diff --git a/.gitignore b/.gitignore index 35a41d63930800b9e8d508bdc4251ef2e881f3db..892b5f00c80bb5552fb41b42e67d90dabf7bdc7e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,13 +12,6 @@ target/ *.iws *.iml *.ipr -.vscode - -# Client -alfa-client/.vscode/ -alfa-client/apps/coverage/ -alfa-client/node/* -alfa-client/temp/* .attach** .factorypath diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..966f07033182549f7aa60700c9930e4bce2acd01 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "angular.enable-strict-mode-prompt": false +} \ No newline at end of file diff --git a/alfa-client/.eslintrc.json b/alfa-client/.eslintrc.json index fcc41f831b508d4b2bb811d29f936fcf3ceab95e..d695a61e5b0d67aa1980d28d45f938a861f9fa73 100644 --- a/alfa-client/.eslintrc.json +++ b/alfa-client/.eslintrc.json @@ -1,43 +1,43 @@ { - "root": true, - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 2018, - "sourceType": "module", - "project": "./tsconfig.*?.json" - }, - "ignorePatterns": ["**/*"], - "plugins": ["@typescript-eslint", "@nx"], - "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/eslint-recommended", - "plugin:@typescript-eslint/recommended", - "prettier" - ], - "rules": { - "@typescript-eslint/explicit-member-accessibility": "off", - "@typescript-eslint/explicit-module-boundary-types": "off", - "@typescript-eslint/no-parameter-properties": "off", - "@nx/enforce-module-boundaries": [ - "error", - { - "enforceBuildableLibDependency": true, - "allow": [], - "depConstraints": [ - { - "sourceTag": "*", - "onlyDependOnLibsWithTags": ["*"] - } - ] - } - ] - }, - "overrides": [ - { - "files": ["*.tsx"], - "rules": { - "@typescript-eslint/no-unused-vars": "off" - } - } - ] + "root": true, + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module", + "project": "./tsconfig.*?.json" + }, + "ignorePatterns": ["**/*"], + "plugins": ["@typescript-eslint", "@nx"], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/eslint-recommended", + "plugin:@typescript-eslint/recommended", + "prettier" + ], + "rules": { + "@typescript-eslint/explicit-member-accessibility": "off", + "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-parameter-properties": "off", + "@nx/enforce-module-boundaries": [ + "error", + { + "enforceBuildableLibDependency": true, + "allow": [], + "depConstraints": [ + { + "sourceTag": "*", + "onlyDependOnLibsWithTags": ["*"] + } + ] + } + ] + }, + "overrides": [ + { + "files": ["*.tsx"], + "rules": { + "@typescript-eslint/no-unused-vars": "off" + } + } + ] } diff --git a/alfa-client/.gitignore b/alfa-client/.gitignore index 075614c3930ad5fdc64fe005bcae36052b6d0954..6116ea3d904921685f791527ee0ec33f12136fa8 100644 --- a/alfa-client/.gitignore +++ b/alfa-client/.gitignore @@ -28,12 +28,13 @@ test-report.xml # IDE - VSCode .vscode/* !.vscode/user-settings.json +!.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json # misc -/.angular/cache +/.angular /.sass-cache /connect.lock /coverage @@ -42,10 +43,9 @@ npm-debug.log yarn-error.log testem.log /typings +/.nx # System Files .DS_Store Thumbs.db -.angular -.nx diff --git a/alfa-client/.prettierignore b/alfa-client/.prettierignore index 6651d46b3eb6643b25dd2d0dd72b2240f63448a8..502fe1afff6f74d63c5c102fe2fd1f02cded9732 100644 --- a/alfa-client/.prettierignore +++ b/alfa-client/.prettierignore @@ -1,5 +1,3 @@ -tmp -/test /build node_modules /package.json @@ -8,3 +6,4 @@ packages/workspace/src/generators/**/files/**/*.json /.nx/cache .angular +/.nx/cache diff --git a/alfa-client/.prettierrc b/alfa-client/.prettierrc index d0c29f49369e7c9cf358b475c1f4ece7a269e7e1..38fff0ae95d8d56c9493bf4d94dbe69d574d573e 100644 --- a/alfa-client/.prettierrc +++ b/alfa-client/.prettierrc @@ -8,7 +8,7 @@ "jsxSingleQuote": true, "quoteProps": "as-needed", "trailingComma": "all", - "singleAttributePerLine": true, + "singleAttributePerLine": false, "htmlWhitespaceSensitivity": "css", "vueIndentScriptAndStyle": false, "proseWrap": "preserve", diff --git a/alfa-client/.vscode/settings.json b/alfa-client/.vscode/settings.json new file mode 100644 index 0000000000000000000000000000000000000000..faa52d3354b8a11143a335b6092b77e99c95bc18 --- /dev/null +++ b/alfa-client/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "angular.enable-strict-mode-prompt": false, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.detectIndentation": false, + "editor.formatOnSave": true, + "editor.formatOnPaste": true, + "editor.formatOnType": true, + "editor.insertSpaces": true, + "editor.tabSize": 2, + "files.encoding": "utf8", + "files.eol": "\n", + "files.trimTrailingWhitespace": true, + "prettier.useTabs": false +} diff --git a/alfa-client/README.md b/alfa-client/README.md index 688707e0cf97fd2e6588db614a1e12573e2dc834..0aeee0637d531b9170ea2b18fd592dfeb5942a97 100644 --- a/alfa-client/README.md +++ b/alfa-client/README.md @@ -14,16 +14,16 @@ Im Anschluß wird das Alfa Frontend über `npm start` gestartet. Hinweise: -* Bei Fehler _npm ERR! Unable to authenticate, need: BASIC realm="Sonatype Nexus Repository Manager"_: - * Prüfen, ob eine Datei _.npmrc_ in _alfa/alfa_ liegt, die den selben Inhalt hat wie die _.npmrc_, die in _apps/alfa-e2e/Jenkinsfile_ angelegt wird. - * Alternative: Die Installation mit dem offiziellen NPM-Repository ausführen: `npm install --registry=https://registry.npmjs.org/` -* Bei nicht nachvollziehbaren Problemen während der Installation kann es helfen, den `node_modules` Ordner und die _package-lock.json_ zu löschen und anschließend erneut zu installieren. -* Prüfen, dass `npm install` die _package-lock.json_ nicht anpasst, wenn das nicht wirklich gewollt ist. Das kann geschehen, wenn ein älteres/neueres NPM verwendet wurde oder ein NPM-Proxy in der _~/.npmrc_ eingetragen ist. +- Bei Fehler _npm ERR! Unable to authenticate, need: BASIC realm="Sonatype Nexus Repository Manager"_: + - Prüfen, ob eine Datei _.npmrc_ in _alfa/alfa_ liegt, die den selben Inhalt hat wie die _.npmrc_, die in _apps/alfa-e2e/Jenkinsfile_ angelegt wird. + - Alternative: Die Installation mit dem offiziellen NPM-Repository ausführen: `npm install --registry=https://registry.npmjs.org/` +- Bei nicht nachvollziehbaren Problemen während der Installation kann es helfen, den `node_modules` Ordner und die _package-lock.json_ zu löschen und anschließend erneut zu installieren. +- Prüfen, dass `npm install` die _package-lock.json_ nicht anpasst, wenn das nicht wirklich gewollt ist. Das kann geschehen, wenn ein älteres/neueres NPM verwendet wurde oder ein NPM-Proxy in der _~/.npmrc_ eingetragen ist. ## Jest und SonarQube -* Parameter testResultsProcessor, collectCoverage, coverageReporters führen zu _Unknown option_ warnings während jeden Tests, wenn sie in der jeweiligen _jest.config.ts_ definiert sind. Werden sie dagegen als CLI Parameter beim Start der Tests übergeben, wird keine Warnung produziert. -* Es können mehrere Tests parallel laufen mittel `nx run-many --target=test --parallel 8`. Tests sollten dann nicht zusätzlich mit Jest's _maxWorkers_ Parameter parallelisiert werden. +- Parameter testResultsProcessor, collectCoverage, coverageReporters führen zu _Unknown option_ warnings während jeden Tests, wenn sie in der jeweiligen _jest.config.ts_ definiert sind. Werden sie dagegen als CLI Parameter beim Start der Tests übergeben, wird keine Warnung produziert. +- Es können mehrere Tests parallel laufen mittel `nx run-many --target=test --parallel 8`. Tests sollten dann nicht zusätzlich mit Jest's _maxWorkers_ Parameter parallelisiert werden. ## Docker build @@ -34,6 +34,7 @@ bin/nx-build-base.sh ``` Anwendungsimage - wird in der Regel vom Jenkins gebaut. + - APPNAME: Name der App im Verzeichnis apps/ - Versionierung steuert Jenkins - build-arg CONFIGURATION steuert production build @@ -41,4 +42,3 @@ Anwendungsimage - wird in der Regel vom Jenkins gebaut. ``` docker buildx build --push --platform linux/amd64 --tag docker.ozg-sh.de/APPNAME:x.x.x --build-arg CONFIGURATION=production -f apps/APPNAME/Dockerfile . ``` - diff --git a/alfa-client/apps/alfa-e2e/.eslintrc.json b/alfa-client/apps/alfa-e2e/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/apps/alfa-e2e/.eslintrc.json +++ b/alfa-client/apps/alfa-e2e/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/apps/alfa-e2e/Jenkinsfile b/alfa-client/apps/alfa-e2e/Jenkinsfile index 05098bc162d6dc85dea6ed29bf72c71bdfd75616..18cd45748722fa9b6c1dd723af62878744e1b819 100644 --- a/alfa-client/apps/alfa-e2e/Jenkinsfile +++ b/alfa-client/apps/alfa-e2e/Jenkinsfile @@ -753,7 +753,11 @@ Map createUserFromFixture(Map userFixture) { "password" : userFixture.password, "first_name": userFixture.get("firstName", ""), "last_name" : userFixture.get("lastName", ""), - "email" : userFixture.get("email", "")] + "email" : userFixture.get("email", ""), + "initials" : userFixture.initials, + "dataTestId" : userFixture.dataTestId, + "clientRoles" : userFixture.clientRoles, + "groups" : userFixture.groups] } String getKeycloakAccessToken(String realm) { diff --git a/alfa-client/apps/alfa-e2e/cypress-ci-einheitlicher-ansprechpartner.config.ts b/alfa-client/apps/alfa-e2e/cypress-ci-einheitlicher-ansprechpartner.config.ts index 464428138059c10708a6ff1e3cd707ec731578c0..c6848595db0c01e5c4304037c2c630cc61217a1b 100644 --- a/alfa-client/apps/alfa-e2e/cypress-ci-einheitlicher-ansprechpartner.config.ts +++ b/alfa-client/apps/alfa-e2e/cypress-ci-einheitlicher-ansprechpartner.config.ts @@ -6,20 +6,20 @@ const cypressConfig = require('./cypress-ci-einheitlicher-ansprechpartner.json') const cypressEvents = require('./src/support/cypress-tasks.ts'); export default defineConfig({ - e2e: { - ...nxE2EPreset(__dirname), - ...cypressConfig, - setupNodeEvents(on, config) { - return cypressEvents(on, config); - }, - }, - retries: { - experimentalStrategy: 'detect-flake-and-pass-on-threshold', - experimentalOptions: { - maxRetries: 2, - passesRequired: 1, - }, - openMode: true, - runMode: true, - }, + e2e: { + ...nxE2EPreset(__dirname), + ...cypressConfig, + setupNodeEvents(on, config) { + return cypressEvents(on, config); + }, + }, + retries: { + experimentalStrategy: 'detect-flake-and-pass-on-threshold', + experimentalOptions: { + maxRetries: 2, + passesRequired: 1, + }, + openMode: true, + runMode: true, + }, }); diff --git a/alfa-client/apps/alfa-e2e/cypress-ci-main-tests.config.ts b/alfa-client/apps/alfa-e2e/cypress-ci-main-tests.config.ts index daf52b990285916f94b2102e4c022be5a177fec2..debc5e3e19864e0afbd6b3376b24aec1be23d3c4 100644 --- a/alfa-client/apps/alfa-e2e/cypress-ci-main-tests.config.ts +++ b/alfa-client/apps/alfa-e2e/cypress-ci-main-tests.config.ts @@ -6,20 +6,20 @@ const cypressConfig = require('./cypress-ci-main-tests.json'); const cypressEvents = require('./src/support/cypress-tasks.ts'); export default defineConfig({ - e2e: { - ...nxE2EPreset(__dirname), - ...cypressConfig, - setupNodeEvents(on, config) { - return cypressEvents(on, config); - }, - }, - retries: { - experimentalStrategy: 'detect-flake-and-pass-on-threshold', - experimentalOptions: { - maxRetries: 2, - passesRequired: 1, - }, - openMode: true, - runMode: true, - }, + e2e: { + ...nxE2EPreset(__dirname), + ...cypressConfig, + setupNodeEvents(on, config) { + return cypressEvents(on, config); + }, + }, + retries: { + experimentalStrategy: 'detect-flake-and-pass-on-threshold', + experimentalOptions: { + maxRetries: 2, + passesRequired: 1, + }, + openMode: true, + runMode: true, + }, }); diff --git a/alfa-client/apps/alfa-e2e/cypress-ci.json b/alfa-client/apps/alfa-e2e/cypress-ci.json index 26599280794ad6d4a2eaf8ba98627211956e814d..b7768dbc3af38c4282d24c58f396f65d2ca20f3b 100644 --- a/alfa-client/apps/alfa-e2e/cypress-ci.json +++ b/alfa-client/apps/alfa-e2e/cypress-ci.json @@ -1,22 +1,22 @@ { - "env": { - "database": "vorgang-manager-database", - "keycloakClient": "alfa" - }, - "fileServerFolder": ".", - "fixturesFolder": "./src/fixtures", - "modifyObstructiveCode": false, - "video": true, - "chromeWebSecurity": false, - "reporter": "../../node_modules/cypress-mochawesome-reporter", - "defaultCommandTimeout": 10000, - "supportFile": "./src/support/e2e.ts", - "testIsolation": false, - "reporterOptions": { - "html": false, - "json": true, - "quite": true, - "reportFilename": "report", - "overwrite": false - } + "env": { + "database": "vorgang-manager-database", + "keycloakClient": "alfa" + }, + "fileServerFolder": ".", + "fixturesFolder": "./src/fixtures", + "modifyObstructiveCode": false, + "video": true, + "chromeWebSecurity": false, + "reporter": "../../node_modules/cypress-mochawesome-reporter", + "defaultCommandTimeout": 10000, + "supportFile": "./src/support/e2e.ts", + "testIsolation": false, + "reporterOptions": { + "html": false, + "json": true, + "quite": true, + "reportFilename": "report", + "overwrite": false + } } diff --git a/alfa-client/apps/alfa-e2e/cypress.config.json b/alfa-client/apps/alfa-e2e/cypress.config.json index 2eaa211f04655dea29923a5a9228dc5a98dcc19b..51aed25856700ddaa535421360ac106f45ca759a 100644 --- a/alfa-client/apps/alfa-e2e/cypress.config.json +++ b/alfa-client/apps/alfa-e2e/cypress.config.json @@ -1,39 +1,39 @@ { - "baseUrl": "http://localhost:4300", - "env": { - "dbUrl": "mongodb://localhost:27018", - "database": "test", - "keycloakRealm": "by-e2e-local-dev", - "keycloakUrl": "https://sso.dev.by.ozg-cloud.de/", - "keycloakClient": "alfa", - "sabineUuid": "2ccf0c13-da74-4516-ae3d-f46d30e8ec0c", - "search": { - "url": "http://localhost:9200", - "index": "e2e-test-index", - "user": "elastic", - "password": "password" - }, - "userManager": { - "dbUrl": "mongodb://localhost:27018", - "database": "usermanager" - } - }, - "fileServerFolder": ".", - "fixturesFolder": "./src/fixtures", - "video": false, - "videosFolder": "./reports/videos", - "screenshotsFolder": "./reports/screenshots", - "chromeWebSecurity": false, - "reporter": "../../node_modules/cypress-mochawesome-reporter", - "defaultCommandTimeout": 10000, - "specPattern": "src/e2e/**/*.cy.{js,jsx,ts,tsx}", - "supportFile": "src/support/e2e.ts", - "testIsolation": false, - "reporterOptions": { - "html": false, - "json": true, - "reportDir": "./reports/mochawesome-report", - "reportFilename": "report", - "overwrite": true - } + "baseUrl": "http://localhost:4300", + "env": { + "dbUrl": "mongodb://localhost:27018", + "database": "test", + "keycloakRealm": "by-e2e-local-dev", + "keycloakUrl": "https://sso.dev.by.ozg-cloud.de/", + "keycloakClient": "alfa", + "sabineUuid": "2ccf0c13-da74-4516-ae3d-f46d30e8ec0c", + "search": { + "url": "http://localhost:9200", + "index": "e2e-test-index", + "user": "elastic", + "password": "password" + }, + "userManager": { + "dbUrl": "mongodb://localhost:27018", + "database": "usermanager" + } + }, + "fileServerFolder": ".", + "fixturesFolder": "./src/fixtures", + "video": false, + "videosFolder": "./reports/videos", + "screenshotsFolder": "./reports/screenshots", + "chromeWebSecurity": false, + "reporter": "../../node_modules/cypress-mochawesome-reporter", + "defaultCommandTimeout": 10000, + "specPattern": "src/e2e/**/*.cy.{js,jsx,ts,tsx}", + "supportFile": "src/support/e2e.ts", + "testIsolation": false, + "reporterOptions": { + "html": false, + "json": true, + "reportDir": "./reports/mochawesome-report", + "reportFilename": "report", + "overwrite": true + } } diff --git a/alfa-client/apps/alfa-e2e/cypress.config.ts b/alfa-client/apps/alfa-e2e/cypress.config.ts index a72d7976359485c9e3da118e39d8cc8dc818c18e..1e57f65df3ed4318fbab8833bc800aed1be41d2e 100644 --- a/alfa-client/apps/alfa-e2e/cypress.config.ts +++ b/alfa-client/apps/alfa-e2e/cypress.config.ts @@ -5,20 +5,20 @@ const cypressConfig = require('./cypress.config.json'); const cypressEvents = require('./src/support/cypress-tasks.ts'); export default defineConfig({ - e2e: { - ...nxE2EPreset(__dirname), - ...cypressConfig, - setupNodeEvents(on, config) { - return cypressEvents(on, config); - }, - }, - retries: { - experimentalStrategy: 'detect-flake-and-pass-on-threshold', - experimentalOptions: { - maxRetries: 2, - passesRequired: 1, - }, - openMode: true, - runMode: true, - }, + e2e: { + ...nxE2EPreset(__dirname), + ...cypressConfig, + setupNodeEvents(on, config) { + return cypressEvents(on, config); + }, + }, + retries: { + experimentalStrategy: 'detect-flake-and-pass-on-threshold', + experimentalOptions: { + maxRetries: 2, + passesRequired: 1, + }, + openMode: true, + runMode: true, + }, }); diff --git a/alfa-client/apps/alfa-e2e/docker-compose.yml b/alfa-client/apps/alfa-e2e/docker-compose.yml index 905f38a5ab41729bf9207c0d97e371a8ffe09118..b13eadb37a019867a2dfa5e64e447dc2da1ae332 100644 --- a/alfa-client/apps/alfa-e2e/docker-compose.yml +++ b/alfa-client/apps/alfa-e2e/docker-compose.yml @@ -104,7 +104,11 @@ services: soft: 65536 hard: 65536 healthcheck: - test: ["CMD-SHELL", "curl -s 'http://localhost:9200/_cat/health?h=status' | egrep -q '(green|yellow)'"] + test: + [ + 'CMD-SHELL', + "curl -s 'http://localhost:9200/_cat/health?h=status' | egrep -q '(green|yellow)'", + ] interval: 10s timeout: 10s retries: 5 @@ -140,4 +144,4 @@ services: image: thiht/smocker ports: - 7080:8080 - - 7081:8081 \ No newline at end of file + - 7081:8081 diff --git a/alfa-client/apps/alfa-e2e/keycloak/imports/keycloak-realm-okd-export.json b/alfa-client/apps/alfa-e2e/keycloak/imports/keycloak-realm-okd-export.json index 1b98bb04746aac76b8052d98f67e1f5523ba2a88..ef15a32eddb463e28aa33d06145671ecdea5433b 100644 --- a/alfa-client/apps/alfa-e2e/keycloak/imports/keycloak-realm-okd-export.json +++ b/alfa-client/apps/alfa-e2e/keycloak/imports/keycloak-realm-okd-export.json @@ -138,10 +138,7 @@ "composite": true, "composites": { "client": { - "realm-management": [ - "query-groups", - "query-users" - ] + "realm-management": ["query-groups", "query-users"] } }, "clientRole": true, @@ -245,9 +242,7 @@ "composite": true, "composites": { "client": { - "realm-management": [ - "query-clients" - ] + "realm-management": ["query-clients"] } }, "clientRole": true, @@ -305,9 +300,7 @@ "composite": true, "composites": { "client": { - "account": [ - "view-consent" - ] + "account": ["view-consent"] } }, "clientRole": true, @@ -366,9 +359,7 @@ "composite": true, "composites": { "client": { - "account": [ - "manage-account-links" - ] + "account": ["manage-account-links"] } }, "clientRole": true, @@ -379,27 +370,17 @@ } }, "groups": [], - "defaultRoles": [ - "offline_access", - "uma_authorization" - ], - "requiredCredentials": [ - "password" - ], + "defaultRoles": ["offline_access", "uma_authorization"], + "requiredCredentials": ["password"], "otpPolicyType": "totp", "otpPolicyAlgorithm": "HmacSHA1", "otpPolicyInitialCounter": 0, "otpPolicyDigits": 6, "otpPolicyLookAheadWindow": 1, "otpPolicyPeriod": 30, - "otpSupportedApplications": [ - "FreeOTP", - "Google Authenticator" - ], + "otpSupportedApplications": ["FreeOTP", "Google Authenticator"], "webAuthnPolicyRpEntityName": "keycloak", - "webAuthnPolicySignatureAlgorithms": [ - "ES256" - ], + "webAuthnPolicySignatureAlgorithms": ["ES256"], "webAuthnPolicyRpId": "", "webAuthnPolicyAttestationConveyancePreference": "not specified", "webAuthnPolicyAuthenticatorAttachment": "not specified", @@ -409,9 +390,7 @@ "webAuthnPolicyAvoidSameAuthenticatorRegister": false, "webAuthnPolicyAcceptableAaguids": [], "webAuthnPolicyPasswordlessRpEntityName": "keycloak", - "webAuthnPolicyPasswordlessSignatureAlgorithms": [ - "ES256" - ], + "webAuthnPolicyPasswordlessSignatureAlgorithms": ["ES256"], "webAuthnPolicyPasswordlessRpId": "", "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified", "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified", @@ -423,18 +402,14 @@ "scopeMappings": [ { "clientScope": "offline_access", - "roles": [ - "offline_access" - ] + "roles": ["offline_access"] } ], "clientScopeMappings": { "account": [ { "client": "account-console", - "roles": [ - "manage-account" - ] + "roles": ["manage-account"] } ] }, @@ -450,13 +425,8 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "**********", - "defaultRoles": [ - "view-profile", - "manage-account" - ], - "redirectUris": [ - "/realms/okd/account/*" - ], + "defaultRoles": ["view-profile", "manage-account"], + "redirectUris": ["/realms/okd/account/*"], "webOrigins": [], "notBefore": 0, "bearerOnly": false, @@ -472,19 +442,8 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "role_list", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] }, { "id": "3b6a7e2a-40c2-44f7-93e0-3b4bd59e6f86", @@ -497,9 +456,7 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "**********", - "redirectUris": [ - "/realms/okd/account/*" - ], + "redirectUris": ["/realms/okd/account/*"], "webOrigins": [], "notBefore": 0, "bearerOnly": false, @@ -527,19 +484,8 @@ "config": {} } ], - "defaultClientScopes": [ - "web-origins", - "role_list", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] }, { "id": "4e94d1b2-996d-4e58-ac61-eb551def3926", @@ -566,19 +512,8 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "role_list", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] }, { "id": "f528990c-0e1e-4ff2-96a3-3b160b2da6f4", @@ -605,19 +540,8 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "role_list", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] }, { "id": "07ea0dd0-2c0b-4ae8-baa5-b6d4ff007721", @@ -629,12 +553,8 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "**********", - "redirectUris": [ - "http://localhost:8080/*" - ], - "webOrigins": [ - "http://localhost:8080" - ], + "redirectUris": ["http://localhost:8080/*"], + "webOrigins": ["http://localhost:8080"], "notBefore": 0, "bearerOnly": false, "consentRequired": false, @@ -652,19 +572,8 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": true, "nodeReRegistrationTimeout": -1, - "defaultClientScopes": [ - "web-origins", - "role_list", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] }, { "id": "2e48205f-04d8-4436-a352-fb71f5d10f42", @@ -691,19 +600,8 @@ "authenticationFlowBindingOverrides": {}, "fullScopeAllowed": false, "nodeReRegistrationTimeout": 0, - "defaultClientScopes": [ - "web-origins", - "role_list", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] }, { "id": "64028d8a-1b15-462f-a6d5-f94860ffc46b", @@ -716,12 +614,8 @@ "alwaysDisplayInConsole": false, "clientAuthenticatorType": "client-secret", "secret": "**********", - "redirectUris": [ - "/admin/okd/console/*" - ], - "webOrigins": [ - "+" - ], + "redirectUris": ["/admin/okd/console/*"], + "webOrigins": ["+"], "notBefore": 0, "bearerOnly": false, "consentRequired": false, @@ -755,19 +649,8 @@ } } ], - "defaultClientScopes": [ - "web-origins", - "role_list", - "profile", - "roles", - "email" - ], - "optionalClientScopes": [ - "address", - "phone", - "offline_access", - "microprofile-jwt" - ] + "defaultClientScopes": ["web-origins", "role_list", "profile", "roles", "email"], + "optionalClientScopes": ["address", "phone", "offline_access", "microprofile-jwt"] } ], "clientScopes": [ @@ -1255,19 +1138,8 @@ ] } ], - "defaultDefaultClientScopes": [ - "web-origins", - "profile", - "email", - "role_list", - "roles" - ], - "defaultOptionalClientScopes": [ - "microprofile-jwt", - "address", - "offline_access", - "phone" - ], + "defaultDefaultClientScopes": ["web-origins", "profile", "email", "role_list", "roles"], + "defaultOptionalClientScopes": ["microprofile-jwt", "address", "offline_access", "phone"], "browserSecurityHeaders": { "contentSecurityPolicyReportOnly": "", "xContentTypeOptions": "nosniff", @@ -1279,9 +1151,7 @@ }, "smtpServer": {}, "eventsEnabled": false, - "eventsListeners": [ - "jboss-logging" - ], + "eventsListeners": ["jboss-logging"], "enabledEventTypes": [], "adminEventsEnabled": false, "adminEventsDetailsEnabled": false, @@ -1296,9 +1166,7 @@ "subType": "authenticated", "subComponents": {}, "config": { - "allow-default-scopes": [ - "true" - ] + "allow-default-scopes": ["true"] } }, { @@ -1308,9 +1176,7 @@ "subType": "anonymous", "subComponents": {}, "config": { - "max-clients": [ - "200" - ] + "max-clients": ["200"] } }, { @@ -1355,9 +1221,7 @@ "subType": "anonymous", "subComponents": {}, "config": { - "allow-default-scopes": [ - "true" - ] + "allow-default-scopes": ["true"] } }, { @@ -1386,12 +1250,8 @@ "subType": "anonymous", "subComponents": {}, "config": { - "host-sending-registration-request-must-match": [ - "true" - ], - "client-uris-must-match": [ - "true" - ] + "host-sending-registration-request-must-match": ["true"], + "client-uris-must-match": ["true"] } } ], @@ -1402,9 +1262,7 @@ "providerId": "rsa-generated", "subComponents": {}, "config": { - "priority": [ - "100" - ] + "priority": ["100"] } }, { @@ -1413,9 +1271,7 @@ "providerId": "aes-generated", "subComponents": {}, "config": { - "priority": [ - "100" - ] + "priority": ["100"] } }, { @@ -1424,12 +1280,8 @@ "providerId": "hmac-generated", "subComponents": {}, "config": { - "priority": [ - "100" - ], - "algorithm": [ - "HS256" - ] + "priority": ["100"], + "algorithm": ["HS256"] } } ] @@ -2060,4 +1912,4 @@ "attributes": {}, "keycloakVersion": "12.0.1", "userManagedAccessAllowed": false -} \ No newline at end of file +} diff --git a/alfa-client/apps/alfa-e2e/project.json b/alfa-client/apps/alfa-e2e/project.json index 4c236c9069858a33fd56b162238e90ea673ec68f..515079be4fc2f5f162e52e2cffdd7f5298a82bc4 100644 --- a/alfa-client/apps/alfa-e2e/project.json +++ b/alfa-client/apps/alfa-e2e/project.json @@ -1,34 +1,31 @@ { - "name": "alfa-e2e", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "apps/alfa-e2e/src", - "projectType": "application", - "targets": { - "e2e": { - "executor": "@nx/cypress:cypress", - "options": { - "cypressConfig": "apps/alfa-e2e/cypress.config.ts", - "tsConfig": "apps/alfa-e2e/tsconfig.e2e.json", - "devServerTarget": "alfa:serve", - "testingType": "e2e" - }, - "configurations": { - "production": { - "devServerTarget": "alfa:serve:production" - } - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/alfa-e2e/**/*.{js,ts}", - "apps/alfa-e2e/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [], - "implicitDependencies": ["alfa"] + "name": "alfa-e2e", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "apps/alfa-e2e/src", + "projectType": "application", + "targets": { + "e2e": { + "executor": "@nx/cypress:cypress", + "options": { + "cypressConfig": "apps/alfa-e2e/cypress.config.ts", + "tsConfig": "apps/alfa-e2e/tsconfig.e2e.json", + "devServerTarget": "alfa:serve", + "testingType": "e2e" + }, + "configurations": { + "production": { + "devServerTarget": "alfa:serve:production" + } + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["apps/alfa-e2e/**/*.{js,ts}", "apps/alfa-e2e/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [], + "implicitDependencies": ["alfa"] } diff --git a/alfa-client/apps/alfa-e2e/src/components/attachment/attachment.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/attachment/attachment.e2e.component.ts index 2e25bcf2492b25233140042d933dcf8b718c5963..005abef8cb58c8fb185e7b7855173fae2e27f5c7 100644 --- a/alfa-client/apps/alfa-e2e/src/components/attachment/attachment.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/attachment/attachment.e2e.component.ts @@ -24,52 +24,49 @@ import { convertToDataTestId } from '../../support/tech.util'; export class AttachmentContainerE2EComponent { + private readonly locatorFileUploadInput: string = '-file-upload-input'; + private readonly attachmentList: AttachmentListE2EComponent = new AttachmentListE2EComponent(); - private readonly locatorFileUploadInput: string = '-file-upload-input'; - private readonly attachmentList: AttachmentListE2EComponent = new AttachmentListE2EComponent(); + public getList(): AttachmentListE2EComponent { + return this.attachmentList; + } - public getList(): AttachmentListE2EComponent { - return this.attachmentList; - } - - public getUploadInput() { - return cy.getTestElement(this.locatorFileUploadInput); - } + public getUploadInput() { + return cy.getTestElement(this.locatorFileUploadInput); + } } export class AttachmentListE2EComponent { + private readonly locatorRoot: string = 'file-list'; - private readonly locatorRoot: string = 'file-list'; - - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getItem(fileName: string): AttachmentE2EItem { - return new AttachmentE2EItem(fileName); - } + public getItem(fileName: string): AttachmentE2EItem { + return new AttachmentE2EItem(fileName); + } } class AttachmentE2EItem { + private readonly locatorDeleteButton: string = 'delete-file-button'; + private readonly locatorDownloadButton: string = 'download-file-button'; - private readonly locatorDeleteButton: string = 'delete-file-button'; - private readonly locatorDownloadButton: string = 'download-file-button'; + private locatorRoot: string; - private locatorRoot: string; + constructor(private fileName: string) { + this.locatorRoot = convertToDataTestId(this.fileName) + '-file-item'; + } - constructor(private fileName: string) { - this.locatorRoot = convertToDataTestId(this.fileName) + '-file-item'; - } + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getDeleteButton() { + return this.getRoot().findTestElementWithClass(this.locatorDeleteButton); + } - public getDeleteButton() { - return this.getRoot().findTestElementWithClass(this.locatorDeleteButton); - } - - public getDownloadButton() { - return this.getRoot().findTestElementWithClass(this.locatorDownloadButton); - } -} \ No newline at end of file + public getDownloadButton() { + return this.getRoot().findTestElementWithClass(this.locatorDownloadButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/basic-dialog/basic-dialog.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/basic-dialog/basic-dialog.e2e.component.ts index f9e52e454e61fe2e28f916fa1b30bbec8bc5f19c..5e39f3bcb8b203487d7411793c11dc2831467acc 100644 --- a/alfa-client/apps/alfa-e2e/src/components/basic-dialog/basic-dialog.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/basic-dialog/basic-dialog.e2e.component.ts @@ -23,29 +23,28 @@ */ export class BasicDialogE2EComponent { + private readonly locatorHeader: string = 'dialog-header'; + private readonly locatorMessage: string = 'dialog-message'; + private readonly locatorConfirmationButton = 'dialog-confirmation-button'; + private readonly locatorCancelButton = 'dialog-cancel-button'; - private readonly locatorHeader: string = 'dialog-header'; - private readonly locatorMessage: string = 'dialog-message'; - private readonly locatorConfirmationButton = 'dialog-confirmation-button'; - private readonly locatorCancelButton = 'dialog-cancel-button'; + public getHeader() { + return cy.getTestElement(this.locatorHeader); + } - public getHeader() { - return cy.getTestElement(this.locatorHeader); - } + public getHeaderText() { + return this.getHeader().innerText; + } - public getHeaderText() { - return this.getHeader().innerText; - } + public getMessage() { + return cy.getTestElement(this.locatorMessage); + } - public getMessage() { - return cy.getTestElement(this.locatorMessage); - } + public getConfirmationButton() { + return cy.getTestElement(this.locatorConfirmationButton); + } - public getConfirmationButton() { - return cy.getTestElement(this.locatorConfirmationButton); - } - - public getCancelButton() { - return cy.getTestElement(this.locatorCancelButton); - } -} \ No newline at end of file + public getCancelButton() { + return cy.getTestElement(this.locatorCancelButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/buildinfo/buildinfo.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/buildinfo/buildinfo.e2e.component.ts index ac800e912b9ebb198e958fb707de2a43a7a6f66d..955289950104891e3823273e01a1d7d27cdc7d40 100644 --- a/alfa-client/apps/alfa-e2e/src/components/buildinfo/buildinfo.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/buildinfo/buildinfo.e2e.component.ts @@ -22,15 +22,14 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class BuildInfoE2EComponent { + private readonly locatorVersion: string = 'version'; + private readonly locatorBuildTime: string = 'build-time'; - private readonly locatorVersion: string = 'version'; - private readonly locatorBuildTime: string = 'build-time'; + public getVersion() { + return cy.getTestElement(this.locatorVersion); + } - public getVersion() { - return cy.getTestElement(this.locatorVersion); - } - - public getBuildTime() { - return cy.getTestElement(this.locatorBuildTime); - } -} \ No newline at end of file + public getBuildTime() { + return cy.getTestElement(this.locatorBuildTime); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/hint/hint.component.e2e.ts b/alfa-client/apps/alfa-e2e/src/components/hint/hint.component.e2e.ts index 2fa57bd6c27834261c2c0b9778a96e4ac5ea3c41..4904d582f378cd79a169a4b0026931fdeedb9b9d 100644 --- a/alfa-client/apps/alfa-e2e/src/components/hint/hint.component.e2e.ts +++ b/alfa-client/apps/alfa-e2e/src/components/hint/hint.component.e2e.ts @@ -1,13 +1,12 @@ export class HintE2EComponent { + private readonly rootLocator: string = 'hint-container'; + private readonly noOrganisationIdLocator: string = 'no-organisations-einheit-id-hint'; - private readonly rootLocator: string = 'hint-container'; - private readonly noOrganisationIdLocator: string = 'no-organisations-einheit-id-hint'; + public getRoot() { + return cy.getTestElementWithOid(this.rootLocator); + } - public getRoot() { - return cy.getTestElementWithOid(this.rootLocator); - } - - public getNoOrganisationId() { - return this.getRoot().getTestElementWithOid(this.noOrganisationIdLocator); - } + public getNoOrganisationId() { + return this.getRoot().getTestElementWithOid(this.noOrganisationIdLocator); + } } diff --git a/alfa-client/apps/alfa-e2e/src/components/kommentar/kommentar-list.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/kommentar/kommentar-list.e2e.component.ts index 90527f8a50f6c811c009403c29ae5c68408edecd..aaa48221486d791eca042aacf840a082153daf50 100644 --- a/alfa-client/apps/alfa-e2e/src/components/kommentar/kommentar-list.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/kommentar/kommentar-list.e2e.component.ts @@ -26,80 +26,80 @@ import { UserProfileE2EComponent } from '../user-profile/user-profile.component. import { AttachmentContainerE2EComponent } from '../attachment/attachment.e2e.component'; export class KommentareInVorgangE2EComponent { - - readonly locatorHinzufuegenButton: string = 'create-kommentar'; - readonly locatorFormular: string = 'kommentar-formular'; - readonly locatorFormularSpeichernButton: string = 'add-button'; - readonly locatorFormularAbbrechenButton: string = 'cancel-button'; - readonly locatorKommentarList: string = 'kommentar-list-in-vorgang'; - readonly locatorTextInput: string = 'Kommentar-textarea-input'; - readonly locatorTextError: string = 'Kommentar-textarea-error'; - - private readonly attachmentContainer: AttachmentContainerE2EComponent = new AttachmentContainerE2EComponent(); - - - readonly locatorRoot: string = 'kommentar-container-in-vorgang'; - - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } - - public getFormular() { - return cy.getTestElement(this.locatorFormular); - } - - public getHinzufuegenButton() { - return cy.getTestElement(this.locatorHinzufuegenButton); - } - - public getFormularSpeichernButton() { - return cy.getTestElement(this.locatorFormularSpeichernButton); - } - - public getFormularAbbrechenButton() { - return cy.getTestElement(this.locatorFormularAbbrechenButton); - } - - public getKommentarList() { - return cy.getTestElement(this.locatorKommentarList); - } - - public getTextInput() { - return cy.getTestElement(this.locatorTextInput); - } - - public getTextError() { - return cy.getTestElement(this.locatorTextError); - } - - public getKommentar(text: string): KommentarInVorgangE2E { - return new KommentarInVorgangE2E(text); - } - - public getAttachmentContainer(): AttachmentContainerE2EComponent { - return this.attachmentContainer; - } + readonly locatorHinzufuegenButton: string = 'create-kommentar'; + readonly locatorFormular: string = 'kommentar-formular'; + readonly locatorFormularSpeichernButton: string = 'add-button'; + readonly locatorFormularAbbrechenButton: string = 'cancel-button'; + readonly locatorKommentarList: string = 'kommentar-list-in-vorgang'; + readonly locatorTextInput: string = 'Kommentar-textarea-input'; + readonly locatorTextError: string = 'Kommentar-textarea-error'; + + private readonly attachmentContainer: AttachmentContainerE2EComponent = + new AttachmentContainerE2EComponent(); + + readonly locatorRoot: string = 'kommentar-container-in-vorgang'; + + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } + + public getFormular() { + return cy.getTestElement(this.locatorFormular); + } + + public getHinzufuegenButton() { + return cy.getTestElement(this.locatorHinzufuegenButton); + } + + public getFormularSpeichernButton() { + return cy.getTestElement(this.locatorFormularSpeichernButton); + } + + public getFormularAbbrechenButton() { + return cy.getTestElement(this.locatorFormularAbbrechenButton); + } + + public getKommentarList() { + return cy.getTestElement(this.locatorKommentarList); + } + + public getTextInput() { + return cy.getTestElement(this.locatorTextInput); + } + + public getTextError() { + return cy.getTestElement(this.locatorTextError); + } + + public getKommentar(text: string): KommentarInVorgangE2E { + return new KommentarInVorgangE2E(text); + } + + public getAttachmentContainer(): AttachmentContainerE2EComponent { + return this.attachmentContainer; + } } -export class KommentarInVorgangE2E {//TODO: Rename to KommentarInVorgangE2EComponent +export class KommentarInVorgangE2E { + //TODO: Rename to KommentarInVorgangE2EComponent - private readonly locatorCreatedAt: string = 'kommentar-created-at'; + private readonly locatorCreatedAt: string = 'kommentar-created-at'; - private readonly locatorRoot: string; + private readonly locatorRoot: string; - constructor(private text: string) { - this.locatorRoot = 'kommentar-item-' + convertToDataTestId(this.text); - } + constructor(private text: string) { + this.locatorRoot = 'kommentar-item-' + convertToDataTestId(this.text); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getUserProfile(): UserProfileE2EComponent { - return new UserProfileE2EComponent(this.locatorRoot); - } + public getUserProfile(): UserProfileE2EComponent { + return new UserProfileE2EComponent(this.locatorRoot); + } - public getCreatedAt() { - return cy.getTestElement(this.locatorCreatedAt); - } -} \ No newline at end of file + public getCreatedAt() { + return cy.getTestElement(this.locatorCreatedAt); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/navigation/navigation.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/navigation/navigation.e2e.component.ts index 0f3653e033f8680344e9238bcbb1068dde00c6d6..61ed796a5a43f0cd00c2c13ce8f78970e590b4c6 100644 --- a/alfa-client/apps/alfa-e2e/src/components/navigation/navigation.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/navigation/navigation.e2e.component.ts @@ -22,26 +22,25 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class NavigationE2EComponent { + private readonly alleFilterToggleButton: string = 'alle-filter-toggle-button'; + private readonly meineVorgaengeToggleButton: string = 'meine-vorgaenge-filter-toggle-button'; + private readonly nichtZugewiesenToggleButton: string = 'nicht-zugewiesen-filter-toggle-button'; - private readonly alleFilterToggleButton: string = 'alle-filter-toggle-button'; - private readonly meineVorgaengeToggleButton: string = 'meine-vorgaenge-filter-toggle-button'; - private readonly nichtZugewiesenToggleButton: string = 'nicht-zugewiesen-filter-toggle-button'; + private readonly locatorRoot: string = 'navigation'; - private readonly locatorRoot: string = 'navigation'; + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getAlleFilter() { + return cy.getTestElement(this.alleFilterToggleButton); + } - public getAlleFilter() { - return cy.getTestElement(this.alleFilterToggleButton); - } + public getMeineVorgaengeFilter() { + return cy.getTestElement(this.meineVorgaengeToggleButton); + } - public getMeineVorgaengeFilter() { - return cy.getTestElement(this.meineVorgaengeToggleButton); - } - - public getNichtZugewiesenFilter() { - return cy.getTestElement(this.nichtZugewiesenToggleButton); - } -} \ No newline at end of file + public getNichtZugewiesenFilter() { + return cy.getTestElement(this.nichtZugewiesenToggleButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail-formular.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail-formular.e2e.component.ts index da861be582054056a1ee5ccc42ec1fa8a37715d9..c07133e490225b77304560ba347d16cfb4645fe1 100644 --- a/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail-formular.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail-formular.e2e.component.ts @@ -24,66 +24,64 @@ import { AttachmentContainerE2EComponent } from '../attachment/attachment.e2e.component'; export class PostfachMailFormularE2EComponent { - - private readonly locatorEmpfaenger: string = 'postfach-empfaenger'; - private readonly locatorBetreff: string = 'Betreff-text-input'; - private readonly locatorBetreffError: string = 'Betreff-text-error'; - private readonly locatorText: string = 'Text-textarea-input'; - private readonly locatorTextError: string = 'Text-textarea-error'; - private readonly locatorSendButton: string = 'postfach-send-button'; - - private readonly replyOption: ReplyOption = new ReplyOption(); - private readonly attachmentContainer: AttachmentContainerE2EComponent = new AttachmentContainerE2EComponent(); - - public getEmpfaenger() { - return cy.getTestElement(this.locatorEmpfaenger); - } - - public getBetreff() { - return cy.getTestElement(this.locatorBetreff); - } - - public getBetreffError() { - return cy.getTestElement(this.locatorBetreffError); - } - - public getText() { - return cy.getTestElement(this.locatorText); - } - - public getTextError() { - return cy.getTestElement(this.locatorTextError); - } - - public getSendButton() { - return cy.getTestElement(this.locatorSendButton); - } - - public getReplyOption(): ReplyOption { - return this.replyOption; - } - - public getAttachmentContainer(): AttachmentContainerE2EComponent { - return this.attachmentContainer; - } - + private readonly locatorEmpfaenger: string = 'postfach-empfaenger'; + private readonly locatorBetreff: string = 'Betreff-text-input'; + private readonly locatorBetreffError: string = 'Betreff-text-error'; + private readonly locatorText: string = 'Text-textarea-input'; + private readonly locatorTextError: string = 'Text-textarea-error'; + private readonly locatorSendButton: string = 'postfach-send-button'; + + private readonly replyOption: ReplyOption = new ReplyOption(); + private readonly attachmentContainer: AttachmentContainerE2EComponent = + new AttachmentContainerE2EComponent(); + + public getEmpfaenger() { + return cy.getTestElement(this.locatorEmpfaenger); + } + + public getBetreff() { + return cy.getTestElement(this.locatorBetreff); + } + + public getBetreffError() { + return cy.getTestElement(this.locatorBetreffError); + } + + public getText() { + return cy.getTestElement(this.locatorText); + } + + public getTextError() { + return cy.getTestElement(this.locatorTextError); + } + + public getSendButton() { + return cy.getTestElement(this.locatorSendButton); + } + + public getReplyOption(): ReplyOption { + return this.replyOption; + } + + public getAttachmentContainer(): AttachmentContainerE2EComponent { + return this.attachmentContainer; + } } export class ReplyOption { + private readonly locatorRoot: string = 'postfach-reply-option'; + private readonly locatorPossible: string = 'POSSIBLE-enum-item'; + private readonly locatorForbidden: string = 'FORBIDDEN-enum-item'; - private readonly locatorRoot: string = 'postfach-reply-option'; - private readonly locatorPossible: string = 'POSSIBLE-enum-item'; - private readonly locatorForbidden: string = 'FORBIDDEN-enum-item'; - - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getPossibleOption() { - return cy.getTestElement(this.locatorPossible); - } + public getPossibleOption() { + return cy.getTestElement(this.locatorPossible); + } - public getForbiddenOption() { - return cy.getTestElement(this.locatorForbidden); - } -} \ No newline at end of file + public getForbiddenOption() { + return cy.getTestElement(this.locatorForbidden); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail-subnavigation.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail-subnavigation.e2e.component.ts index 72e1964588de03b0d14c7f3a771ad87dfd5a8306..8e95057c4f479156e3d833a5c9bba24504c18127 100644 --- a/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail-subnavigation.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail-subnavigation.e2e.component.ts @@ -22,10 +22,9 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class PostfachMailSubnavigation { + private readonly locatorBackButton: string = 'back-button'; - private readonly locatorBackButton: string = 'back-button'; - - public getBackButton() { - return cy.getTestElement(this.locatorBackButton); - } -} \ No newline at end of file + public getBackButton() { + return cy.getTestElement(this.locatorBackButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail.e2e.component.ts index 8dac3c2d81e93ba6b52e4811b9c9f783831dada1..c57f6ad8477afa7f6e7d79de4c378dedc8f2271f 100644 --- a/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/postfach/postfach-mail.e2e.component.ts @@ -26,115 +26,116 @@ import { AttachmentContainerE2EComponent } from '../attachment/attachment.e2e.co import { UserProfileE2EComponent } from '../user-profile/user-profile.component.e2e'; export class PostfachMailE2EComponent { - - private readonly createMailButtonWithText: string = 'create-mail-button-with-text'; - private readonly createMailButtonWithoutText: string = 'create-mail-button-without-text'; - private readonly list: string = 'postfach-mail-list'; - private readonly noPostfachText: string = 'no-postfach-text'; - private readonly attachments: string = 'postfach-nachricht-attachments-container'; - private readonly downloadButtonWithIcon: string = 'postfach-pdf-export-button'; - private readonly downloadButtonWithLabel: string = 'postfach-pdf-export-label-button'; - - private readonly locatorRoot: string = 'postfach-nachrichten-container-in-vorgang'; - - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } - - public getCreateButtonWithText() { - return cy.getTestElement(this.createMailButtonWithText); - } - - public getCreateButtonWithoutText() { - return cy.getTestElement(this.createMailButtonWithoutText); - } - - public getList() { - return cy.getTestElement(this.list); - } - - public getNoPostfachText() { - return cy.getTestElement(this.noPostfachText); - } - - public getListItem(subject: string): PostfachMailListItem { - return new PostfachMailListItem(subject); - } - - public getAttachments() { - return cy.getTestElement(this.attachments); - } - - public getDownloadButtonWithIcon() { - return cy.getTestElement(this.downloadButtonWithIcon); - } - - public getDownloadButtonWithLabel() { - return cy.getTestElement(this.downloadButtonWithLabel); - } + private readonly createMailButtonWithText: string = 'create-mail-button-with-text'; + private readonly createMailButtonWithoutText: string = 'create-mail-button-without-text'; + private readonly list: string = 'postfach-mail-list'; + private readonly noPostfachText: string = 'no-postfach-text'; + private readonly attachments: string = 'postfach-nachricht-attachments-container'; + private readonly downloadButtonWithIcon: string = 'postfach-pdf-export-button'; + private readonly downloadButtonWithLabel: string = 'postfach-pdf-export-label-button'; + + private readonly locatorRoot: string = 'postfach-nachrichten-container-in-vorgang'; + + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } + + public getCreateButtonWithText() { + return cy.getTestElement(this.createMailButtonWithText); + } + + public getCreateButtonWithoutText() { + return cy.getTestElement(this.createMailButtonWithoutText); + } + + public getList() { + return cy.getTestElement(this.list); + } + + public getNoPostfachText() { + return cy.getTestElement(this.noPostfachText); + } + + public getListItem(subject: string): PostfachMailListItem { + return new PostfachMailListItem(subject); + } + + public getAttachments() { + return cy.getTestElement(this.attachments); + } + + public getDownloadButtonWithIcon() { + return cy.getTestElement(this.downloadButtonWithIcon); + } + + public getDownloadButtonWithLabel() { + return cy.getTestElement(this.downloadButtonWithLabel); + } } -export class PostfachMailListItem {//TODO: Rename -> PostfachMailListItemE2EComponent +export class PostfachMailListItem { + //TODO: Rename -> PostfachMailListItemE2EComponent - private readonly locatorCreatedAt: string = 'mail-created-at'; - private readonly locatorSubject: string = 'mail-subject'; - private readonly locatorText: string = 'mail-text'; - private readonly locatorReplyIcon: string = 'reply-icon'; - private readonly locatorSentAt: string = 'mail-sent-at'; + private readonly locatorCreatedAt: string = 'mail-created-at'; + private readonly locatorSubject: string = 'mail-subject'; + private readonly locatorText: string = 'mail-text'; + private readonly locatorReplyIcon: string = 'reply-icon'; + private readonly locatorSentAt: string = 'mail-sent-at'; - private readonly locatorMailSendErrorText: string = 'mail-send-error-text'; - private readonly locatorMailSendErrorIcon: string = 'mail-send-error-icon'; - private readonly locatorMailResendButton: string = 'mail-resend-button'; + private readonly locatorMailSendErrorText: string = 'mail-send-error-text'; + private readonly locatorMailSendErrorIcon: string = 'mail-send-error-icon'; + private readonly locatorMailResendButton: string = 'mail-resend-button'; - private readonly attachmentContainer: AttachmentContainerE2EComponent = new AttachmentContainerE2EComponent(); + private readonly attachmentContainer: AttachmentContainerE2EComponent = + new AttachmentContainerE2EComponent(); - private locatorRoot: string; + private locatorRoot: string; - constructor(subject: string) { - this.locatorRoot = convertToDataTestId(subject) + '-item'; - } + constructor(subject: string) { + this.locatorRoot = convertToDataTestId(subject) + '-item'; + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getSubject() { - return this.getRoot().getTestElement(this.locatorSubject); - } + public getSubject() { + return this.getRoot().getTestElement(this.locatorSubject); + } - public getText() { - return this.getRoot().getTestElement(this.locatorText); - } + public getText() { + return this.getRoot().getTestElement(this.locatorText); + } - public getCreatedAt() { - return this.getRoot().getTestElement(this.locatorCreatedAt); - } + public getCreatedAt() { + return this.getRoot().getTestElement(this.locatorCreatedAt); + } - public getUserProfile(): UserProfileE2EComponent { - return new UserProfileE2EComponent(this.locatorRoot); - } + public getUserProfile(): UserProfileE2EComponent { + return new UserProfileE2EComponent(this.locatorRoot); + } - public getReplyIcon() { - return this.getRoot().getTestElement(this.locatorReplyIcon); - } + public getReplyIcon() { + return this.getRoot().getTestElement(this.locatorReplyIcon); + } - public getSentAt() { - return this.getRoot().getTestElement(this.locatorSentAt); - } + public getSentAt() { + return this.getRoot().getTestElement(this.locatorSentAt); + } - public getMailSendErrorText() { - return this.getRoot().getTestElement(this.locatorMailSendErrorText); - } + public getMailSendErrorText() { + return this.getRoot().getTestElement(this.locatorMailSendErrorText); + } - public getMailSendErrorIcon() { - return this.getRoot().getTestElement(this.locatorMailSendErrorIcon); - } + public getMailSendErrorIcon() { + return this.getRoot().getTestElement(this.locatorMailSendErrorIcon); + } - public getResendButton() { - return this.getRoot().getTestElement(this.locatorMailResendButton); - } + public getResendButton() { + return this.getRoot().getTestElement(this.locatorMailResendButton); + } - public getAttachmentContainer(): AttachmentContainerE2EComponent { - return this.attachmentContainer; - } -} \ No newline at end of file + public getAttachmentContainer(): AttachmentContainerE2EComponent { + return this.attachmentContainer; + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/ui/button-with-spinner.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/ui/button-with-spinner.e2e.component.ts index 26bc152d60953533cddddd58da532a879ed8aaec..aa08e8c1dd1523845fa935251fb5d615589a7725 100644 --- a/alfa-client/apps/alfa-e2e/src/components/ui/button-with-spinner.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/ui/button-with-spinner.e2e.component.ts @@ -22,15 +22,14 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class ButtonWithSpinnerE2EComponent { + private readonly locatorButton: string = 'icon-button'; - private readonly locatorButton: string = 'icon-button'; + public findButton(root) { + return root.findTestElementWithClass(this.locatorButton); + } - public findButton(root) { - return root.findTestElementWithClass(this.locatorButton); - } - - //TODO Methode aus der MeinPage verwenden - public waitToDisappear(root) { - root.should('not.have.descendants', '[data-test-class=spinner]'); - } -} \ No newline at end of file + //TODO Methode aus der MeinPage verwenden + public waitToDisappear(root) { + root.should('not.have.descendants', '[data-test-class=spinner]'); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/ui/connection-timeout-retry-dialog.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/ui/connection-timeout-retry-dialog.e2e.component.ts index 6f022b243eed4fa5bf56316d4ecea6e6b2c55564..7b5bd1a48ccb1f5dc36ebf0c82c44b5e90094233 100644 --- a/alfa-client/apps/alfa-e2e/src/components/ui/connection-timeout-retry-dialog.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/ui/connection-timeout-retry-dialog.e2e.component.ts @@ -22,56 +22,54 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class ConnectionTimeoutRetryDialogE2EComponent { + private readonly locatorIcon: string = 'icon'; + private readonly locatorHeader: string = 'header'; + private readonly locatorMessage: string = 'message'; - private readonly locatorIcon: string = 'icon'; - private readonly locatorHeader: string = 'header'; - private readonly locatorMessage: string = 'message'; + private readonly locatorRoot: string = 'connection-timeout-retry-dialog'; - private readonly locatorRoot: string = 'connection-timeout-retry-dialog'; + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getIcon() { + return this.getRoot().getTestElement(this.locatorIcon); + } - public getIcon() { - return this.getRoot().getTestElement(this.locatorIcon); - } + public getHeader() { + return this.getRoot().getTestElement(this.locatorHeader); + } - public getHeader() { - return this.getRoot().getTestElement(this.locatorHeader); - } - - public getMessage() { - return this.getRoot().getTestElement(this.locatorMessage); - } + public getMessage() { + return this.getRoot().getTestElement(this.locatorMessage); + } } export class ConnectionTimeoutRetryFailDialogE2EComponent { + private readonly locatorIcon: string = 'icon'; + private readonly locatorHeader: string = 'header'; + private readonly locatorMessage: string = 'message'; + private readonly locatorReloadButton: string = 'reload-button'; - private readonly locatorIcon: string = 'icon'; - private readonly locatorHeader: string = 'header'; - private readonly locatorMessage: string = 'message'; - private readonly locatorReloadButton: string = 'reload-button'; - - private readonly locatorRoot: string = 'connection-timeout-retry-fail-dialog'; + private readonly locatorRoot: string = 'connection-timeout-retry-fail-dialog'; - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getIcon() { - return this.getRoot().getTestElement(this.locatorIcon); - } + public getIcon() { + return this.getRoot().getTestElement(this.locatorIcon); + } - public getHeader() { - return this.getRoot().getTestElement(this.locatorHeader); - } + public getHeader() { + return this.getRoot().getTestElement(this.locatorHeader); + } - public getMessage() { - return this.getRoot().getTestElement(this.locatorMessage); - } + public getMessage() { + return this.getRoot().getTestElement(this.locatorMessage); + } - public getReloadButton() { - return this.getRoot().getTestElement(this.locatorReloadButton); - } -} \ No newline at end of file + public getReloadButton() { + return this.getRoot().getTestElement(this.locatorReloadButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/ui/expansion-panel.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/ui/expansion-panel.e2e.component.ts index 8566f9b029d0271d61cd702ffae1a3784ebf331e..897cfb01c6e61cf7df28161199a1922acacab44f 100644 --- a/alfa-client/apps/alfa-e2e/src/components/ui/expansion-panel.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/ui/expansion-panel.e2e.component.ts @@ -22,15 +22,14 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class ExpansionPanelE2Eomponent { + private readonly locatorExpansionPanel: string = 'expansion-panel'; + private readonly locatorExpansionPanelTitle: string = 'panel-title'; - private readonly locatorExpansionPanel: string = 'expansion-panel'; - private readonly locatorExpansionPanelTitle: string = 'panel-title'; + public getExpansionPanel() { + return cy.getTestElementWithClass(this.locatorExpansionPanel); + } - public getExpansionPanel() { - return cy.getTestElementWithClass(this.locatorExpansionPanel); - } - - public getExpansionPanelTitle() { - return cy.getTestElementWithClass(this.locatorExpansionPanelTitle); - } + public getExpansionPanelTitle() { + return cy.getTestElementWithClass(this.locatorExpansionPanelTitle); + } } diff --git a/alfa-client/apps/alfa-e2e/src/components/ui/fixed-dialog.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/ui/fixed-dialog.e2e.component.ts index 7a71cc91195a807a924048973b3aeb821bbe7aed..9b7ed825cace6144cfeebebabd2da50b09f06d25 100644 --- a/alfa-client/apps/alfa-e2e/src/components/ui/fixed-dialog.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/ui/fixed-dialog.e2e.component.ts @@ -22,25 +22,24 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class FixedDialogE2EComponent { + private readonly locatorDialogHeader: string = 'dialog-header'; + private readonly locatorDialogContent: string = 'dialog-content'; + private readonly locatorCloseButton: string = 'close-button'; + private readonly locatorMinMaxButton: string = 'min-max-button'; - private readonly locatorDialogHeader: string = 'dialog-header'; - private readonly locatorDialogContent: string = 'dialog-content'; - private readonly locatorCloseButton: string = 'close-button'; - private readonly locatorMinMaxButton: string = 'min-max-button'; + public getDialogHeader() { + return cy.getTestElement(this.locatorDialogHeader); + } - public getDialogHeader() { - return cy.getTestElement(this.locatorDialogHeader); - } + public getDialogContent() { + return cy.getTestElement(this.locatorDialogContent); + } - public getDialogContent() { - return cy.getTestElement(this.locatorDialogContent); - } + public getCloseButton() { + return cy.getTestElement(this.locatorCloseButton); + } - public getCloseButton() { - return cy.getTestElement(this.locatorCloseButton); - } - - public getMinMaxButton() { - return cy.getTestElement(this.locatorMinMaxButton); - } -} \ No newline at end of file + public getMinMaxButton() { + return cy.getTestElement(this.locatorMinMaxButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/ui/internal-server-error-diaog.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/ui/internal-server-error-diaog.e2e.component.ts index 374eb7863423555525fa2682f62a6d311240f637..50f956af928ab87517fcfef58d96c12524b05e3d 100644 --- a/alfa-client/apps/alfa-e2e/src/components/ui/internal-server-error-diaog.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/ui/internal-server-error-diaog.e2e.component.ts @@ -22,25 +22,24 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class InternalServerErrorDialogE2EComponent { + private readonly locatorIcon: string = 'error-icon'; + private readonly locatorHeader: string = 'error-header'; + private readonly locatorMessage: string = 'error-message'; + private readonly locatorLogoutButton: string = 'logout-button'; - private readonly locatorIcon: string = 'error-icon'; - private readonly locatorHeader: string = 'error-header'; - private readonly locatorMessage: string = 'error-message'; - private readonly locatorLogoutButton: string = 'logout-button'; + public getIcon() { + return cy.getTestElement(this.locatorIcon); + } - public getIcon() { - return cy.getTestElement(this.locatorIcon); - } + public getHeader() { + return cy.getTestElement(this.locatorHeader); + } - public getHeader() { - return cy.getTestElement(this.locatorHeader); - } + public getMessage() { + return cy.getTestElement(this.locatorMessage); + } - public getMessage() { - return cy.getTestElement(this.locatorMessage); - } - - public getLogoutButton() { - return cy.getTestElement(this.locatorLogoutButton); - } -} \ No newline at end of file + public getLogoutButton() { + return cy.getTestElement(this.locatorLogoutButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/ui/snackbar.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/ui/snackbar.e2e.component.ts index cecdd25386353fb54960d6c90853d923e3caa317..ab35f2d1cf9fc714ac9a453a5e686c1382b8c330 100644 --- a/alfa-client/apps/alfa-e2e/src/components/ui/snackbar.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/ui/snackbar.e2e.component.ts @@ -22,20 +22,19 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class SnackBarE2EComponent { + private readonly locatorMessage: string = 'snackbar-message'; + private readonly locatorCloseButton: string = 'snackbar-close-button'; + private readonly locatorRevokeButton: string = 'snackbar-revoke-button'; - private readonly locatorMessage: string = 'snackbar-message'; - private readonly locatorCloseButton: string = 'snackbar-close-button'; - private readonly locatorRevokeButton: string = 'snackbar-revoke-button'; + public getMessage() { + return cy.getTestElement(this.locatorMessage); + } - public getMessage() { - return cy.getTestElement(this.locatorMessage); - } + public getCloseButton() { + return cy.getTestElement(this.locatorCloseButton); + } - public getCloseButton() { - return cy.getTestElement(this.locatorCloseButton); - } - - public getRevokeButton() { - return cy.getTestElement(this.locatorRevokeButton); - } -} \ No newline at end of file + public getRevokeButton() { + return cy.getTestElement(this.locatorRevokeButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/ui/spinner.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/ui/spinner.e2e.component.ts index a3a047a514ac083bea8d86eaa0d83705aebe1137..872fcc86d72680c608e92c092e06c4a7c20862fb 100644 --- a/alfa-client/apps/alfa-e2e/src/components/ui/spinner.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/ui/spinner.e2e.component.ts @@ -22,15 +22,14 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class SpinnerE2EComponent { + private readonly locator: string = 'spinner'; - private readonly locator: string = 'spinner'; + public findSpinner(root) { + return root.findTestElementWithClass(this.locator); + } - public findSpinner(root) { - return root.findTestElementWithClass(this.locator); - } - - //TODO Methode aus der MeinPage verwenden - public waitToDisappear(root) { - root.should('not.have.descendants', '[data-test-class=spinner]'); - } -} \ No newline at end of file + //TODO Methode aus der MeinPage verwenden + public waitToDisappear(root) { + root.should('not.have.descendants', '[data-test-class=spinner]'); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts b/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts index a2c6c10e6274b9d5e367edadd30e14b47309477b..c5128261b80d27316a0256bd39796003e7e6f9fb 100644 --- a/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts +++ b/alfa-client/apps/alfa-e2e/src/components/user-assistance/help-menu.component.e2e.ts @@ -1,18 +1,17 @@ export class HelpMenuE2EComponent { + private readonly root: string = 'help-menu'; + private readonly button: string = 'help-menu-button'; + private readonly openDocumentationButton: string = 'open-documentation-button'; - private readonly root: string = 'help-menu'; - private readonly button: string = 'help-menu-button'; - private readonly openDocumentationButton: string = 'open-documentation-button'; + public getRoot() { + return cy.getTestElementWithOid(this.root); + } - public getRoot() { - return cy.getTestElementWithOid(this.root); - } + public getButton() { + return this.getRoot().getTestElementWithOid(this.button); + } - public getButton() { - return this.getRoot().getTestElementWithOid(this.button); - } - - public getOpenDocumentationButton() { - return this.getRoot().getTestElementWithOid(this.openDocumentationButton); - } + public getOpenDocumentationButton() { + return this.getRoot().getTestElementWithOid(this.openDocumentationButton); + } } diff --git a/alfa-client/apps/alfa-e2e/src/components/user-profile/current-user-profile.component.e2e.ts b/alfa-client/apps/alfa-e2e/src/components/user-profile/current-user-profile.component.e2e.ts index 39da6c6339913a9da780e8ae55acd30432b62df3..caa4da170044134fd7d8439b78e4870fcb43a678 100644 --- a/alfa-client/apps/alfa-e2e/src/components/user-profile/current-user-profile.component.e2e.ts +++ b/alfa-client/apps/alfa-e2e/src/components/user-profile/current-user-profile.component.e2e.ts @@ -24,30 +24,29 @@ import { UserProfileE2EComponent } from './user-profile.component.e2e'; export class CurrentUserProfileE2EComponent { + private readonly locatorUserIconButton: string = 'user-icon-button'; + private readonly locatorLogoutButton: string = 'logout-button'; - private readonly locatorUserIconButton: string = 'user-icon-button'; - private readonly locatorLogoutButton: string = 'logout-button'; + private readonly locatorRoot: string = 'current-user'; - private readonly locatorRoot: string = 'current-user'; + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getUserProfile(): UserProfileE2EComponent { + return new UserProfileE2EComponent(this.locatorRoot); + } - public getUserProfile(): UserProfileE2EComponent { - return new UserProfileE2EComponent(this.locatorRoot); - } + public logout(): void { + this.getUserIconButton().click(); + this.getLogoutButton().click(); + } - public logout(): void { - this.getUserIconButton().click(); - this.getLogoutButton().click(); - } + public getUserIconButton() { + return cy.getTestElement(this.locatorUserIconButton); + } - public getUserIconButton() { - return cy.getTestElement(this.locatorUserIconButton); - } - - private getLogoutButton() { - return cy.getTestElement(this.locatorLogoutButton); - } -} \ No newline at end of file + private getLogoutButton() { + return cy.getTestElement(this.locatorLogoutButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile-icon.component.e2e.ts b/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile-icon.component.e2e.ts index 22d633cbd6ef3df66655d92a562b329515b18465..4a86c818e21a1a946abfed5ffca98e00518d5520 100644 --- a/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile-icon.component.e2e.ts +++ b/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile-icon.component.e2e.ts @@ -23,38 +23,37 @@ */ export class UserProfileIconE2EComponent { + private readonly locatorAssignedIcon: string = 'user-profile-assigned'; + private readonly locatorUnassignedIcon: string = 'user-profile-unassigned'; - private readonly locatorAssignedIcon: string = 'user-profile-assigned'; - private readonly locatorUnassignedIcon: string = 'user-profile-unassigned'; + private readonly locatorErrorNotFoundIcon: string = 'user-profile-user-not-found'; + private readonly locatorErrorServiceUnavailableIcon: string = 'user-profile-service-unavailable'; - private readonly locatorErrorNotFoundIcon: string = 'user-profile-user-not-found'; - private readonly locatorErrorServiceUnavailableIcon: string = 'user-profile-service-unavailable'; + private readonly locatorUserProfileButton: string = 'user-profile-button-container'; - private readonly locatorUserProfileButton: string = 'user-profile-button-container'; + constructor(private root: string) {} - constructor(private root: string) { } + public getRoot() { + return cy.getTestElement(this.root); + } - public getRoot() { - return cy.getTestElement(this.root); - } + public getUnassignedIcon() { + return this.getRoot().findTestElementWithClass(this.locatorUnassignedIcon); + } - public getUnassignedIcon() { - return this.getRoot().findTestElementWithClass(this.locatorUnassignedIcon); - } + public getAssignedIcon() { + return this.getRoot().findTestElementWithClass(this.locatorAssignedIcon); + } - public getAssignedIcon() { - return this.getRoot().findTestElementWithClass(this.locatorAssignedIcon); - } + public getErrorResourceNotFoundIcon() { + return this.getRoot().findTestElementWithClass(this.locatorErrorNotFoundIcon); + } - public getErrorResourceNotFoundIcon() { - return this.getRoot().findTestElementWithClass(this.locatorErrorNotFoundIcon); - } + public getErrorServiceUnavailableIcon() { + return this.getRoot().findTestElementWithClass(this.locatorErrorServiceUnavailableIcon); + } - public getErrorServiceUnavailableIcon() { - return this.getRoot().findTestElementWithClass(this.locatorErrorServiceUnavailableIcon); - } - - public getButton() { - return this.getRoot().getTestElement(this.locatorUserProfileButton); - } -} \ No newline at end of file + public getButton() { + return this.getRoot().getTestElement(this.locatorUserProfileButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile-search.component.e2e.ts b/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile-search.component.e2e.ts index a685ec6f0d21a101b6475569f238e43a6e8f2e49..b1c740608f38769e27a76ae85b58b4fbaee8ec4c 100644 --- a/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile-search.component.e2e.ts +++ b/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile-search.component.e2e.ts @@ -22,26 +22,25 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class UserProfileSearchE2EComponent { + private readonly locatorInput: string = 'Bearbeiter-autocomplete-input'; + private readonly locatorError: string = 'Bearbeiter-autocomplete-error'; + private readonly locatorOptions: string = 'autocomplete-option'; - private readonly locatorInput: string = 'Bearbeiter-autocomplete-input'; - private readonly locatorError: string = 'Bearbeiter-autocomplete-error'; - private readonly locatorOptions: string = 'autocomplete-option'; + constructor(private root: string) {} - constructor(private root: string) { } + public getRoot() { + return cy.getTestElement(this.root); + } - public getRoot() { - return cy.getTestElement(this.root); - } + public getInput() { + return cy.getTestElement(this.locatorInput); + } - public getInput() { - return cy.getTestElement(this.locatorInput); - } + public getSearchOption(prefix: string) { + return cy.getTestElement(prefix + '-' + this.locatorOptions); + } - public getSearchOption(prefix: string) { - return cy.getTestElement(prefix + '-' + this.locatorOptions); - } - - public getError() { - return cy.getTestElement(this.locatorError); - } -} \ No newline at end of file + public getError() { + return cy.getTestElement(this.locatorError); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile.component.e2e.ts b/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile.component.e2e.ts index efccf8a9c2ba8c6fb6a869577ae3410287cd89a6..8bad72031fefd5d267c3c3951562d9e2ce10565e 100644 --- a/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile.component.e2e.ts +++ b/alfa-client/apps/alfa-e2e/src/components/user-profile/user-profile.component.e2e.ts @@ -25,24 +25,23 @@ import { UserProfileIconE2EComponent } from './user-profile-icon.component.e2e'; import { UserProfileSearchE2EComponent } from './user-profile-search.component.e2e'; export class UserProfileE2EComponent { + private readonly locatorUserProfileName: string = 'user-profile-name'; - private readonly locatorUserProfileName: string = 'user-profile-name'; + constructor(private root: string) {} - constructor(private root: string) { } + public getRoot() { + return cy.getTestElement(this.root); + } - public getRoot() { - return cy.getTestElement(this.root); - } + public getIconContainer(): UserProfileIconE2EComponent { + return new UserProfileIconE2EComponent(this.root); + } - public getIconContainer(): UserProfileIconE2EComponent { - return new UserProfileIconE2EComponent(this.root); - } + public getSearchContainer(): UserProfileSearchE2EComponent { + return new UserProfileSearchE2EComponent(this.root); + } - public getSearchContainer(): UserProfileSearchE2EComponent { - return new UserProfileSearchE2EComponent(this.root); - } - - public getName() { - return this.getRoot().findTestElementWithClass(this.locatorUserProfileName); - } -} \ No newline at end of file + public getName() { + return this.getRoot().findTestElementWithClass(this.locatorUserProfileName); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/user-settings/user-settings.component.e2e.ts b/alfa-client/apps/alfa-e2e/src/components/user-settings/user-settings.component.e2e.ts index a53454a3edf3205d4fe91ea212b7c8b9bd758af2..0ff6578edbce33cb3da9392fe3a1d41716352a71 100644 --- a/alfa-client/apps/alfa-e2e/src/components/user-settings/user-settings.component.e2e.ts +++ b/alfa-client/apps/alfa-e2e/src/components/user-settings/user-settings.component.e2e.ts @@ -24,42 +24,40 @@ import { TOGGLE_ELEMENT } from '../../support/angular.util'; export class UserSettingsE2EComponent { - - private readonly rootLocator: string = 'user-settings'; - private readonly emailBenachrichtigungLocator: string = 'email-benachrichtigung'; - private readonly darkModeLocator: string = 'dark-mode'; - private readonly buttonLocator: string = 'icon-button'; - - public getRoot() { - return cy.getTestElementWithOid(this.rootLocator); - } - - public getEmailBenachrichtigung(): ToggleE2EComponent { - return new ToggleE2EComponent(this.emailBenachrichtigungLocator); - } - - public getDarkMode(): ToggleE2EComponent { - return new ToggleE2EComponent(this.darkModeLocator); - } - - public getButton() { - return this.getRoot().findTestElementWithClass(this.buttonLocator); - } + private readonly rootLocator: string = 'user-settings'; + private readonly emailBenachrichtigungLocator: string = 'email-benachrichtigung'; + private readonly darkModeLocator: string = 'dark-mode'; + private readonly buttonLocator: string = 'icon-button'; + + public getRoot() { + return cy.getTestElementWithOid(this.rootLocator); + } + + public getEmailBenachrichtigung(): ToggleE2EComponent { + return new ToggleE2EComponent(this.emailBenachrichtigungLocator); + } + + public getDarkMode(): ToggleE2EComponent { + return new ToggleE2EComponent(this.darkModeLocator); + } + + public getButton() { + return this.getRoot().findTestElementWithClass(this.buttonLocator); + } } export class ToggleE2EComponent { + private readonly rootLocator: string; - private readonly rootLocator: string; - - constructor(root: string) { - this.rootLocator = root; - } + constructor(root: string) { + this.rootLocator = root; + } - public getRoot() { - return cy.getTestElementWithOid(this.rootLocator); - } + public getRoot() { + return cy.getTestElementWithOid(this.rootLocator); + } - public getToggle() { - return this.getRoot().findElement(TOGGLE_ELEMENT); - } -} \ No newline at end of file + public getToggle() { + return this.getRoot().findElement(TOGGLE_ELEMENT); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-aktenzeichen-edit.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-aktenzeichen-edit.e2e.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..e7abc4ad43553519453880fff286e1cd6063ac31 --- /dev/null +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-aktenzeichen-edit.e2e.component.ts @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den + * Ministerpräsidenten des Landes Schleswig-Holstein + * Staatskanzlei + * Abteilung Digitalisierung und zentrales IT-Management der Landesregierung + * + * Lizenziert unter der EUPL, Version 1.2 oder - sobald + * diese von der Europäischen Kommission genehmigt wurden - + * Folgeversionen der EUPL ("Lizenz"); + * Sie dürfen dieses Werk ausschließlich gemäß + * dieser Lizenz nutzen. + * Eine Kopie der Lizenz finden Sie hier: + * + * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 + * + * Sofern nicht durch anwendbare Rechtsvorschriften + * gefordert oder in schriftlicher Form vereinbart, wird + * die unter der Lizenz verbreitete Software "so wie sie + * ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - + * ausdrücklich oder stillschweigend - verbreitet. + * Die sprachspezifischen Genehmigungen und Beschränkungen + * unter der Lizenz sind dem Lizenztext zu entnehmen. + */ + +export class VorgangAktenzeichenEditE2EComponent { + private readonly textEditor: string = 'Aktenzeichen-text-input'; + private readonly confirmButton: string = 'aktenzeichen-edit-dialog-confirmation-button'; + private readonly cancelButton: string = 'aktenzeichen-edit-dialog-cancel-button'; + private readonly clearButton: string = 'clear-button'; + private readonly clipboardButton: string = 'aktenzeichen-paste-clipboard'; + + private locatorRoot: string = 'alfa-aktenzeichen-edit-dialog'; + + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } + + public getTextEditor() { + return cy.getTestElement(this.textEditor); + } + + public getConfirmButton() { + return cy.getTestElement(this.confirmButton); + } + + public getCancelButton() { + return cy.getTestElement(this.cancelButton); + } + + public getClearButton() { + return cy.getTestElement(this.clearButton); + } + + public getClipboardButton() { + return cy.getTestElement(this.clipboardButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-antragsteller.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-antragsteller.e2e.component.ts index 36b0cdd154738f151dec0062e86445e8ed455415..4b7aeff44cff9eeb83ee2c4053c9afe6d886b808 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-antragsteller.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-antragsteller.e2e.component.ts @@ -22,46 +22,45 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class AntragstellerE2EComponent { + private readonly antragstellerName: string = 'antragsteller-name'; + private readonly antragstellerEmail: string = 'antragsteller-email'; + private readonly antragstellerTelefon: string = 'antragsteller-telefon'; + private readonly antragstellerStrasseHausnummer: string = 'antragsteller-strasse-hausnummer'; + private readonly antragstellerPlzOrt: string = 'antragsteller-plz-ort'; + private readonly antragstellerBirthData: string = 'antragsteller-geburt'; + private readonly noAntragsteller: string = 'no-antragsteller'; - private readonly antragstellerName: string = 'antragsteller-name'; - private readonly antragstellerEmail: string = 'antragsteller-email'; - private readonly antragstellerTelefon: string = 'antragsteller-telefon'; - private readonly antragstellerStrasseHausnummer: string = 'antragsteller-strasse-hausnummer'; - private readonly antragstellerPlzOrt: string = 'antragsteller-plz-ort'; - private readonly antragstellerBirthData: string = 'antragsteller-geburt'; - private readonly noAntragsteller: string = 'no-antragsteller'; + private readonly locatorRoot: string = 'vorgang-detail-antragsteller'; - private readonly locatorRoot: string = 'vorgang-detail-antragsteller'; + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getName() { + return cy.getTestElement(this.antragstellerName); + } - public getName() { - return cy.getTestElement(this.antragstellerName); - } + public getEmail() { + return cy.getTestElement(this.antragstellerEmail); + } - public getEmail() { - return cy.getTestElement(this.antragstellerEmail); - } + public getTelefon() { + return cy.getTestElement(this.antragstellerTelefon); + } - public getTelefon() { - return cy.getTestElement(this.antragstellerTelefon); - } + public getStrasseHausnummer() { + return cy.getTestElement(this.antragstellerStrasseHausnummer); + } - public getStrasseHausnummer() { - return cy.getTestElement(this.antragstellerStrasseHausnummer); - } + public getPlzOrt() { + return cy.getTestElement(this.antragstellerPlzOrt); + } - public getPlzOrt() { - return cy.getTestElement(this.antragstellerPlzOrt); - } + public getBirthData() { + return cy.getTestElement(this.antragstellerBirthData); + } - public getBirthData() { - return cy.getTestElement(this.antragstellerBirthData); - } - - public getNoAntragsteller() { - return cy.getTestElement(this.noAntragsteller); - } -} \ No newline at end of file + public getNoAntragsteller() { + return cy.getTestElement(this.noAntragsteller); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-detail-header.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-detail-header.e2e.component.ts index 46c6cc3fae4d43171dcc7e93e1fc0a2b8f469555..19f5a06a60280de864453ef80c62f4c6260df889 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-detail-header.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-detail-header.e2e.component.ts @@ -24,43 +24,53 @@ import { UserProfileE2EComponent } from '../user-profile/user-profile.component.e2e'; export class VorgangDetailHeaderE2EComponent { + private readonly locatorStatus: string = 'status-text'; + private readonly locatorCreatedAt: string = 'created-at'; + private readonly locatorName: string = 'name'; + private readonly locatorAktenzeichen: string = 'aktenzeichen'; + private readonly locatorAktenzeichenEdit: string = 'aktenzeichen-editieren'; + private readonly locatorVorgangNummer: string = 'vorgang-nummer'; + private readonly locatorUserIcon: string = 'vorgang-header-user-icon'; - private readonly locatorStatus: string = 'status-text'; - private readonly locatorCreatedAt: string = 'created-at'; - private readonly locatorName: string = 'name'; - private readonly locatorAktenzeichen: string = 'aktenzeichen'; - private readonly locatorVorgangNummer: string = 'vorgang-nummer'; - private readonly locatorUserIcon: string = 'vorgang-header-user-icon'; + private readonly userIcon: UserProfileE2EComponent = new UserProfileE2EComponent( + this.locatorUserIcon, + ); - private readonly userIcon: UserProfileE2EComponent = new UserProfileE2EComponent(this.locatorUserIcon); + private readonly locatorRoot: string = 'vorgang-detail-header'; - private readonly locatorRoot: string = 'vorgang-detail-header'; + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getStatus() { + return cy.getTestElement(this.locatorStatus); + } - public getStatus() { - return cy.getTestElement(this.locatorStatus); - } + public getCreatedAt() { + return cy.getTestElement(this.locatorCreatedAt); + } - public getCreatedAt() { - return cy.getTestElement(this.locatorCreatedAt); - } + public getName() { + return cy.getTestElement(this.locatorName); + } - public getName() { - return cy.getTestElement(this.locatorName); - } + public getAktenzeichen() { + return cy.getTestElement(this.locatorAktenzeichen); + } - public getAktenzeichen() { - return cy.getTestElement(this.locatorAktenzeichen); - } + public getAktenzeichenEdit() { + return cy.getTestElement(this.locatorAktenzeichenEdit); + } - public getVorgangNummer() { - return cy.getTestElement(this.locatorVorgangNummer); - } + public getAktenzeichenEditButton() { + return cy.getTestElement(this.locatorAktenzeichenEdit).children('button'); + } - public getUserContainer(): UserProfileE2EComponent { - return this.userIcon; - } -} \ No newline at end of file + public getVorgangNummer() { + return cy.getTestElement(this.locatorVorgangNummer); + } + + public getUserContainer(): UserProfileE2EComponent { + return this.userIcon; + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components.ts index d626406e3ce77a83da953b05245000d5af693ff7..73501d7faca9d4ca1bd5995ba42df76f4008714d 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components.ts @@ -22,60 +22,60 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class VorgangFormularButtonsE2EComponent { + private readonly abschliessenButton: string = 'abschliessen-button'; + private readonly annehmenButton: string = 'annehmen-button'; + private readonly bearbeitenButton: string = 'bearbeiten-button'; + private readonly bescheidenButton: string = 'bescheiden-button'; + private readonly endgueltigLoeschenButton: string = 'endgueltig-loeschen-button'; + private readonly loeschAnforderungZuruecknehmenButton: string = + 'loesch-anforderung-zuruecknehmen-button'; + private readonly loeschenAnfordernButton: string = 'loeschen-anfordern-button'; + private readonly verwerfenButton: string = 'verwerfen-button'; + private readonly wiedereroeffnenButton: string = 'wiedereroeffnen-button'; + private readonly zurueckholenButton: string = 'zurueckholen-button'; + private readonly zurueckstellenButton: string = 'zurueckstellen-button'; - private readonly abschliessenButton: string = 'abschliessen-button'; - private readonly annehmenButton: string = 'annehmen-button'; - private readonly bearbeitenButton: string = 'bearbeiten-button'; - private readonly bescheidenButton: string = 'bescheiden-button'; - private readonly endgueltigLoeschenButton: string = 'endgueltig-loeschen-button'; - private readonly loeschAnforderungZuruecknehmenButton: string = 'loesch-anforderung-zuruecknehmen-button'; - private readonly loeschenAnfordernButton: string = 'loeschen-anfordern-button'; - private readonly verwerfenButton: string = 'verwerfen-button'; - private readonly wiedereroeffnenButton: string = 'wiedereroeffnen-button'; - private readonly zurueckholenButton: string = 'zurueckholen-button'; - private readonly zurueckstellenButton: string = 'zurueckstellen-button'; + public getAbschliessenButton() { + return cy.getTestElement(this.abschliessenButton); + } - public getAbschliessenButton() { - return cy.getTestElement(this.abschliessenButton); - } + public getAnnehmenButton() { + return cy.getTestElement(this.annehmenButton); + } - public getAnnehmenButton() { - return cy.getTestElement(this.annehmenButton); - } + public getBearbeitenButton() { + return cy.getTestElement(this.bearbeitenButton); + } - public getBearbeitenButton() { - return cy.getTestElement(this.bearbeitenButton); - } + public getBescheidenButton() { + return cy.getTestElement(this.bescheidenButton); + } - public getBescheidenButton() { - return cy.getTestElement(this.bescheidenButton); - } + public getEndgueltigLoeschenButton() { + return cy.getTestElement(this.endgueltigLoeschenButton); + } - public getEndgueltigLoeschenButton() { - return cy.getTestElement(this.endgueltigLoeschenButton); - } + public getLoeschAnforderungZuruecknehmenButton() { + return cy.getTestElement(this.loeschAnforderungZuruecknehmenButton); + } - public getLoeschAnforderungZuruecknehmenButton() { - return cy.getTestElement(this.loeschAnforderungZuruecknehmenButton); - } + public getLoeschenAnfordernButton() { + return cy.getTestElement(this.loeschenAnfordernButton); + } - public getLoeschenAnfordernButton() { - return cy.getTestElement(this.loeschenAnfordernButton); - } + public getVerwerfenButton() { + return cy.getTestElement(this.verwerfenButton); + } - public getVerwerfenButton() { - return cy.getTestElement(this.verwerfenButton); - } + public getWiedereroeffnenButton() { + return cy.getTestElement(this.wiedereroeffnenButton); + } - public getWiedereroeffnenButton() { - return cy.getTestElement(this.wiedereroeffnenButton); - } + public getZurueckholenButton() { + return cy.getTestElement(this.zurueckholenButton); + } - public getZurueckholenButton() { - return cy.getTestElement(this.zurueckholenButton); - } - - public getZurueckstellenButton() { - return cy.getTestElement(this.zurueckstellenButton); - } -} \ No newline at end of file + public getZurueckstellenButton() { + return cy.getTestElement(this.zurueckstellenButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component.ts index 8cc5beaa14e714748fd0accbc105224197358b2a..262f8449c33319364bb2fff0853e92c8f2225412 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-formular.e2e.component.ts @@ -26,62 +26,63 @@ import { ExpansionPanelE2Eomponent } from '../ui/expansion-panel.e2e.component'; import { VorgangFormularDatenHistorieE2EComponent } from './vorgang.formular-daten.historie.e2e.component'; export class VorgangFormularDatenE2EComponent { + private readonly locatorRoot: string = 'formulardaten-panel'; + private readonly locatorMetadaten: string = 'metadaten'; + private readonly locatorAntragdaten: string = 'antragdaten'; + private readonly locatorTabset: string = 'div[role=tab]'; - private readonly locatorRoot: string = 'formulardaten-panel'; - private readonly locatorMetadaten: string = 'metadaten'; - private readonly locatorAntragdaten: string = 'antragdaten'; - private readonly locatorTabset: string = 'div[role=tab]'; + private readonly vorgangFormPanelContainer: ExpansionPanelE2Eomponent = + new ExpansionPanelE2Eomponent(); + private readonly historieContainer: VorgangFormularDatenHistorieE2EComponent = + new VorgangFormularDatenHistorieE2EComponent(); - private readonly vorgangFormPanelContainer: ExpansionPanelE2Eomponent = new ExpansionPanelE2Eomponent(); - private readonly historieContainer: VorgangFormularDatenHistorieE2EComponent = new VorgangFormularDatenHistorieE2EComponent(); + private readonly antragdatenTab: number = 0; + private readonly metadatenTab: number = 1; + private readonly representationTab: number = 2; + private readonly attachmentTab: number = 3; + private readonly historieTab: number = 4; - private readonly antragdatenTab: number = 0; - private readonly metadatenTab: number = 1; - private readonly representationTab: number = 2; - private readonly attachmentTab: number = 3; - private readonly historieTab: number = 4; + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getExpansionPanelContainer(): ExpansionPanelE2Eomponent { + return this.vorgangFormPanelContainer; + } - public getExpansionPanelContainer(): ExpansionPanelE2Eomponent { - return this.vorgangFormPanelContainer; - } + public getAntragdatenTab() { + return this.getTabsetElement().eq(this.antragdatenTab); + } - public getAntragdatenTab() { - return this.getTabsetElement().eq(this.antragdatenTab); - } + public getMetadatenTab() { + return this.getTabsetElement().eq(this.metadatenTab); + } - public getMetadatenTab() { - return this.getTabsetElement().eq(this.metadatenTab); - } + public getRepresentationTab() { + return this.getTabsetElement().eq(this.representationTab); + } - public getRepresentationTab() { - return this.getTabsetElement().eq(this.representationTab); - } + public getAttachmentTab() { + return this.getTabsetElement().eq(this.attachmentTab); + } - public getAttachmentTab() { - return this.getTabsetElement().eq(this.attachmentTab); - } + public getHistorieTab() { + return this.getTabsetElement().eq(this.historieTab); + } - public getHistorieTab() { - return this.getTabsetElement().eq(this.historieTab); - } + private getTabsetElement() { + return getElement(this.locatorTabset); + } - private getTabsetElement() { - return getElement(this.locatorTabset); - } + public getMetadaten() { + return getTestElement(this.locatorMetadaten); + } - public getMetadaten() { - return getTestElement(this.locatorMetadaten); - } + public getAntragdaten() { + return getTestElement(this.locatorAntragdaten); + } - public getAntragdaten() { - return getTestElement(this.locatorAntragdaten); - } - - public getHistorieContainer(): VorgangFormularDatenHistorieE2EComponent { - return this.historieContainer; - } -} \ No newline at end of file + public getHistorieContainer(): VorgangFormularDatenHistorieE2EComponent { + return this.historieContainer; + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forward-formular.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forward-formular.e2e.component.ts index 1c6c82292178ed8f63195747ebdc818719459338..8fb48a259215e425ab13463c35e90eebcf616c60 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forward-formular.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forward-formular.e2e.component.ts @@ -22,42 +22,41 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class ForwardFormularE2EComponent { - - private readonly locatorPasswortInput: string = 'Passwort-text-input'; - private readonly locatorPasswortError: string = 'Passwort-text-error'; - private readonly locatorZustaendigeStelleInput: string = 'zustandige_Stelle-text-input'; - private readonly locatorZustaendigeStelleError: string = 'zustandige_Stelle-text-error'; - private readonly locatorForwardButton: string = 'forward-button'; - - private readonly locatorRoot: string = 'forward-form'; - - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } - - public getPasswort() { - return cy.getTestElement(this.locatorPasswortInput); - } - - public getPasswortError() { - return cy.getTestElement(this.locatorPasswortError); - } - - public getZustaendigeStelle() { - return cy.getTestElement(this.locatorZustaendigeStelleInput); - } - - public getZustaendigeStelleError() { - return cy.getTestElement(this.locatorZustaendigeStelleError); - } - - //TODO Getter draus machen und im Test den click durchführen - public forward() { - return this.getForwardButton().click(); - } - // - - private getForwardButton() { - return cy.getTestElement(this.locatorForwardButton); - } -} \ No newline at end of file + private readonly locatorPasswortInput: string = 'Passwort-text-input'; + private readonly locatorPasswortError: string = 'Passwort-text-error'; + private readonly locatorZustaendigeStelleInput: string = 'zustandige_Stelle-text-input'; + private readonly locatorZustaendigeStelleError: string = 'zustandige_Stelle-text-error'; + private readonly locatorForwardButton: string = 'forward-button'; + + private readonly locatorRoot: string = 'forward-form'; + + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } + + public getPasswort() { + return cy.getTestElement(this.locatorPasswortInput); + } + + public getPasswortError() { + return cy.getTestElement(this.locatorPasswortError); + } + + public getZustaendigeStelle() { + return cy.getTestElement(this.locatorZustaendigeStelleInput); + } + + public getZustaendigeStelleError() { + return cy.getTestElement(this.locatorZustaendigeStelleError); + } + + //TODO Getter draus machen und im Test den click durchführen + public forward() { + return this.getForwardButton().click(); + } + // + + private getForwardButton() { + return cy.getTestElement(this.locatorForwardButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forward.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forward.e2e.component.ts index a6794417c583d9fb202da3e8d28fb970c10473db..6597c84566712da8d144f10af1da120b3857052e 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forward.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-forward.e2e.component.ts @@ -24,52 +24,52 @@ import { ForwardFormularE2EComponent } from './vorgang-forward-formular.e2e.component'; export class VorgangForwardingE2EComponent { + private readonly locatorForwardingSpinner: string = 'forwarding-spinner'; + private readonly locatorForwardingSuccessMessage: string = 'forwarding-success-message'; + private readonly locatorForwardingErrorMessage: string = 'forwarding-error-message'; + private readonly locatorForwardingMarkAsSuccessButton: string = 'mark-as-success-button'; + private readonly locatorSuccessfullMessage: string = 'successfull-message'; + private readonly locatorForwardingMarkAsFailButton: string = 'mark-as-fail-button'; + private readonly locatorFailedMessage: string = 'failed-message'; - private readonly locatorForwardingSpinner: string = 'forwarding-spinner'; - private readonly locatorForwardingSuccessMessage: string = 'forwarding-success-message'; - private readonly locatorForwardingErrorMessage: string = 'forwarding-error-message'; - private readonly locatorForwardingMarkAsSuccessButton: string = 'mark-as-success-button'; - private readonly locatorSuccessfullMessage: string = 'successfull-message'; - private readonly locatorForwardingMarkAsFailButton: string = 'mark-as-fail-button'; - private readonly locatorFailedMessage: string = 'failed-message'; + private readonly forwardingFormular: ForwardFormularE2EComponent = + new ForwardFormularE2EComponent(); - private readonly forwardingFormular: ForwardFormularE2EComponent = new ForwardFormularE2EComponent(); + private readonly locatorRoot: string = 'forwarding'; - private readonly locatorRoot: string = 'forwarding'; + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getFormular(): ForwardFormularE2EComponent { + return this.forwardingFormular; + } - public getFormular(): ForwardFormularE2EComponent { - return this.forwardingFormular; - } + public getForwardingSuccessMessage() { + return cy.getTestElement(this.locatorForwardingSuccessMessage); + } - public getForwardingSuccessMessage() { - return cy.getTestElement(this.locatorForwardingSuccessMessage); - } + public getForwardingErrorMessage() { + return cy.getTestElement(this.locatorForwardingErrorMessage); + } - public getForwardingErrorMessage() { - return cy.getTestElement(this.locatorForwardingErrorMessage); - } + public getSpinner() { + return cy.getTestElement(this.locatorForwardingSpinner); + } - public getSpinner() { - return cy.getTestElement(this.locatorForwardingSpinner); - } + public getMarkAsSuccessButton() { + return cy.getTestElement(this.locatorForwardingMarkAsSuccessButton); + } - public getMarkAsSuccessButton() { - return cy.getTestElement(this.locatorForwardingMarkAsSuccessButton); - } + public getSuccessfullMessage() { + return cy.getTestElement(this.locatorSuccessfullMessage); + } - public getSuccessfullMessage() { - return cy.getTestElement(this.locatorSuccessfullMessage); - } + public getMarkAsFailButton() { + return cy.getTestElement(this.locatorForwardingMarkAsFailButton); + } - public getMarkAsFailButton() { - return cy.getTestElement(this.locatorForwardingMarkAsFailButton); - } - - public getFailedMessage() { - return cy.getTestElement(this.locatorFailedMessage); - } + public getFailedMessage() { + return cy.getTestElement(this.locatorFailedMessage); + } } diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-item.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-item.e2e.component.ts index c0c9ae9c11075d2fa569c4e9636a85782e9a19f2..ee113c32c6c350d13b8915daa3486ae08cbca54c 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-item.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-item.e2e.component.ts @@ -25,44 +25,43 @@ import { convertToDataTestId } from '../../support/tech.util'; import { UserProfileE2EComponent } from '../user-profile/user-profile.component.e2e'; export class VorgangListItemE2EComponent { + private readonly locatorStatus: string = 'status-text'; + private readonly locatorPostfachIcon: string = 'postfach-icon'; + private readonly locatorPostfachIconMatIcon: string = 'postfach-icon-mat-icon'; + private readonly locatorWiedervorlageNextFrist: string = 'wiedervorlage-next-frist'; + private readonly locatorWiedervorlagenList: string = 'wiedervorlagen-list-in-vorgang'; - private readonly locatorStatus: string = 'status-text'; - private readonly locatorPostfachIcon: string = 'postfach-icon'; - private readonly locatorPostfachIconMatIcon: string = 'postfach-icon-mat-icon'; - private readonly locatorWiedervorlageNextFrist: string = 'wiedervorlage-next-frist'; - private readonly locatorWiedervorlagenList: string = 'wiedervorlagen-list-in-vorgang'; + private locatorRoot: string; - private locatorRoot: string; + constructor(private vorgangName: string) { + this.locatorRoot = 'vorgang-list-item-' + convertToDataTestId(this.vorgangName); + } - constructor(private vorgangName: string) { - this.locatorRoot = 'vorgang-list-item-' + convertToDataTestId(this.vorgangName); - } + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getStatus() { + return this.getRoot().findTestElementWithClass(this.locatorStatus); + } - public getStatus() { - return this.getRoot().findTestElementWithClass(this.locatorStatus); - } + public getPostfachIcon() { + return this.getRoot().findTestElementWithClass(this.locatorPostfachIcon); + } - public getPostfachIcon() { - return this.getRoot().findTestElementWithClass(this.locatorPostfachIcon); - } + public getPostfachIconMatIcon() { + return this.getRoot().findTestElementWithClass(this.locatorPostfachIconMatIcon); + } - public getPostfachIconMatIcon() { - return this.getRoot().findTestElementWithClass(this.locatorPostfachIconMatIcon); - } + public getWiedervorlageNextFrist() { + return this.getRoot().findTestElementWithClass(this.locatorWiedervorlageNextFrist); + } - public getWiedervorlageNextFrist() { - return this.getRoot().findTestElementWithClass(this.locatorWiedervorlageNextFrist); - } + public getWiedervorlagenList() { + return this.getRoot().findTestElementWithClass(this.locatorWiedervorlagenList); + } - public getWiedervorlagenList() { - return this.getRoot().findTestElementWithClass(this.locatorWiedervorlagenList); - } - - public getUserProfile(): UserProfileE2EComponent { - return new UserProfileE2EComponent(this.locatorRoot); - } -} \ No newline at end of file + public getUserProfile(): UserProfileE2EComponent { + return new UserProfileE2EComponent(this.locatorRoot); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-list.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-list.e2e.component.ts index d0e624dcf85c3a9fc1ed5268a9ed36578389ea4b..bdf2986a88bab4074b7c0ee12ae54595def52f34 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-list.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-list.e2e.component.ts @@ -25,37 +25,36 @@ import { SpinnerE2EComponent } from '../ui/spinner.e2e.component'; import { VorgangListItemE2EComponent } from './vorgang-item.e2e.component'; export class VorgangListE2EComponent { - - private readonly spinnerComponent: SpinnerE2EComponent = new SpinnerE2EComponent(); - - private readonly root: string = 'vorgang-list'; - private readonly item: string = 'alfa-vorgang-list-item'; - private readonly noRoleMessage: string = 'user-no-role-message'; - private readonly emptyListText: string = 'empty-list-text'; - private readonly emptyList: string = 'empty-list'; - - public getRoot() { - return cy.getTestElement(this.root); - } - - public getItems() { - return this.getRoot().find(this.item); - } - - public getListItem(vorgangName: string): VorgangListItemE2EComponent { - return new VorgangListItemE2EComponent(vorgangName); - } - - /**@deprecated use waitForSpinnerToAppear() */ - public getSpinner() { - return this.spinnerComponent.findSpinner(this.getRoot()); - } - - public getNoRoleMessage() { - return cy.getTestElement(this.noRoleMessage); - } - - public getEmptySucheMessage() { - return cy.getTestElement(this.emptyListText); - } -} \ No newline at end of file + private readonly spinnerComponent: SpinnerE2EComponent = new SpinnerE2EComponent(); + + private readonly root: string = 'vorgang-list'; + private readonly item: string = 'alfa-vorgang-list-item'; + private readonly noRoleMessage: string = 'user-no-role-message'; + private readonly emptyListText: string = 'empty-list-text'; + private readonly emptyList: string = 'empty-list'; + + public getRoot() { + return cy.getTestElement(this.root); + } + + public getItems() { + return this.getRoot().find(this.item); + } + + public getListItem(vorgangName: string): VorgangListItemE2EComponent { + return new VorgangListItemE2EComponent(vorgangName); + } + + /**@deprecated use waitForSpinnerToAppear() */ + public getSpinner() { + return this.spinnerComponent.findSpinner(this.getRoot()); + } + + public getNoRoleMessage() { + return cy.getTestElement(this.noRoleMessage); + } + + public getEmptySucheMessage() { + return cy.getTestElement(this.emptyListText); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-more-menu.e2e.components.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-more-menu.e2e.components.ts index c532679ba633513017d9ae1f6e92150badb725e4..cb6f501de05aeae9d46d44ccbcc9c53c37127a28 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-more-menu.e2e.components.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-more-menu.e2e.components.ts @@ -22,56 +22,55 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class VorgangMoreMenuE2EComponent { + private readonly rootLocator: string = 'more-menu'; + private readonly buttonLocator: string = 'more-menu-button'; - private readonly rootLocator: string = 'more-menu'; - private readonly buttonLocator: string = 'more-menu-button'; + private readonly exportierenItem: VorgangMoreMenuExportierenItemE2EComponent = + new VorgangMoreMenuExportierenItemE2EComponent(); + private readonly vorpruefenItem: VorgangMoreMenuVorpruefenItemE2EComponent = + new VorgangMoreMenuVorpruefenItemE2EComponent(); - private readonly exportierenItem: VorgangMoreMenuExportierenItemE2EComponent = new VorgangMoreMenuExportierenItemE2EComponent(); - private readonly vorpruefenItem: VorgangMoreMenuVorpruefenItemE2EComponent = new VorgangMoreMenuVorpruefenItemE2EComponent(); + public getRoot() { + return cy.getTestElementWithOid(this.rootLocator); + } - public getRoot() { - return cy.getTestElementWithOid(this.rootLocator); - } + //TODO in die Subnavigation verschieben + public getButton() { + return this.getRoot().getTestElementWithOid(this.buttonLocator); + } + // - //TODO in die Subnavigation verschieben - public getButton() { - return this.getRoot().getTestElementWithOid(this.buttonLocator); - } - // + public getExportierenItem(): VorgangMoreMenuExportierenItemE2EComponent { + return this.exportierenItem; + } - public getExportierenItem(): VorgangMoreMenuExportierenItemE2EComponent { - return this.exportierenItem; - } - - public getVorpruefenItem(): VorgangMoreMenuVorpruefenItemE2EComponent { - return this.vorpruefenItem; - } + public getVorpruefenItem(): VorgangMoreMenuVorpruefenItemE2EComponent { + return this.vorpruefenItem; + } } export class VorgangMoreMenuExportierenItemE2EComponent { + private readonly root: string = 'vorgang-exportieren-button'; + private readonly button: string = 'export-vorgang'; - private readonly root: string = 'vorgang-exportieren-button'; - private readonly button: string = 'export-vorgang'; - - public getRoot() { - return cy.getTestElementWithOid(this.root); - } + public getRoot() { + return cy.getTestElementWithOid(this.root); + } - public getButton() { - return this.getRoot().getTestElementWithOid(this.button); - } + public getButton() { + return this.getRoot().getTestElementWithOid(this.button); + } } export class VorgangMoreMenuVorpruefenItemE2EComponent { + private readonly root: string = 'vorgang-process-vorgang-button'; + private readonly button: string = 'process-vorgang'; - private readonly root: string = 'vorgang-process-vorgang-button'; - private readonly button: string = 'process-vorgang'; - - public getRoot() { - return cy.getTestElementWithOid(this.root); - } + public getRoot() { + return cy.getTestElementWithOid(this.root); + } - public getButton() { - return this.getRoot().getTestElementWithOid(this.button); - } + public getButton() { + return this.getRoot().getTestElementWithOid(this.button); + } } diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component.ts index 84558c877b9985b512a4d257641e03bbd76c65ec..d879ee9fc1c21ef8e1318dad1ca87283118e2439 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component.ts @@ -24,74 +24,74 @@ import { convertToDataTestId } from '../../support/tech.util'; export class VorgangSearchE2EComponent { - - private readonly locatorButton: string = 'search-button'; - private readonly locatorInput: string = 'search-input'; - private readonly locatorForm: string = 'search-form'; - private readonly locatorSearchPreviewList: string = 'search-preview-list'; - private readonly locatorClearButton: string = 'clear-button'; - - private readonly locatorRoot: string = 'vorgang-search'; - - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } - - public getInput() { - return cy.getTestElement(this.locatorInput); - } - - public getSearchButton() { - return cy.getTestElement(this.locatorButton); - } - - public getForm() { - return cy.getTestElement(this.locatorForm); - } - - public getVorgangSearchPreviewList() { - return cy.getTestElement(this.locatorSearchPreviewList); - } - - public getVorgangSearchPreviewListItem(vorgangName: string): VorgangSearchPreviewListItemE2EComponent { - return new VorgangSearchPreviewListItemE2EComponent(vorgangName); - } - - public getClearButton() { - return cy.getTestElement(this.locatorClearButton); - } + private readonly locatorButton: string = 'search-button'; + private readonly locatorInput: string = 'search-input'; + private readonly locatorForm: string = 'search-form'; + private readonly locatorSearchPreviewList: string = 'search-preview-list'; + private readonly locatorClearButton: string = 'clear-button'; + + private readonly locatorRoot: string = 'vorgang-search'; + + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } + + public getInput() { + return cy.getTestElement(this.locatorInput); + } + + public getSearchButton() { + return cy.getTestElement(this.locatorButton); + } + + public getForm() { + return cy.getTestElement(this.locatorForm); + } + + public getVorgangSearchPreviewList() { + return cy.getTestElement(this.locatorSearchPreviewList); + } + + public getVorgangSearchPreviewListItem( + vorgangName: string, + ): VorgangSearchPreviewListItemE2EComponent { + return new VorgangSearchPreviewListItemE2EComponent(vorgangName); + } + + public getClearButton() { + return cy.getTestElement(this.locatorClearButton); + } } export class VorgangSearchPreviewListItemE2EComponent { + private readonly locatorCreatedAt: string = 'preview-list-item-created-at'; + private readonly locatorVorgangName: string = 'preview-list-item-vorgang-name'; + private readonly locatorVorgangAktenzeichen: string = 'preview-list-item-vorgang-aktenzeichen'; + private readonly locatorVorgangNummer: string = 'vorgang-nummer'; - private readonly locatorCreatedAt: string = 'preview-list-item-created-at'; - private readonly locatorVorgangName: string = 'preview-list-item-vorgang-name'; - private readonly locatorVorgangAktenzeichen: string = 'preview-list-item-vorgang-aktenzeichen'; - private readonly locatorVorgangNummer: string = 'vorgang-nummer'; + private locatorRoot: string; - private locatorRoot: string; + constructor(vorgangName: string) { + this.locatorRoot = 'search-preview-list-item-' + convertToDataTestId(vorgangName); + } - constructor(vorgangName: string) { - this.locatorRoot = 'search-preview-list-item-' + convertToDataTestId(vorgangName); - } + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getCreatedAt() { + return this.getRoot().getTestElement(this.locatorCreatedAt); + } - public getCreatedAt() { - return this.getRoot().getTestElement(this.locatorCreatedAt); - } + public getVorgangName() { + return this.getRoot().getTestElement(this.locatorVorgangName); + } - public getVorgangName() { - return this.getRoot().getTestElement(this.locatorVorgangName); - } + public getVorgangAktenzeichen() { + return this.getRoot().getTestElement(this.locatorVorgangAktenzeichen); + } - public getVorgangAktenzeichen() { - return this.getRoot().getTestElement(this.locatorVorgangAktenzeichen); - } - - public getVorgangNummer() { - return this.getRoot().getTestElement(this.locatorVorgangNummer); - } -} \ No newline at end of file + public getVorgangNummer() { + return this.getRoot().getTestElement(this.locatorVorgangNummer); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-subnavigation.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-subnavigation.ts index 184b7e157dfa1bafa472c31ae5dec09f37c58280..826cb6a09e8321d97578db6ddc61f3706874ba1c 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-subnavigation.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-subnavigation.ts @@ -23,87 +23,87 @@ */ //TODO Datei umbenennen -> vorgang-subnavigation.e2e-component.ts export class VorgangSubnavigationE2EComponent { - - private readonly backIconButton: string = 'back-button'; - - private readonly assignUserProfileIconButton: string = 'assign-user-profile-icon-button'; - private readonly annehmenIconButton: string = 'annehmen-icon-button'; - private readonly abschliessenIconButton: string = 'abschliessen-icon-button'; - private readonly bearbeitenIconButton: string = 'bearbeiten-icon-button'; - private readonly bescheidenIconButton: string = 'bescheiden-icon-button'; - private readonly endgueltigLoeschenIconButton: string = 'endgueltig-loeschen-icon-button'; - private readonly loeschAnforderungZuruecknehmenIconButton: string = 'loesch-anforderung-zuruecknehmen-icon-button'; - private readonly loeschenAnfordernIconButton: string = 'loeschen-anfordern-icon-button'; - private readonly postfachMailIconButton: string = 'send-mail-icon-button'; - private readonly verwerfenIconButton: string = 'verwerfen-icon-button'; - private readonly wiedereroeffnenIconButton: string = 'wiedereroeffnen-icon-button'; - private readonly wiedervorlageErstellenIconButton: string = 'create-wiedervorlage-icon-button'; - private readonly zurueckholenIconButton: string = 'zurueckholen-icon-button'; - private readonly zurueckstellenIconButton: string = 'zurueckstellen-icon-button'; - - public getBackButton() { - return cy.getTestElement(this.backIconButton); - } - - public getAnnehmenIconButton() { - return cy.getTestElement(this.annehmenIconButton); - } - - //TOCHECK Wird nicht genutzt - public getEndgueltigLoeschenIconButton() { - return cy.getTestElement(this.endgueltigLoeschenIconButton); - } - // - - public getLoeschAnforderungZuruecknehmenIconButton() { - return cy.getTestElement(this.loeschAnforderungZuruecknehmenIconButton); - } - - public getVerwerfenIconButton() { - return cy.getTestElement(this.verwerfenIconButton); - } - - public getZurueckholenIconButton() { - return cy.getTestElement(this.zurueckholenIconButton); - } - - public getLoeschenAnfordernByIconButton() { - return cy.getTestElement(this.loeschenAnfordernIconButton); - } - - public getAbschliessenIconButton() { - return cy.getTestElement(this.abschliessenIconButton); - } - - public getBearbeitenIconButton() { - return cy.getTestElement(this.bearbeitenIconButton); - } - - public getBescheidenIconButton() { - return cy.getTestElement(this.bescheidenIconButton); - } - - public getWiedereroeffnenIconButton() { - return cy.getTestElement(this.wiedereroeffnenIconButton); - } - - public getZurueckstellenIconButton() { - return cy.getTestElement(this.zurueckstellenIconButton); - } - - public getWiedervorlageIconButton() { - return cy.getTestElement(this.wiedervorlageErstellenIconButton); - } - - public getCreateWiedervorlageIconButton() { - return cy.getTestElement(this.wiedervorlageErstellenIconButton); - } - - public getAssignUserProfileIconButton() { - return cy.getTestElement(this.assignUserProfileIconButton); - } - - public getPostfachMailIconButton() { - return cy.getTestElement(this.postfachMailIconButton); - } -} \ No newline at end of file + private readonly backIconButton: string = 'back-button'; + + private readonly assignUserProfileIconButton: string = 'assign-user-profile-icon-button'; + private readonly annehmenIconButton: string = 'annehmen-icon-button'; + private readonly abschliessenIconButton: string = 'abschliessen-icon-button'; + private readonly bearbeitenIconButton: string = 'bearbeiten-icon-button'; + private readonly bescheidenIconButton: string = 'bescheiden-icon-button'; + private readonly endgueltigLoeschenIconButton: string = 'endgueltig-loeschen-icon-button'; + private readonly loeschAnforderungZuruecknehmenIconButton: string = + 'loesch-anforderung-zuruecknehmen-icon-button'; + private readonly loeschenAnfordernIconButton: string = 'loeschen-anfordern-icon-button'; + private readonly postfachMailIconButton: string = 'send-mail-icon-button'; + private readonly verwerfenIconButton: string = 'verwerfen-icon-button'; + private readonly wiedereroeffnenIconButton: string = 'wiedereroeffnen-icon-button'; + private readonly wiedervorlageErstellenIconButton: string = 'create-wiedervorlage-icon-button'; + private readonly zurueckholenIconButton: string = 'zurueckholen-icon-button'; + private readonly zurueckstellenIconButton: string = 'zurueckstellen-icon-button'; + + public getBackButton() { + return cy.getTestElement(this.backIconButton); + } + + public getAnnehmenIconButton() { + return cy.getTestElement(this.annehmenIconButton); + } + + //TOCHECK Wird nicht genutzt + public getEndgueltigLoeschenIconButton() { + return cy.getTestElement(this.endgueltigLoeschenIconButton); + } + // + + public getLoeschAnforderungZuruecknehmenIconButton() { + return cy.getTestElement(this.loeschAnforderungZuruecknehmenIconButton); + } + + public getVerwerfenIconButton() { + return cy.getTestElement(this.verwerfenIconButton); + } + + public getZurueckholenIconButton() { + return cy.getTestElement(this.zurueckholenIconButton); + } + + public getLoeschenAnfordernByIconButton() { + return cy.getTestElement(this.loeschenAnfordernIconButton); + } + + public getAbschliessenIconButton() { + return cy.getTestElement(this.abschliessenIconButton); + } + + public getBearbeitenIconButton() { + return cy.getTestElement(this.bearbeitenIconButton); + } + + public getBescheidenIconButton() { + return cy.getTestElement(this.bescheidenIconButton); + } + + public getWiedereroeffnenIconButton() { + return cy.getTestElement(this.wiedereroeffnenIconButton); + } + + public getZurueckstellenIconButton() { + return cy.getTestElement(this.zurueckstellenIconButton); + } + + public getWiedervorlageIconButton() { + return cy.getTestElement(this.wiedervorlageErstellenIconButton); + } + + public getCreateWiedervorlageIconButton() { + return cy.getTestElement(this.wiedervorlageErstellenIconButton); + } + + public getAssignUserProfileIconButton() { + return cy.getTestElement(this.assignUserProfileIconButton); + } + + public getPostfachMailIconButton() { + return cy.getTestElement(this.postfachMailIconButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component.ts index 67c59701fbdfae208d5c698dc08900eb0a4b79fa..f1240912ebb55269bfea578cd2a72a23187a61a6 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component.ts @@ -1,78 +1,92 @@ export class VorgangViewsE2EComponent { - - private readonly neuViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Neu'); - private readonly angenommenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Angenommen'); - private readonly inBearbeitungViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('In_Bearbeitung'); - private readonly beschiedenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Beschieden'); - private readonly abgeschlossenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Abgeschlossen'); - private readonly verworfenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Verworfen'); - private readonly zuLoeschenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Zu_Loschen'); - private readonly wiedervorlagenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Wiedervorlagen'); - private readonly vorgangListViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Vorgangsliste'); - private readonly searchViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Suche'); - - public getNeu(): VorgangViewE2EComponent { - return this.neuViewItem; - } - - public getAngenommen(): VorgangViewE2EComponent { - return this.angenommenViewItem; - } - - public getInBearbeitung(): VorgangViewE2EComponent { - return this.inBearbeitungViewItem; - } - - public getBeschieden(): VorgangViewE2EComponent { - return this.beschiedenViewItem; - } - - public getAbgeschlossen(): VorgangViewE2EComponent { - return this.abgeschlossenViewItem; - } - - public getVerworfen(): VorgangViewE2EComponent { - return this.verworfenViewItem; - } - - public getZuLoeschen(): VorgangViewE2EComponent { - return this.zuLoeschenViewItem; - } - - public getWiedervorlagen(): VorgangViewE2EComponent { - return this.wiedervorlagenViewItem; - } - - public getVorgangList(): VorgangViewE2EComponent { - return this.vorgangListViewItem; - } - - public getSuche(): VorgangViewE2EComponent { - return this.searchViewItem; - } + private readonly neuViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Neu'); + private readonly angenommenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent( + 'Angenommen', + ); + private readonly inBearbeitungViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent( + 'In_Bearbeitung', + ); + private readonly beschiedenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent( + 'Beschieden', + ); + private readonly abgeschlossenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent( + 'Abgeschlossen', + ); + private readonly verworfenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent( + 'Verworfen', + ); + private readonly zuLoeschenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent( + 'Zu_Loschen', + ); + private readonly wiedervorlagenViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent( + 'Wiedervorlagen', + ); + private readonly vorgangListViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent( + 'Vorgangsliste', + ); + private readonly searchViewItem: VorgangViewE2EComponent = new VorgangViewE2EComponent('Suche'); + + public getNeu(): VorgangViewE2EComponent { + return this.neuViewItem; + } + + public getAngenommen(): VorgangViewE2EComponent { + return this.angenommenViewItem; + } + + public getInBearbeitung(): VorgangViewE2EComponent { + return this.inBearbeitungViewItem; + } + + public getBeschieden(): VorgangViewE2EComponent { + return this.beschiedenViewItem; + } + + public getAbgeschlossen(): VorgangViewE2EComponent { + return this.abgeschlossenViewItem; + } + + public getVerworfen(): VorgangViewE2EComponent { + return this.verworfenViewItem; + } + + public getZuLoeschen(): VorgangViewE2EComponent { + return this.zuLoeschenViewItem; + } + + public getWiedervorlagen(): VorgangViewE2EComponent { + return this.wiedervorlagenViewItem; + } + + public getVorgangList(): VorgangViewE2EComponent { + return this.vorgangListViewItem; + } + + public getSuche(): VorgangViewE2EComponent { + return this.searchViewItem; + } } export class VorgangViewE2EComponent { + private readonly count: string = 'views-menu-item-count-'; + private readonly root: string = 'views-menu-item-'; + private readonly button: string = 'routing-button'; - private readonly count: string = 'views-menu-item-count-'; - private readonly root: string = 'views-menu-item-'; - private readonly button: string = 'routing-button'; - - private rootId: string; + private rootId: string; - constructor(rootId: string){ - this.rootId = rootId; - } + constructor(rootId: string) { + this.rootId = rootId; + } - public getRoot() { - return cy.getTestElement(`${this.root}${this.rootId}`); - } + public getRoot() { + return cy.getTestElement(`${this.root}${this.rootId}`); + } - public getCount() { - return this.getRoot().getTestElement(`${this.count}${this.rootId}`); - } + public getCount() { + return this.getRoot().getTestElement(`${this.count}${this.rootId}`); + } - public getButton() { - return this.getRoot().getTestElementWithClass(this.button); - } -} \ No newline at end of file + public getButton() { + return this.getRoot().getTestElementWithClass(this.button); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component.ts index aacf32c6360b98f94a23adb2ca3abe7d38b4f96d..d5286aa695acb9684e9b7ae74e3d3361768b0995 100644 --- a/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component.ts @@ -24,146 +24,163 @@ import { getTestElement } from '../../support/cypress-helper'; export class VorgangFormularDatenHistorieE2EComponent { + private readonly locatorRoot: string = 'historie-in-vorgang-container'; + private readonly locatorCreatedAt: string = 'historie-vorgang-created-at'; - private readonly locatorRoot: string = 'historie-in-vorgang-container'; - private readonly locatorCreatedAt: string = 'historie-vorgang-created-at'; + public getRoot() { + return getTestElement(this.locatorRoot); + } - public getRoot() { - return getTestElement(this.locatorRoot); - } + public getCreatedAt() { + return getTestElement(this.locatorCreatedAt); + } - public getCreatedAt() { - return getTestElement(this.locatorCreatedAt); - } - - public getListItemByIndex(index: number): VorgangFormularDatenHistorieItemE2EComponent { - return new VorgangFormularDatenHistorieItemE2EComponent(index); - } + public getListItemByIndex(index: number): VorgangFormularDatenHistorieItemE2EComponent { + return new VorgangFormularDatenHistorieItemE2EComponent(index); + } } export class VorgangFormularDatenHistorieItemE2EComponent { - - private readonly locatorRoot: string = 'historie-list-item-'; - private readonly locatorHeadline: string = 'historie-item-header'; - private readonly locatorUser: string = 'user-profile-in-historie-item-header'; - private readonly locatorSystemUser: string = 'system-user-in-historie-item-header'; - private readonly locatorExpandButton: string = 'expansion-button'; - - constructor(private itemIndex: number) { - this.locatorRoot = 'historie-list-item-' + this.itemIndex; - } - - public getRoot() { - return getTestElement(this.locatorRoot); - } - - public getHeadline() { - return this.getRoot().findTestElementWithClass(this.locatorHeadline); - } - - public getUser() { - return this.getRoot().findTestElementWithClass(this.locatorUser); - } - - public getSystemUser() { - return this.getRoot().findTestElementWithClass(this.locatorSystemUser); - } - - public getExpandButton() { - return this.getRoot().findTestElementWithClass(this.locatorExpandButton); - } - - public getPostfachNachricht(): PostfachNachrichtHistorieItemE2EComponent { - return new PostfachNachrichtHistorieItemE2EComponent(this.locatorRoot); - } - - public getWiedervorlage(): WiedervorlageHistorieItemE2EComponent { - return new WiedervorlageHistorieItemE2EComponent(this.locatorRoot); - } - - public getKommentar(): KommentarHistorieItemE2EComponent { - return new KommentarHistorieItemE2EComponent(this.locatorRoot); - } + private readonly locatorRoot: string = 'historie-list-item-'; + private readonly locatorHeadline: string = 'historie-item-header'; + private readonly locatorUser: string = 'user-profile-in-historie-item-header'; + private readonly locatorSystemUser: string = 'system-user-in-historie-item-header'; + private readonly locatorExpandButton: string = 'expansion-button'; + + constructor(private itemIndex: number) { + this.locatorRoot = 'historie-list-item-' + this.itemIndex; + } + + public getRoot() { + return getTestElement(this.locatorRoot); + } + + public getHeadline() { + return this.getRoot().findTestElementWithClass(this.locatorHeadline); + } + + public getUser() { + return this.getRoot().findTestElementWithClass(this.locatorUser); + } + + public getSystemUser() { + return this.getRoot().findTestElementWithClass(this.locatorSystemUser); + } + + public getExpandButton() { + return this.getRoot().findTestElementWithClass(this.locatorExpandButton); + } + + public getPostfachNachricht(): PostfachNachrichtHistorieItemE2EComponent { + return new PostfachNachrichtHistorieItemE2EComponent(this.locatorRoot); + } + + public getWiedervorlage(): WiedervorlageHistorieItemE2EComponent { + return new WiedervorlageHistorieItemE2EComponent(this.locatorRoot); + } + + public getKommentar(): KommentarHistorieItemE2EComponent { + return new KommentarHistorieItemE2EComponent(this.locatorRoot); + } + + public getAktenzeichen(): AktenzeichenHistorieItemE2EComponent { + return new AktenzeichenHistorieItemE2EComponent(this.locatorRoot); + } } export class PostfachNachrichtHistorieItemE2EComponent { + private readonly locatorRoot: string; - private readonly locatorRoot: string; - - private readonly locatorPostfachMailBody: string = 'postfach-nachricht-mail-body'; - private readonly locatorPostfachSubject: string = 'postfach-nachricht-subject'; + private readonly locatorPostfachMailBody: string = 'postfach-nachricht-mail-body'; + private readonly locatorPostfachSubject: string = 'postfach-nachricht-subject'; - constructor(rootLocator: string) { - this.locatorRoot = rootLocator; - } + constructor(rootLocator: string) { + this.locatorRoot = rootLocator; + } - public getRoot() { - return getTestElement(this.locatorRoot); - } + public getRoot() { + return getTestElement(this.locatorRoot); + } - public getPostfachNachrichtSubject() { - return this.getRoot().findTestElementWithClass(this.locatorPostfachSubject); - } + public getPostfachNachrichtSubject() { + return this.getRoot().findTestElementWithClass(this.locatorPostfachSubject); + } - public getPostfachNachrichtMailBody() { - return this.getRoot().findTestElementWithClass(this.locatorPostfachMailBody); - } + public getPostfachNachrichtMailBody() { + return this.getRoot().findTestElementWithClass(this.locatorPostfachMailBody); + } } export class WiedervorlageHistorieItemE2EComponent { + private readonly locatorRoot: string; - private readonly locatorRoot: string; - - private readonly locatorStatus: string = 'wiedervorlage-status'; - private readonly locatorBetreff: string = 'wiedervorlage-betreff'; - private readonly locatorBeschreibung: string = 'wiedervorlage-beschreibung'; - private readonly locatorAttachment: string = 'historie-item-attachment'; + private readonly locatorStatus: string = 'wiedervorlage-status'; + private readonly locatorBetreff: string = 'wiedervorlage-betreff'; + private readonly locatorBeschreibung: string = 'wiedervorlage-beschreibung'; + private readonly locatorAttachment: string = 'historie-item-attachment'; - constructor(rootLocator: string) { - this.locatorRoot = rootLocator; - } + constructor(rootLocator: string) { + this.locatorRoot = rootLocator; + } - public getRoot() { - return getTestElement(this.locatorRoot); - } + public getRoot() { + return getTestElement(this.locatorRoot); + } - public getStatus() { - return this.getRoot().findTestElementWithClass(this.locatorStatus); - } + public getStatus() { + return this.getRoot().findTestElementWithClass(this.locatorStatus); + } - public getBetreff() { - return this.getRoot().findTestElementWithClass(this.locatorBetreff); - } + public getBetreff() { + return this.getRoot().findTestElementWithClass(this.locatorBetreff); + } - public getBeschreibung() { - return this.getRoot().findTestElementWithClass(this.locatorBeschreibung); - } + public getBeschreibung() { + return this.getRoot().findTestElementWithClass(this.locatorBeschreibung); + } - public getAttachment() { - return this.getRoot().findTestElementWithClass(this.locatorAttachment); - } + public getAttachment() { + return this.getRoot().findTestElementWithClass(this.locatorAttachment); + } } export class KommentarHistorieItemE2EComponent { + private readonly locatorRoot: string; - private readonly locatorRoot: string; + private readonly locatorText: string = 'kommentar-text'; + private readonly locatorAttachment: string = 'historie-item-attachment'; - private readonly locatorText: string = 'kommentar-text'; - private readonly locatorAttachment: string = 'historie-item-attachment'; + constructor(rootLocator: string) { + this.locatorRoot = rootLocator; + } - constructor(rootLocator: string) { - this.locatorRoot = rootLocator; - } + public getRoot() { + return getTestElement(this.locatorRoot); + } - public getRoot() { - return getTestElement(this.locatorRoot); - } + public getText() { + return this.getRoot().findTestElementWithClass(this.locatorText); + } + + public getAttachment() { + return this.getRoot().findTestElementWithClass(this.locatorAttachment); + } +} - public getText() { - return this.getRoot().findTestElementWithClass(this.locatorText); - } +export class AktenzeichenHistorieItemE2EComponent { + private readonly root: string; - public getAttachment() { - return this.getRoot().findTestElementWithClass(this.locatorAttachment); - } -} \ No newline at end of file + private readonly text: string = 'aktenzeichen-text'; + + constructor(rootLocator: string) { + this.root = rootLocator; + } + + public getRoot() { + return getTestElement(this.root); + } + + public getText() { + return this.getRoot().findTestElementWithClass(this.text); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-in-vorgang.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-in-vorgang.e2e.component.ts index 35530cf17375ca5272e7b1bdf22c62001b94ee6c..cb475a71a15c76c219fe5830a897786c3c9b92ae 100644 --- a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-in-vorgang.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-in-vorgang.e2e.component.ts @@ -26,53 +26,53 @@ import { AttachmentContainerE2EComponent } from '../attachment/attachment.e2e.co import { StatusE2EComponent } from './wiedervorlage-status.e2e.component'; export class WiedervorlageInVorgangE2EComponent { + private readonly locatorFrist: string = 'frist'; + private readonly locatorBetreff: string = 'betreff'; + private readonly locatorLink: string = 'link'; + private readonly locatorExpandButon: string = 'expand-button'; + private readonly locatorExpandable: string = 'expandable'; + private readonly attachmentContainer: AttachmentContainerE2EComponent = + new AttachmentContainerE2EComponent(); - private readonly locatorFrist: string = 'frist'; - private readonly locatorBetreff: string = 'betreff'; - private readonly locatorLink: string = 'link'; - private readonly locatorExpandButon: string = 'expand-button'; - private readonly locatorExpandable: string = 'expandable'; - private readonly attachmentContainer: AttachmentContainerE2EComponent = new AttachmentContainerE2EComponent(); + private locatorRoot: string; - private locatorRoot: string; + constructor(private betreff: string) { + this.locatorRoot = replaceAllWhitespaces(this.betreff, '_'); + } - constructor(private betreff: string) { - this.locatorRoot = replaceAllWhitespaces(this.betreff, '_'); - } + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getLink() { + return this.getRoot().findTestElementWithClass(this.locatorLink); + } - public getLink() { - return this.getRoot().findTestElementWithClass(this.locatorLink); - } + public getFrist() { + return this.getRoot().findTestElementWithClass(this.locatorFrist); + } - public getFrist() { - return this.getRoot().findTestElementWithClass(this.locatorFrist); - } + public getBetreff() { + return this.getRoot().findTestElementWithClass(this.locatorBetreff); + } - public getBetreff() { - return this.getRoot().findTestElementWithClass(this.locatorBetreff); - } + public getExpandButton() { + return this.getRoot().findTestElementWithClass(this.locatorExpandButon); + } - public getExpandButton() { - return this.getRoot().findTestElementWithClass(this.locatorExpandButon); - } + public getStatus(): StatusE2EComponent { + return new StatusE2EComponent(this.locatorRoot); + } - public getStatus(): StatusE2EComponent { - return new StatusE2EComponent(this.locatorRoot) - } + public expandItem(): void { + this.getExpandButton().click(); + } - public expandItem(): void { - this.getExpandButton().click(); - } + public getExpandable() { + return this.getRoot().findTestElementWithClass(this.locatorExpandable); + } - public getExpandable() { - return this.getRoot().findTestElementWithClass(this.locatorExpandable); - } - - public getAttachmentContainer(): AttachmentContainerE2EComponent { - return this.attachmentContainer; - } -} \ No newline at end of file + public getAttachmentContainer(): AttachmentContainerE2EComponent { + return this.attachmentContainer; + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-page.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-page.e2e.component.ts index 0c039320f5cf6d6279dc2b1b0fcd0d38ec77c299..9da456960ea99739b3aeffcb930459f990608495 100644 --- a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-page.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-page.e2e.component.ts @@ -25,47 +25,50 @@ import { AttachmentContainerE2EComponent } from '../attachment/attachment.e2e.co import { ButtonWithSpinnerE2EComponent } from '../ui/button-with-spinner.e2e.component'; export class WiedervorlageE2EComponent { + private readonly locatorBetreffInput: string = 'Betreff-text-input'; + private readonly locatorBeschreibungInput: string = 'Beschreibung-textarea-input'; + private readonly locatorFristInput: string = 'Frist-date-input'; + private readonly locatorBetreffError: string = 'Betreff-text-error'; + private readonly locatorDatumError: string = 'Frist-date-error'; + private readonly locatorStatusDot: string = 'dot'; + private readonly locatorSpeichernButton: string = 'speichern-button'; - private readonly locatorBetreffInput: string = 'Betreff-text-input'; - private readonly locatorBeschreibungInput: string = 'Beschreibung-textarea-input'; - private readonly locatorFristInput: string = 'Frist-date-input'; - private readonly locatorBetreffError: string = 'Betreff-text-error'; - private readonly locatorDatumError: string = 'Frist-date-error'; - private readonly locatorStatusDot: string = 'dot'; - private readonly locatorSpeichernButton: string = 'speichern-button'; + private readonly buttonWithSpinnerComponent: ButtonWithSpinnerE2EComponent = + new ButtonWithSpinnerE2EComponent(); + private readonly attachmentContainer: AttachmentContainerE2EComponent = + new AttachmentContainerE2EComponent(); - private readonly buttonWithSpinnerComponent: ButtonWithSpinnerE2EComponent = new ButtonWithSpinnerE2EComponent(); - private readonly attachmentContainer: AttachmentContainerE2EComponent = new AttachmentContainerE2EComponent(); + public getBetreff() { + return cy.getTestElement(this.locatorBetreffInput); + } - public getBetreff() { - return cy.getTestElement(this.locatorBetreffInput); - } + public getBetreffError() { + return cy.getTestElement(this.locatorBetreffError); + } - public getBetreffError() { - return cy.getTestElement(this.locatorBetreffError); - } + public getBeschreibung() { + return cy.getTestElement(this.locatorBeschreibungInput); + } - public getBeschreibung() { - return cy.getTestElement(this.locatorBeschreibungInput); - } + public getFrist() { + return cy.getTestElement(this.locatorFristInput); + } - public getFrist() { - return cy.getTestElement(this.locatorFristInput); - } + public getDatumError() { + return cy.getTestElement(this.locatorDatumError); + } - public getDatumError() { - return cy.getTestElement(this.locatorDatumError); - } + public getStatusDot() { + return cy.getTestElementWithClass(this.locatorStatusDot); + } - public getStatusDot() { - return cy.getTestElementWithClass(this.locatorStatusDot); - } + public getSpeichernButton() { + return this.buttonWithSpinnerComponent.findButton( + cy.getTestElement(this.locatorSpeichernButton), + ); + } - public getSpeichernButton() { - return this.buttonWithSpinnerComponent.findButton(cy.getTestElement(this.locatorSpeichernButton)); - } - - public getAttachmentContainer(): AttachmentContainerE2EComponent { - return this.attachmentContainer; - } -} \ No newline at end of file + public getAttachmentContainer(): AttachmentContainerE2EComponent { + return this.attachmentContainer; + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-status.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-status.e2e.component.ts index 6c01778eb5356730c3bcb3f61ca37b99fa6b8b3e..e17513fc9664b7341f2434cc4e1f548df92b3cff 100644 --- a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-status.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-status.e2e.component.ts @@ -22,17 +22,16 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class StatusE2EComponent { + private readonly locatorStatus: string = 'status'; + private readonly locatorStatusDot: string = 'dot'; - private readonly locatorStatus: string = 'status'; - private readonly locatorStatusDot: string = 'dot'; + constructor(private betreff: string) {} - constructor(private betreff: string) { } + public getRoot() { + return cy.getTestElement(this.betreff).findTestElementWithClass(this.locatorStatus); + } - public getRoot() { - return cy.getTestElement(this.betreff).findTestElementWithClass(this.locatorStatus); - } - - public getStatusDot() { - return this.getRoot().findTestElementWithClass(this.locatorStatusDot); - } -} \ No newline at end of file + public getStatusDot() { + return this.getRoot().findTestElementWithClass(this.locatorStatusDot); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-subnavigation.ts b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-subnavigation.ts index 570ef9e3769c01cecd56b6f0c592feaf7d6d35ed..40a1ca85ccd06e989946e4af1b9278c2b14444ef 100644 --- a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-subnavigation.ts +++ b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-subnavigation.ts @@ -22,34 +22,33 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class WiedervorlageSubnavigationE2EComponent { + private readonly locatorNavigateBackButton: string = 'back-button'; + private readonly locatorErledigenButton: string = 'erledigen-icon-button'; + private readonly locatorWiedereroeffnenButton: string = 'wiedereroeffnen-icon-button'; - private readonly locatorNavigateBackButton: string = 'back-button'; - private readonly locatorErledigenButton: string = 'erledigen-icon-button'; - private readonly locatorWiedereroeffnenButton: string = 'wiedereroeffnen-icon-button'; + private readonly locatorRoot: string = 'subnavigation-wiedervorlage'; - private readonly locatorRoot: string = 'subnavigation-wiedervorlage'; + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getBackButton() { + return cy.getTestElement(this.locatorNavigateBackButton); + } - public getBackButton() { - return cy.getTestElement(this.locatorNavigateBackButton); - } + //TODO Getter draus machen und das click im test durchführen - //TODO Getter draus machen und das click im test durchführen + //use getBackButton() instead + public navigateBack(): void { + cy.getTestElement(this.locatorNavigateBackButton).click(); + } - //use getBackButton() instead - public navigateBack(): void { - cy.getTestElement(this.locatorNavigateBackButton).click(); - } + public erledigen(): void { + cy.getTestElement(this.locatorErledigenButton).click(); + } - public erledigen(): void { - cy.getTestElement(this.locatorErledigenButton).click(); - } - - public wiedereroeffnen(): void { - cy.getTestElement(this.locatorWiedereroeffnenButton).click(); - } - // -} \ No newline at end of file + public wiedereroeffnen(): void { + cy.getTestElement(this.locatorWiedereroeffnenButton).click(); + } + // +} diff --git a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component.ts b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component.ts index d9497489f12cee13adfac06b7b4840f5ac798c2a..cd881d0c7d1dfa1d21577c3fb022d316686587c8 100644 --- a/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component.ts +++ b/alfa-client/apps/alfa-e2e/src/components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component.ts @@ -25,22 +25,22 @@ import { ButtonWithSpinnerE2EComponent } from '../ui/button-with-spinner.e2e.com import { WiedervorlageInVorgangE2EComponent } from './wiedervorlage-in-vorgang.e2e.component'; export class WiedervorlagenInVorgangE2EComponent { + private readonly locatorCreateWiedervorlageButton: string = 'create-wiedervorlage'; - private readonly locatorCreateWiedervorlageButton: string = 'create-wiedervorlage'; + private readonly buttonWithSpinnerComponent: ButtonWithSpinnerE2EComponent = + new ButtonWithSpinnerE2EComponent(); - private readonly buttonWithSpinnerComponent: ButtonWithSpinnerE2EComponent = new ButtonWithSpinnerE2EComponent(); + private readonly locatorRoot: string = 'wiedervorlagen-in-vorgang'; - private readonly locatorRoot: string = 'wiedervorlagen-in-vorgang'; + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } + public getWiedervorlage(betreff: string): WiedervorlageInVorgangE2EComponent { + return new WiedervorlageInVorgangE2EComponent(betreff); + } - public getWiedervorlage(betreff: string): WiedervorlageInVorgangE2EComponent { - return new WiedervorlageInVorgangE2EComponent(betreff); - } - - public getCreateWiedervorlageButton() { - return cy.getTestElement(this.locatorCreateWiedervorlageButton); - } -} \ No newline at end of file + public getCreateWiedervorlageButton() { + return cy.getTestElement(this.locatorCreateWiedervorlageButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/navigation/navigation.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/navigation/navigation.cy.ts index 28cc8daed7a1e093ed89eadbdf4bbc162860d96c..f78d366d8834087c8de5bb5268232c8bc9c06a67 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/navigation/navigation.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/navigation/navigation.cy.ts @@ -30,40 +30,38 @@ import { exist, notExist } from 'apps/alfa-e2e/src/support/cypress.util'; import { loginAsEmil } from 'apps/alfa-e2e/src/support/user-util'; describe('Navigation', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const vorgangViews: VorgangViewsE2EComponent = mainPage.getViews(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const vorgangViews: VorgangViewsE2EComponent = mainPage.getViews(); - const navigation: NavigationE2EComponent = mainPage.getNavigation(); + const navigation: NavigationE2EComponent = mainPage.getNavigation(); - before(() => { - loginAsEmil(); - }) + before(() => { + loginAsEmil(); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('after login', () => { + describe('after login', () => { + it('should show vorgangList', { defaultCommandTimeout: 30000 }, () => { + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - it('should show vorgangList', { defaultCommandTimeout: 30000 }, () => { - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + it('should show vorgangList view', () => { + exist(vorgangViews.getVorgangList().getRoot()); + }); + }); - it('should show vorgangList view', () => { - exist(vorgangViews.getVorgangList().getRoot()); - }) - }) + describe('Vorgang filter', () => { + it('MeineVorgaenge should NOT exists', () => { + notExist(navigation.getMeineVorgaengeFilter()); + }); - describe('Vorgang filter', () => { - - it('MeineVorgaenge should NOT exists', () => { - notExist(navigation.getMeineVorgaengeFilter()); - }) - - it('Alle should NOT exists', () => { - notExist(navigation.getAlleFilter()); - }) - }) -}) \ No newline at end of file + it('Alle should NOT exists', () => { + notExist(navigation.getAlleFilter()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-abschliessen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-abschliessen.cy.ts index 78c0a67177065ee489819782514e477ced27ab1c..15b06ef2419bd6df855f8a76a59e8878e543a2ae 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-abschliessen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-abschliessen.cy.ts @@ -23,133 +23,169 @@ */ import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { loginAsEmil } from 'apps/alfa-e2e/src/support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from 'apps/alfa-e2e/src/support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from 'apps/alfa-e2e/src/support/vorgang-util'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; -import { MainPage, waitForSpinnerToDisappear, waitforSpinnerToAppear } from '../../../page-objects/main.po'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; +import { + MainPage, + waitForSpinnerToDisappear, + waitforSpinnerToAppear, +} from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; describe('Vorgang abschliessen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangAbschliessen: VorgangE2E = { ...createVorgang(), name: 'DoAbschliessen', status: VorgangStatusE2E.IN_BEARBEITUNG }; - const vorgangAbschliessenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeAbschliessen'), status: VorgangStatusE2E.IN_BEARBEITUNG }; - - before(() => { - initVorgaenge([vorgangAbschliessen, vorgangAbschliessenRevoke]); - - loginAsEmil(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('abschliessen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbschliessen.name).getRoot().click(); - - waitForSpinnerToDisappear(); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Beschieden', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbschliessen.status]); - }) - - it('should show snackBar', () => { - vorgangFormularButtons.getAbschliessenButton().click(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN) - }) - - it('should close snackBar', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Abgeschlossen', () => { - haveText(vorgangList.getListItem(vorgangAbschliessen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - }) - }) - - describe('abschliessen und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbschliessenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Beschieden', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbschliessenRevoke.status]); - }) - - it('should show snackBar', () => { - vorgangPage.getSubnavigation().getAbschliessenIconButton().click(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Beschieden after progressbar dissapear', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Beschieden', () => { - haveText(vorgangList.getListItem(vorgangAbschliessenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]) - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangAbschliessen: VorgangE2E = { + ...createVorgang(), + name: 'DoAbschliessen', + status: VorgangStatusE2E.IN_BEARBEITUNG, + }; + const vorgangAbschliessenRevoke: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoRevokeAbschliessen'), + status: VorgangStatusE2E.IN_BEARBEITUNG, + }; + + before(() => { + initVorgaenge([vorgangAbschliessen, vorgangAbschliessenRevoke]); + + loginAsEmil(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('abschliessen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbschliessen.name).getRoot().click(); + + waitForSpinnerToDisappear(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Beschieden', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbschliessen.status], + ); + }); + + it('should show snackBar', () => { + vorgangFormularButtons.getAbschliessenButton().click(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN); + }); + + it('should close snackBar', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Abgeschlossen', () => { + haveText( + vorgangList.getListItem(vorgangAbschliessen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + }); + }); + + describe('abschliessen und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbschliessenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Beschieden', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbschliessenRevoke.status], + ); + }); + + it('should show snackBar', () => { + vorgangPage.getSubnavigation().getAbschliessenIconButton().click(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Beschieden after progressbar dissapear', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Beschieden', () => { + haveText( + vorgangList.getListItem(vorgangAbschliessenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward-fail.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward-fail.cy.ts index 03e03da1df22a7439105e0908b164353790be02f..5de87937b1b2c80162c12d23bbd33855aa5b5186 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward-fail.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward-fail.cy.ts @@ -33,70 +33,70 @@ import { loginAsEmil } from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; describe.skip('{TODO: need to fix with a mock} Vorgang forwarding fail', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const vorgangPage: VorgangPage = new VorgangPage(); - const forwardingContainer: VorgangForwardingE2EComponent = vorgangPage.getForwardingContainer(); + const vorgangPage: VorgangPage = new VorgangPage(); + const forwardingContainer: VorgangForwardingE2EComponent = vorgangPage.getForwardingContainer(); - const vorgang: VorgangE2E = createVorgang(); + const vorgang: VorgangE2E = createVorgang(); - before(() => { - initVorgang(vorgang); + before(() => { + initVorgang(vorgang); - loginAsEmil(); + loginAsEmil(); - exist(vorgangList.getRoot()); - }) + exist(vorgangList.getRoot()); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('after click on vorgang', () => { + describe('after click on vorgang', () => { + it('should show vorgang header', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); - it('should show vorgang header', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) + it('should show forwarding', () => { + exist(forwardingContainer.getRoot()); + }); + }); - it('should show forwarding', () => { - exist(forwardingContainer.getRoot()); - }) - }) + describe('fill forward formular', () => { + it('should show spinner with text on valid formular', () => { + const forwardForumlar = forwardingContainer.getFormular(); + forwardForumlar.getZustaendigeStelle().clear().type(FORWARDING_INVALID_EMAIL); + forwardForumlar.getPasswort().clear().type('validespasswort'); - describe('fill forward formular', () => { + forwardForumlar.forward(); - it('should show spinner with text on valid formular', () => { - const forwardForumlar = forwardingContainer.getFormular(); - forwardForumlar.getZustaendigeStelle().clear().type(FORWARDING_INVALID_EMAIL); - forwardForumlar.getPasswort().clear().type('validespasswort'); + exist(forwardingContainer.getSpinner()); + }); + }); - forwardForumlar.forward(); + describe('fail forwarding', () => { + it('should have status ' + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], () => { + waitForSpinnerToDisappear(); - exist(forwardingContainer.getSpinner()); - }) - }) + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); - describe('fail forwarding', () => { + it('should show forward fail text', () => { + exist(forwardingContainer.getForwardingErrorMessage()); + }); - it('should have status ' + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], () => { - waitForSpinnerToDisappear(); + it('should NOT show "mark as success" button', () => { + notExist(forwardingContainer.getMarkAsSuccessButton()); + }); - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]) - }) - - it('should show forward fail text', () => { - exist(forwardingContainer.getForwardingErrorMessage()); - }) - - it('should NOT show "mark as success" button', () => { - notExist(forwardingContainer.getMarkAsSuccessButton()); - }) - - it('should show formular', () => { - exist(forwardingContainer.getFormular().getRoot()); - }) - }) -}) + it('should show formular', () => { + exist(forwardingContainer.getFormular().getRoot()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward.cy.ts index 9f45c89cab9360e2e4d053ea06678d20bd88882b..60283ce3ce26a78f954e4ddedb602be47949e092 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forward.cy.ts @@ -28,144 +28,162 @@ import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main. import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { exist, haveText, haveValue, notExist } from '../../../support/cypress.util'; -import { FORWARDING_INVALID_EMAIL, FORWARDING_TEST_EMAIL, VORGANG_ZUSTAENDIGE_STELLE_EMAIL } from '../../../support/data.util'; +import { + FORWARDING_INVALID_EMAIL, + FORWARDING_TEST_EMAIL, + VORGANG_ZUSTAENDIGE_STELLE_EMAIL, +} from '../../../support/data.util'; import { loginAsEmil } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; describe.skip('Vorgang forward', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const forwardingContainer: VorgangForwardingE2EComponent = vorgangPage.getForwardingContainer(); - - const vorgang: VorgangE2E = { ...createVorgang(), name: 'TestVorgangRedirectSpinner' }; - const vorgangEmpty: VorgangE2E = buildVorgang(objectIds[0], 'TestVorgangRedirectEmpty'); - - before(() => { - initVorgaenge([vorgang, vorgangEmpty]); - - loginAsEmil(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('after click on vorgang', () => { - - it('should show vorgang header', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should show forwarding', () => { - exist(forwardingContainer.getRoot()); - }) - - it('should be prefilled', () => { - haveValue(forwardingContainer.getFormular().getZustaendigeStelle(), VORGANG_ZUSTAENDIGE_STELLE_EMAIL); - }) - }) - - describe('fill forward formular', () => { - - describe('with email domain NOT in landesnetz', () => { - - it('should show validation message for invalid password', () => { - const forwardFormular = forwardingContainer.getFormular(); - forwardFormular.getZustaendigeStelle().clear().type(FORWARDING_INVALID_EMAIL);//TODO create valid email-address without adding it to landesnetzlist - forwardFormular.getPasswort().clear().type('zukurz'); - - forwardFormular.forward(); - waitForSpinnerToDisappear(); - - exist(forwardFormular.getPasswortError()); - }) - - it('should show validation message for invalid email', () => { - const forwardFormular = forwardingContainer.getFormular(); - forwardFormular.getZustaendigeStelle().clear().type(FORWARDING_INVALID_EMAIL); - - forwardFormular.forward(); - waitForSpinnerToDisappear(); - - exist(forwardFormular.getZustaendigeStelleError()); - }) - }) - - describe('with email domain in landesnetz', () => { - - it('should send formular with landesnetz email and empty password', () => { - const forwardFormular = forwardingContainer.getFormular(); - forwardFormular.getZustaendigeStelle().clear().type(FORWARDING_TEST_EMAIL); - forwardFormular.getPasswort().clear(); - - forwardFormular.forward(); - - exist(forwardingContainer.getSpinner()); - }) - }) - }) - - describe('success forwarding', () => { - - it('should have status ' + vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET], { defaultCommandTimeout: 30000 }, () => { - waitForSpinnerToDisappear(); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET]) - }) - - it('should show forward success text', () => { - exist(forwardingContainer.getForwardingSuccessMessage()); - }) - - it('should show "mark as success" button', () => { - exist(forwardingContainer.getMarkAsSuccessButton()); - }) - - it('should NOT show formular', () => { - notExist(forwardingContainer.getFormular().getRoot()); - }) - - it('should show "zustellung success message" after click on button', () => { - forwardingContainer.getMarkAsSuccessButton().click(); - waitForSpinnerToDisappear(); - - exist(forwardingContainer.getForwardingSuccessMessage()); - }) - }) - - describe('switch to list view', () => { - - it('should have status ' + vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET] + ' in list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - haveText(vorgangList.getListItem(vorgang.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET]); - }) - }) - - describe('change to non forwarding vorgang', () => { - - it('should formular after switching vorgang without pending commands', () => { - vorgangList.getListItem(vorgangEmpty.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(forwardingContainer.getRoot()); - }) - - it('should show forward formular', () => { - exist(forwardingContainer.getFormular().getRoot()); - }) - - it('sould not show forwarding success text', () => { - notExist(forwardingContainer.getForwardingSuccessMessage()); - }) - }) -}) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const forwardingContainer: VorgangForwardingE2EComponent = vorgangPage.getForwardingContainer(); + + const vorgang: VorgangE2E = { ...createVorgang(), name: 'TestVorgangRedirectSpinner' }; + const vorgangEmpty: VorgangE2E = buildVorgang(objectIds[0], 'TestVorgangRedirectEmpty'); + + before(() => { + initVorgaenge([vorgang, vorgangEmpty]); + + loginAsEmil(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('after click on vorgang', () => { + it('should show vorgang header', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should show forwarding', () => { + exist(forwardingContainer.getRoot()); + }); + + it('should be prefilled', () => { + haveValue( + forwardingContainer.getFormular().getZustaendigeStelle(), + VORGANG_ZUSTAENDIGE_STELLE_EMAIL, + ); + }); + }); + + describe('fill forward formular', () => { + describe('with email domain NOT in landesnetz', () => { + it('should show validation message for invalid password', () => { + const forwardFormular = forwardingContainer.getFormular(); + forwardFormular.getZustaendigeStelle().clear().type(FORWARDING_INVALID_EMAIL); //TODO create valid email-address without adding it to landesnetzlist + forwardFormular.getPasswort().clear().type('zukurz'); + + forwardFormular.forward(); + waitForSpinnerToDisappear(); + + exist(forwardFormular.getPasswortError()); + }); + + it('should show validation message for invalid email', () => { + const forwardFormular = forwardingContainer.getFormular(); + forwardFormular.getZustaendigeStelle().clear().type(FORWARDING_INVALID_EMAIL); + + forwardFormular.forward(); + waitForSpinnerToDisappear(); + + exist(forwardFormular.getZustaendigeStelleError()); + }); + }); + + describe('with email domain in landesnetz', () => { + it('should send formular with landesnetz email and empty password', () => { + const forwardFormular = forwardingContainer.getFormular(); + forwardFormular.getZustaendigeStelle().clear().type(FORWARDING_TEST_EMAIL); + forwardFormular.getPasswort().clear(); + + forwardFormular.forward(); + + exist(forwardingContainer.getSpinner()); + }); + }); + }); + + describe('success forwarding', () => { + it( + 'should have status ' + vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET], + { defaultCommandTimeout: 30000 }, + () => { + waitForSpinnerToDisappear(); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET], + ); + }, + ); + + it('should show forward success text', () => { + exist(forwardingContainer.getForwardingSuccessMessage()); + }); + + it('should show "mark as success" button', () => { + exist(forwardingContainer.getMarkAsSuccessButton()); + }); + + it('should NOT show formular', () => { + notExist(forwardingContainer.getFormular().getRoot()); + }); + + it('should show "zustellung success message" after click on button', () => { + forwardingContainer.getMarkAsSuccessButton().click(); + waitForSpinnerToDisappear(); + + exist(forwardingContainer.getForwardingSuccessMessage()); + }); + }); + + describe('switch to list view', () => { + it( + 'should have status ' + vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET] + ' in list', + () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + haveText( + vorgangList.getListItem(vorgang.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET], + ); + }, + ); + }); + + describe('change to non forwarding vorgang', () => { + it('should formular after switching vorgang without pending commands', () => { + vorgangList.getListItem(vorgangEmpty.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(forwardingContainer.getRoot()); + }); + + it('should show forward formular', () => { + exist(forwardingContainer.getFormular().getRoot()); + }); + + it('sould not show forwarding success text', () => { + notExist(forwardingContainer.getForwardingSuccessMessage()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forwarding-failed-cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forwarding-failed-cy.ts index c9524c7b552faa1a38cc2be05af36af1212c35ff..9d7b7fdee95f2933de9299ca8f60c01a35097204 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forwarding-failed-cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-forwarding-failed-cy.ts @@ -33,100 +33,105 @@ import { loginAsEmil } from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; describe('Vorgang forwarding failed', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const forwardingContainer: VorgangForwardingE2EComponent = vorgangPage.getForwardingContainer(); - - const vorgang: VorgangE2E = createVorgang(); - - before(() => { - initVorgang(vorgang); - - loginAsEmil(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('after click on vorgang', () => { - - it('should show vorgang header', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should show forwarding', () => { - exist(forwardingContainer.getRoot()); - }) - }) - - describe('fill forward formular', () => { - - it('should show spinner with text on valid formular', { defaultCommandTimeout: 30000 }, () => { - const formular = forwardingContainer.getFormular(); - formular.getZustaendigeStelle().clear().type(FORWARDING_TEST_EMAIL); - formular.getPasswort().clear().type('validespasswort'); - - formular.forward(); - - exist(forwardingContainer.getSpinner()); - }) - }) - - describe('mark forwarding as fail', () => { - - it('should have status ' + vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET], () => { - waitForSpinnerToDisappear(); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET]) - }) - - it('should show forward success text', () => { - exist(forwardingContainer.getForwardingSuccessMessage()); - }) - - it('should show "mark as fail" button', () => { - exist(forwardingContainer.getMarkAsFailButton()); - }) - - it('should NOT show formular', () => { - notExist(forwardingContainer.getFormular().getRoot()); - }) - - it('should show "zustellung failed message" after click on button', () => { - forwardingContainer.getMarkAsFailButton().click(); - - exist(forwardingContainer.getFailedMessage()); - }) - - it('should show formular', () => { - exist(forwardingContainer.getFormular().getRoot()); - }) - - it('should hide mark as fail button', () => { - notExist(forwardingContainer.getMarkAsFailButton()); - }) - - it('should hide mark as success button', () => { - notExist(forwardingContainer.getMarkAsSuccessButton()); - }) - }) - - describe('switch to list view', () => { - - it('should have status ' + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG] + ' in list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - haveText(vorgangList.getListItem(vorgang.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const forwardingContainer: VorgangForwardingE2EComponent = vorgangPage.getForwardingContainer(); + + const vorgang: VorgangE2E = createVorgang(); + + before(() => { + initVorgang(vorgang); + + loginAsEmil(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('after click on vorgang', () => { + it('should show vorgang header', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should show forwarding', () => { + exist(forwardingContainer.getRoot()); + }); + }); + + describe('fill forward formular', () => { + it('should show spinner with text on valid formular', { defaultCommandTimeout: 30000 }, () => { + const formular = forwardingContainer.getFormular(); + formular.getZustaendigeStelle().clear().type(FORWARDING_TEST_EMAIL); + formular.getPasswort().clear().type('validespasswort'); + + formular.forward(); + + exist(forwardingContainer.getSpinner()); + }); + }); + + describe('mark forwarding as fail', () => { + it('should have status ' + vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET], () => { + waitForSpinnerToDisappear(); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.WEITERGELEITET], + ); + }); + + it('should show forward success text', () => { + exist(forwardingContainer.getForwardingSuccessMessage()); + }); + + it('should show "mark as fail" button', () => { + exist(forwardingContainer.getMarkAsFailButton()); + }); + + it('should NOT show formular', () => { + notExist(forwardingContainer.getFormular().getRoot()); + }); + + it('should show "zustellung failed message" after click on button', () => { + forwardingContainer.getMarkAsFailButton().click(); + + exist(forwardingContainer.getFailedMessage()); + }); + + it('should show formular', () => { + exist(forwardingContainer.getFormular().getRoot()); + }); + + it('should hide mark as fail button', () => { + notExist(forwardingContainer.getMarkAsFailButton()); + }); + + it('should hide mark as success button', () => { + notExist(forwardingContainer.getMarkAsSuccessButton()); + }); + }); + + describe('switch to list view', () => { + it( + 'should have status ' + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG] + ' in list', + () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + haveText( + vorgangList.getListItem(vorgang.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }, + ); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-loeschen-anfordern.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-loeschen-anfordern.cy.ts index 4859a6225f9bcbf322c734ad3261e171efcd9beb..91617d3639ed07f3107ce74e274de36b9d319262 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-loeschen-anfordern.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-loeschen-anfordern.cy.ts @@ -24,7 +24,12 @@ import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; @@ -33,219 +38,264 @@ import { loginAsEmil } from '../../../support/user-util'; import { buildVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; describe('Vorgang löschen anfordern', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangAbgeschlossenLoeschenAnfordern: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoAbgeschlossenLoeschenAnfordern'), status: VorgangStatusE2E.ABGESCHLOSSEN }; - const vorgangAbgeschlossenLoeschenAnfordernRevoke: VorgangE2E = { ...buildVorgang(objectIds[1], 'DoAbgeschlossenRevokeLoeschenAnfordern'), status: VorgangStatusE2E.ABGESCHLOSSEN }; - const vorgangVerworfenLoeschenAnfordern: VorgangE2E = { ...buildVorgang(objectIds[2], 'DoVerworfenLoeschenAnfordern'), status: VorgangStatusE2E.VERWORFEN }; - const vorgangVerworfenLoeschenAnfordernRevoke: VorgangE2E = { ...buildVorgang(objectIds[3], 'DoVerworfenRevokeLoeschenAnfordern'), status: VorgangStatusE2E.VERWORFEN }; - - before(() => { - initVorgaenge([vorgangAbgeschlossenLoeschenAnfordern, vorgangAbgeschlossenLoeschenAnfordernRevoke, vorgangVerworfenLoeschenAnfordern, vorgangVerworfenLoeschenAnfordernRevoke]); - - loginAsEmil(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('Abgeschlossen: löschen anfordern', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordern.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbgeschlossenLoeschenAnfordern.status]); - }) - - it('should show snackBar message', () => { - vorgangFormularButtons.getLoeschenAnfordernButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN) - }) - - it('should close snackBar', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status zu Löschen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status zu Löschen', () => { - haveText(vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordern.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN]); - }) - }) - }) - - describe('Abgeschlossen: löschen anfordern und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordernRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbgeschlossenLoeschenAnfordernRevoke.status]); - }) - - it('should show snackBar message', () => { - vorgangPage.getSubnavigation().getLoeschenAnfordernByIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Abgeschlossen', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Abgeschlossen', () => { - haveText(vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordernRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]) - }) - }) - }) - - describe('Verworfen: löschen anfordern', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangVerworfenLoeschenAnfordern.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Verworfen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangVerworfenLoeschenAnfordern.status]); - }) - - it('should show snackBar message', () => { - vorgangFormularButtons.getLoeschenAnfordernButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN) - }) - - it('should close snackBar', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status zu Löschen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status zu Löschen', () => { - haveText(vorgangList.getListItem(vorgangVerworfenLoeschenAnfordern.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN]); - }) - }) - }) - - describe('Verworfen: löschen anfordern und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - - vorgangList.getListItem(vorgangVerworfenLoeschenAnfordernRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Verworfen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangVerworfenLoeschenAnfordernRevoke.status]); - }) - - it('should show snackBar message', () => { - vorgangPage.getSubnavigation().getLoeschenAnfordernByIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Verworfen', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Verworfen', () => { - haveText(vorgangList.getListItem(vorgangVerworfenLoeschenAnfordernRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]) - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangAbgeschlossenLoeschenAnfordern: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoAbgeschlossenLoeschenAnfordern'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + const vorgangAbgeschlossenLoeschenAnfordernRevoke: VorgangE2E = { + ...buildVorgang(objectIds[1], 'DoAbgeschlossenRevokeLoeschenAnfordern'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + const vorgangVerworfenLoeschenAnfordern: VorgangE2E = { + ...buildVorgang(objectIds[2], 'DoVerworfenLoeschenAnfordern'), + status: VorgangStatusE2E.VERWORFEN, + }; + const vorgangVerworfenLoeschenAnfordernRevoke: VorgangE2E = { + ...buildVorgang(objectIds[3], 'DoVerworfenRevokeLoeschenAnfordern'), + status: VorgangStatusE2E.VERWORFEN, + }; + + before(() => { + initVorgaenge([ + vorgangAbgeschlossenLoeschenAnfordern, + vorgangAbgeschlossenLoeschenAnfordernRevoke, + vorgangVerworfenLoeschenAnfordern, + vorgangVerworfenLoeschenAnfordernRevoke, + ]); + + loginAsEmil(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('Abgeschlossen: löschen anfordern', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordern.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbgeschlossenLoeschenAnfordern.status], + ); + }); + + it('should show snackBar message', () => { + vorgangFormularButtons.getLoeschenAnfordernButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); + }); + + it('should close snackBar', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status zu Löschen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status zu Löschen', () => { + haveText( + vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordern.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN], + ); + }); + }); + }); + + describe('Abgeschlossen: löschen anfordern und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordernRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbgeschlossenLoeschenAnfordernRevoke.status], + ); + }); + + it('should show snackBar message', () => { + vorgangPage.getSubnavigation().getLoeschenAnfordernByIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Abgeschlossen', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Abgeschlossen', () => { + haveText( + vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordernRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + }); + }); + + describe('Verworfen: löschen anfordern', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangVerworfenLoeschenAnfordern.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Verworfen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangVerworfenLoeschenAnfordern.status], + ); + }); + + it('should show snackBar message', () => { + vorgangFormularButtons.getLoeschenAnfordernButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); + }); + + it('should close snackBar', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status zu Löschen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status zu Löschen', () => { + haveText( + vorgangList.getListItem(vorgangVerworfenLoeschenAnfordern.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN], + ); + }); + }); + }); + + describe('Verworfen: löschen anfordern und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangVerworfenLoeschenAnfordernRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Verworfen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangVerworfenLoeschenAnfordernRevoke.status], + ); + }); + + it('should show snackBar message', () => { + vorgangPage.getSubnavigation().getLoeschenAnfordernByIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Verworfen', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Verworfen', () => { + haveText( + vorgangList.getListItem(vorgangVerworfenLoeschenAnfordernRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-verwerfen.ea.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-verwerfen.ea.cy.ts index 29b2ff15afe3b97f142010da9a536eb5dbd30626..20afc2819837bb8c13c621513d4f538a06fd8b6c 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-verwerfen.ea.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-verwerfen.ea.cy.ts @@ -27,10 +27,20 @@ import localeDeExtra from '@angular/common/locales/extra/de'; import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { dropCollections } from 'apps/alfa-e2e/src/support/cypress-helper'; import { loginAsEmil } from 'apps/alfa-e2e/src/support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from 'apps/alfa-e2e/src/support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from 'apps/alfa-e2e/src/support/vorgang-util'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; @@ -38,131 +48,146 @@ import { contains, exist, haveText, notExist } from '../../../support/cypress.ut registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Verwerfen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangVerwerfen: VorgangE2E = { ...createVorgang(), name: 'DoVerwerfen' }; - const vorgangVerwerfenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeVerwerfen') }; - - before(() => { - initVorgaenge([vorgangVerwerfen, vorgangVerwerfenRevoke]); - - loginAsEmil(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('verwerfen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangVerwerfen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Neu', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangVerwerfen.status]); - }) - - it('should show snackBar message', () => { - vorgangFormularButtons.getVerwerfenButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN); - }) - - it('should close snackBar on close button', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getMessage()); - }) - - it('should have status Verworfen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]); - }) - - it('should have button zurückholen', () => { - exist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); - exist(vorgangFormularButtons.getZurueckholenButton()); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Verworfen', () => { - haveText(vorgangList.getListItem(vorgangVerwerfen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]); - }) - }) - }) - - describe('verwerfen und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangVerwerfenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Neu', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangVerwerfenRevoke.status]); - }) - - it('should show snackBar', () => { - vorgangPage.getSubnavigation().getVerwerfenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN); - }) - - it('should close snackbar on revoke', () => { - snackbar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackbar.getMessage()); - }) - - it('should show status Neu after progressbar dissapear', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]); - }) - - it('should not have button zurückholen', () => { - notExist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); - notExist(vorgangFormularButtons.getZurueckholenButton()); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Neu', () => { - haveText(vorgangList.getListItem(vorgangVerwerfenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]); - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangVerwerfen: VorgangE2E = { ...createVorgang(), name: 'DoVerwerfen' }; + const vorgangVerwerfenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeVerwerfen') }; + + before(() => { + initVorgaenge([vorgangVerwerfen, vorgangVerwerfenRevoke]); + + loginAsEmil(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('verwerfen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangVerwerfen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Neu', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangVerwerfen.status], + ); + }); + + it('should show snackBar message', () => { + vorgangFormularButtons.getVerwerfenButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN); + }); + + it('should close snackBar on close button', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getMessage()); + }); + + it('should have status Verworfen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + + it('should have button zurückholen', () => { + exist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); + exist(vorgangFormularButtons.getZurueckholenButton()); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Verworfen', () => { + haveText( + vorgangList.getListItem(vorgangVerwerfen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + }); + }); + + describe('verwerfen und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangVerwerfenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Neu', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangVerwerfenRevoke.status], + ); + }); + + it('should show snackBar', () => { + vorgangPage.getSubnavigation().getVerwerfenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN); + }); + + it('should close snackbar on revoke', () => { + snackbar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackbar.getMessage()); + }); + + it('should show status Neu after progressbar dissapear', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.NEU], + ); + }); + + it('should not have button zurückholen', () => { + notExist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); + notExist(vorgangFormularButtons.getZurueckholenButton()); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Neu', () => { + haveText( + vorgangList.getListItem(vorgangVerwerfenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.NEU], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-wiedereroeffnen.ea.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-wiedereroeffnen.ea.cy.ts index 48afb65b1a8b419fb30597fc723be5612e23c229..24108803003bd16018090b7b71ee0e9a6180c29d 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-wiedereroeffnen.ea.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-wiedereroeffnen.ea.cy.ts @@ -24,133 +24,165 @@ import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { dropCollections } from 'apps/alfa-e2e/src/support/cypress-helper'; import { loginAsEmil } from 'apps/alfa-e2e/src/support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from 'apps/alfa-e2e/src/support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from 'apps/alfa-e2e/src/support/vorgang-util'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; describe('Vorgang wiedereroeffnen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangAbgeschlossenWiedereroeffnen: VorgangE2E = { ...createVorgang(), name: 'DoWiedereroeffnenOnAbgeschlossen', status: VorgangStatusE2E.ABGESCHLOSSEN }; - const vorgangAbgeschlossenWiedereroeffnenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeWiedereroeffnenOnAbgeschlossen'), status: VorgangStatusE2E.ABGESCHLOSSEN }; - - before(() => { - initVorgaenge([vorgangAbgeschlossenWiedereroeffnen, vorgangAbgeschlossenWiedereroeffnenRevoke]); - - loginAsEmil(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('vorgang in status abgeschlossen', () => { - - describe('wiedereroeffnen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbgeschlossenWiedereroeffnen.status]); - }) - - it('should show snackBar', () => { - vorgangFormularButtons.getWiedereroeffnenButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); - }) - - it('should close snackBar on close', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getMessage()); - }) - - it('should have status In Bearbeitung', () => { - vorgangPage.getVorgangDetailHeader().getStatus().should('exist').should('have.text', vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status In Bearbeitung', () => { - haveText(vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - }) - }) - - describe('wiedereroeffnen und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbgeschlossenWiedereroeffnenRevoke.status]); - }) - - it('should show snackBar', () => { - vorgangPage.getSubnavigation().getWiedereroeffnenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); - }) - - it('should close snackbar on revoke', () => { - snackbar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackbar.getMessage()); - }) - - it('should show status Abgeschlossen after progressbar dissapear', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Abgeschlossen', () => { - haveText(vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangAbgeschlossenWiedereroeffnen: VorgangE2E = { + ...createVorgang(), + name: 'DoWiedereroeffnenOnAbgeschlossen', + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + const vorgangAbgeschlossenWiedereroeffnenRevoke: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoRevokeWiedereroeffnenOnAbgeschlossen'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + + before(() => { + initVorgaenge([vorgangAbgeschlossenWiedereroeffnen, vorgangAbgeschlossenWiedereroeffnenRevoke]); + + loginAsEmil(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('vorgang in status abgeschlossen', () => { + describe('wiedereroeffnen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbgeschlossenWiedereroeffnen.status], + ); + }); + + it('should show snackBar', () => { + vorgangFormularButtons.getWiedereroeffnenButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); + }); + + it('should close snackBar on close', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getMessage()); + }); + + it('should have status In Bearbeitung', () => { + vorgangPage + .getVorgangDetailHeader() + .getStatus() + .should('exist') + .should('have.text', vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status In Bearbeitung', () => { + haveText( + vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + }); + }); + + describe('wiedereroeffnen und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbgeschlossenWiedereroeffnenRevoke.status], + ); + }); + + it('should show snackBar', () => { + vorgangPage.getSubnavigation().getWiedereroeffnenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); + }); + + it('should close snackbar on revoke', () => { + snackbar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackbar.getMessage()); + }); + + it('should show status Abgeschlossen after progressbar dissapear', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Abgeschlossen', () => { + haveText( + vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-zurueckholen.ea.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-zurueckholen.ea.cy.ts index d8da31039437a68e5c2b335c6a8b6622f646c632..87bb746118e04d2ca4abf142f3093f3d213a2440 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-zurueckholen.ea.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-detail/vorgang-zurueckholen.ea.cy.ts @@ -27,10 +27,20 @@ import localeDeExtra from '@angular/common/locales/extra/de'; import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { dropCollections } from 'apps/alfa-e2e/src/support/cypress-helper'; import { loginAsEmil } from 'apps/alfa-e2e/src/support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from 'apps/alfa-e2e/src/support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from 'apps/alfa-e2e/src/support/vorgang-util'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; @@ -38,130 +48,152 @@ import { contains, exist, haveText, notExist } from '../../../support/cypress.ut registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Zurueckholen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangZurueckholen: VorgangE2E = { ...createVorgang(), name: 'DoZurueckholen', status: VorgangStatusE2E.VERWORFEN }; - const vorgangZurueckholenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeZurueckholen'), status: VorgangStatusE2E.VERWORFEN }; - - before(() => { - initVorgaenge([vorgangZurueckholen, vorgangZurueckholenRevoke]) - - loginAsEmil(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('Zurueckholen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangZurueckholen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Verworfen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZurueckholen.status]); - }) - - it('should show snackBar', () => { - vorgangFormularButtons.getZurueckholenButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT); - }) - - it('should close snackBar on close button', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status Neu', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]); - }) - - it('should have button annehmen und verwerfen', () => { - exist(vorgangFormularButtons.getVerwerfenButton()); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Neu', () => { - haveText(vorgangList.getListItem(vorgangZurueckholen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]); - }) - }) - }) - - describe('Zurueckholen und rueckgaengig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangZurueckholenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Neu', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZurueckholenRevoke.status]); - }) - - it('should show snackBar', () => { - vorgangPage.getSubnavigation().getZurueckholenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Verworfen after progressbar dissapear', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]); - }) - - it('should have button zurueckholen', () => { - exist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); - exist(vorgangFormularButtons.getZurueckholenButton()); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Verworfen', () => { - haveText(vorgangList.getListItem(vorgangZurueckholenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]); - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangZurueckholen: VorgangE2E = { + ...createVorgang(), + name: 'DoZurueckholen', + status: VorgangStatusE2E.VERWORFEN, + }; + const vorgangZurueckholenRevoke: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoRevokeZurueckholen'), + status: VorgangStatusE2E.VERWORFEN, + }; + + before(() => { + initVorgaenge([vorgangZurueckholen, vorgangZurueckholenRevoke]); + + loginAsEmil(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('Zurueckholen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangZurueckholen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Verworfen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangZurueckholen.status], + ); + }); + + it('should show snackBar', () => { + vorgangFormularButtons.getZurueckholenButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT); + }); + + it('should close snackBar on close button', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status Neu', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.NEU], + ); + }); + + it('should have button annehmen und verwerfen', () => { + exist(vorgangFormularButtons.getVerwerfenButton()); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Neu', () => { + haveText( + vorgangList.getListItem(vorgangZurueckholen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.NEU], + ); + }); + }); + }); + + describe('Zurueckholen und rueckgaengig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangZurueckholenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Neu', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangZurueckholenRevoke.status], + ); + }); + + it('should show snackBar', () => { + vorgangPage.getSubnavigation().getZurueckholenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Verworfen after progressbar dissapear', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + + it('should have button zurueckholen', () => { + exist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); + exist(vorgangFormularButtons.getZurueckholenButton()); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Verworfen', () => { + haveText( + vorgangList.getListItem(vorgangZurueckholenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-list/vorgang-list-ea.search.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-list/vorgang-list-ea.search.cy.ts index 2576383938c45747ad147b95813e713e76b6ecce..34230fb57065648c979fd6516eb19d98b73551cf 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-list/vorgang-list-ea.search.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/einheitlicher-ansprechpartner/vorgang-list/vorgang-list-ea.search.cy.ts @@ -30,69 +30,88 @@ import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections, dropSearchIndex } from '../../../support/cypress-helper'; import { enterWith, exist, notExist } from '../../../support/cypress.util'; import { UserRoleE2E, loginAsEmil } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initSearchIndex, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initSearchIndex, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; describe('VorgangList Suche for EA User', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const header: HeaderE2EComponent = mainPage.getHeader(); - - const vorgangPage: VorgangPage = new VorgangPage(); - - const requestId: string = '20201118365670866102'; - const eingangHeader: EingangHeaderE2E = { ...createVorgang().eingangs[0].header }; - const eingang: EingangE2E = { ...createVorgang().eingangs[0], header: { ...eingangHeader, requestId } } - const vorgangToStay: VorgangE2E = { ...createVorgang(), name: 'VorgangToStay', eingangs: [eingang] }; - - const vorgangToDisappear: VorgangE2E = { ...buildVorgang(objectIds[1], 'VorgangToDisappear'), status: VorgangStatusE2E.NEU }; - - // TODO initSearchIndex() needs to wait for ElastiSearch - unskip once OZG-4453 is implemented - describe.skip(`on user with role ${UserRoleE2E.EINHEITLICHER_ANSPRECHPARTNER}`, () => { - - const vorgangStayInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangToStay.name); - const vorgangDisappearInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangToDisappear.name); - - before(() => { - initVorgaenge([vorgangToStay, vorgangToDisappear]) - - initSearchIndex([vorgangToStay, vorgangToDisappear]) - - loginAsEmil(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - dropSearchIndex(); - }) - - it('should filter list', () => { - doSearch(); - waitForSpinnerToDisappear(); - - exist(vorgangStayInList.getRoot()); - notExist(vorgangDisappearInList.getRoot()); - }) - - it('should show filtered list after navigate to vorgang detail and back', () => { - doSearch(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - vorgangStayInList.getRoot().click(); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - exist(vorgangStayInList.getRoot()); - notExist(vorgangDisappearInList.getRoot()); - }) - - function doSearch(): void { - enterWith(header.getVorgangSearch().getInput(), vorgangToStay.name); - } - }) -}); \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const header: HeaderE2EComponent = mainPage.getHeader(); + + const vorgangPage: VorgangPage = new VorgangPage(); + + const requestId: string = '20201118365670866102'; + const eingangHeader: EingangHeaderE2E = { ...createVorgang().eingangs[0].header }; + const eingang: EingangE2E = { + ...createVorgang().eingangs[0], + header: { ...eingangHeader, requestId }, + }; + const vorgangToStay: VorgangE2E = { + ...createVorgang(), + name: 'VorgangToStay', + eingangs: [eingang], + }; + + const vorgangToDisappear: VorgangE2E = { + ...buildVorgang(objectIds[1], 'VorgangToDisappear'), + status: VorgangStatusE2E.NEU, + }; + + // TODO initSearchIndex() needs to wait for ElastiSearch - unskip once OZG-4453 is implemented + describe.skip(`on user with role ${UserRoleE2E.EINHEITLICHER_ANSPRECHPARTNER}`, () => { + const vorgangStayInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangToStay.name, + ); + const vorgangDisappearInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangToDisappear.name, + ); + + before(() => { + initVorgaenge([vorgangToStay, vorgangToDisappear]); + + initSearchIndex([vorgangToStay, vorgangToDisappear]); + + loginAsEmil(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + dropSearchIndex(); + }); + + it('should filter list', () => { + doSearch(); + waitForSpinnerToDisappear(); + + exist(vorgangStayInList.getRoot()); + notExist(vorgangDisappearInList.getRoot()); + }); + + it('should show filtered list after navigate to vorgang detail and back', () => { + doSearch(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + vorgangStayInList.getRoot().click(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + exist(vorgangStayInList.getRoot()); + notExist(vorgangDisappearInList.getRoot()); + }); + + function doSearch(): void { + enterWith(header.getVorgangSearch().getInput(), vorgangToStay.name); + } + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/accessibility/vorgang-list.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/accessibility/vorgang-list.cy.ts index b49d3d56c4c4e76db0731457e3390bd5bde3eb29..3b5f5ab65bbc9e3d70d92b585b1b03739e5456fa 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/accessibility/vorgang-list.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/accessibility/vorgang-list.cy.ts @@ -7,157 +7,156 @@ import { MainPage, waitForSpinnerToDisappear } from 'apps/alfa-e2e/src/page-obje import { isKeyboardFocused } from 'apps/alfa-e2e/src/support/angular.util'; import { dropCollections, pressTab } from 'apps/alfa-e2e/src/support/cypress-helper'; import { exist, haveFocus } from 'apps/alfa-e2e/src/support/cypress.util'; -import { getUserManagerUserSabine, initUsermanagerUsers, loginAsSabine } from 'apps/alfa-e2e/src/support/user-util'; +import { + getUserManagerUserSabine, + initUsermanagerUsers, + loginAsSabine, +} from 'apps/alfa-e2e/src/support/user-util'; describe('VorgangList Page', () => { - const mainPage: MainPage = new MainPage(); - const header: HeaderE2EComponent = mainPage.getHeader(); - const vorgangSearch: VorgangSearchE2EComponent = header.getVorgangSearch(); + const mainPage: MainPage = new MainPage(); + const header: HeaderE2EComponent = mainPage.getHeader(); + const vorgangSearch: VorgangSearchE2EComponent = header.getVorgangSearch(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const views: VorgangViewsE2EComponent = mainPage.getViews(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const views: VorgangViewsE2EComponent = mainPage.getViews(); - const navigation: NavigationE2EComponent = mainPage.getNavigation(); + const navigation: NavigationE2EComponent = mainPage.getNavigation(); - before(() => { - initUsermanagerUsers([getUserManagerUserSabine()]); + before(() => { + initUsermanagerUsers([getUserManagerUserSabine()]); - loginAsSabine(); + loginAsSabine(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('initial', () => { + describe('initial', () => { + it('should select header logo as start element', () => { + header.getLogo().click(); - it('should select header logo as start element', () => { - header.getLogo().click(); + //TODO Pruefung ergaenzen + }); + }); - //TODO Pruefung ergaenzen - }) - }) + describe('Tab through', () => { + describe('header', () => { + it('should focus search button', () => { + pressTab(); - describe('Tab through', () => { + isKeyboardFocused(vorgangSearch.getSearchButton()); + }); - describe('header', () => { + it('should focus search field', () => { + pressTab(); - it('should focus search button', () => { - pressTab(); + haveFocus(vorgangSearch.getInput()); + }); - isKeyboardFocused(vorgangSearch.getSearchButton()); - }) + it('should focus help menu icon', () => { + pressTab(); - it('should focus search field', () => { - pressTab(); + isKeyboardFocused(header.getHelpMenu().getButton()); + }); - haveFocus(vorgangSearch.getInput()); - }) + it('should focus settings icon', () => { + pressTab(); - it('should focus help menu icon', () => { - pressTab(); + isKeyboardFocused(header.getUserSettings().getButton()); + }); - isKeyboardFocused(header.getHelpMenu().getButton()); - }) + it('should focus user icon', () => { + pressTab(); - it('should focus settings icon', () => { - pressTab(); + isKeyboardFocused(header.getCurrentUserProfile().getUserIconButton()); + }); + }); - isKeyboardFocused(header.getUserSettings().getButton()); - }) + describe('subnavigation', () => { + it('should focus Meine filter', () => { + pressTab(); - it('should focus user icon', () => { - pressTab(); + isKeyboardFocused(navigation.getMeineVorgaengeFilter()); + }); - isKeyboardFocused(header.getCurrentUserProfile().getUserIconButton()); - }) - }) + it('should focus Alle filter', () => { + pressTab(); - describe('subnavigation', () => { + isKeyboardFocused(navigation.getAlleFilter()); + }); - it('should focus Meine filter', () => { - pressTab(); + it('should focus Nicht zugewiesen filter', () => { + pressTab(); - isKeyboardFocused(navigation.getMeineVorgaengeFilter()); - }) + isKeyboardFocused(navigation.getNichtZugewiesenFilter()); + }); + }); - it('should focus Alle filter', () => { - pressTab(); + describe('views', () => { + it('should focus Neu view', () => { + pressTab(); - isKeyboardFocused(navigation.getAlleFilter()); - }) + isKeyboardFocused(views.getNeu().getButton()); + }); - it('should focus Nicht zugewiesen filter', () => { - pressTab(); + it('should focus Angenommen view', () => { + pressTab(); - isKeyboardFocused(navigation.getNichtZugewiesenFilter()); - }) - }) + isKeyboardFocused(views.getAngenommen().getButton()); + }); - describe('views', () => { + it('should focus InBearbeitung view', () => { + pressTab(); - it('should focus Neu view', () => { - pressTab(); + isKeyboardFocused(views.getInBearbeitung().getButton()); + }); - isKeyboardFocused(views.getNeu().getButton()); - }) + it('should focus Beschieden view', () => { + pressTab(); - it('should focus Angenommen view', () => { - pressTab(); + isKeyboardFocused(views.getBeschieden().getButton()); + }); - isKeyboardFocused(views.getAngenommen().getButton()); - }) + it('should focus Abgeschlossen view', () => { + pressTab(); - it('should focus InBearbeitung view', () => { - pressTab(); + isKeyboardFocused(views.getAbgeschlossen().getButton()); + }); - isKeyboardFocused(views.getInBearbeitung().getButton()); - }) + it('should focus Verworfen view', () => { + pressTab(); - it('should focus Beschieden view', () => { - pressTab(); + isKeyboardFocused(views.getVerworfen().getButton()); + }); - isKeyboardFocused(views.getBeschieden().getButton()); - }) + it('should focus Zu Löschen view', () => { + pressTab(); - it('should focus Abgeschlossen view', () => { - pressTab(); + isKeyboardFocused(views.getZuLoeschen().getButton()); + }); - isKeyboardFocused(views.getAbgeschlossen().getButton()); - }) + it('should focus Wiedervorlagen view', () => { + pressTab(); - it('should focus Verworfen view', () => { - pressTab(); + isKeyboardFocused(views.getWiedervorlagen().getButton()); + }); - isKeyboardFocused(views.getVerworfen().getButton()); - }) + it('should focus VorgangList view', () => { + pressTab(); - it('should focus Zu Löschen view', () => { - pressTab(); + isKeyboardFocused(views.getVorgangList().getButton()); + }); - isKeyboardFocused(views.getZuLoeschen().getButton()); - }) + it('should focus Suche view', () => { + pressTab(); - it('should focus Wiedervorlagen view', () => { - pressTab(); - - isKeyboardFocused(views.getWiedervorlagen().getButton()); - }) - - it('should focus VorgangList view', () => { - pressTab(); - - isKeyboardFocused(views.getVorgangList().getButton()); - }) - - it('should focus Suche view', () => { - pressTab(); - - isKeyboardFocused(views.getSuche().getButton()); - }) - }) - }) -}) \ No newline at end of file + isKeyboardFocused(views.getSuche().getButton()); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/app/buildinfo.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/app/buildinfo.cy.ts index 1e75530843d855592a511e2c7c0eb3520e3e738d..c3ede2ca93ade1ae7056d52e9bc2275f12d9cf96 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/app/buildinfo.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/app/buildinfo.cy.ts @@ -29,31 +29,28 @@ import { exist } from 'apps/alfa-e2e/src/support/cypress.util'; import { loginAsSabine } from 'apps/alfa-e2e/src/support/user-util'; describe('Buildinfo', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const buildInfo: BuildInfoE2EComponent = mainPage.getBuildInfo(); - - before(() => { - loginAsSabine(); - }) - - after(() => { - dropCollections(); - }) - - describe('after login', () => { - - it('should show vorgangList', { defaultCommandTimeout: 30000 }, () => { - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - }) - - describe('buildinfo', () => { - - it('should show version', () => { - exist(buildInfo.getVersion()); - }) - - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const buildInfo: BuildInfoE2EComponent = mainPage.getBuildInfo(); + + before(() => { + loginAsSabine(); + }); + + after(() => { + dropCollections(); + }); + + describe('after login', () => { + it('should show vorgangList', { defaultCommandTimeout: 30000 }, () => { + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + }); + + describe('buildinfo', () => { + it('should show version', () => { + exist(buildInfo.getVersion()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/app/login-logout.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/app/login-logout.cy.ts index 846645d7008985a89636caf40406a4eb0739ea71..3bff01163b44e2400ebb80bb3d9305a87afbe78d 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/app/login-logout.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/app/login-logout.cy.ts @@ -31,41 +31,44 @@ import { exist } from '../../../support/cypress.util'; import { getUserSabine } from '../../../support/user-util'; describe('Login and Logout', () => { + const app: App = getApp(); + const user: UserE2E = getUserSabine(); - const app: App = getApp(); - const user: UserE2E = getUserSabine(); + const mainPage: MainPage = new MainPage(); + const header: HeaderE2EComponent = mainPage.getHeader(); - const mainPage: MainPage = new MainPage(); - const header: HeaderE2EComponent = mainPage.getHeader(); + before(() => { + cy.logout(); + }); - before(() => { - cy.logout(); - }) + it('login as test user', () => { + cy.visit('') + .get('#kc-login') + .should('exist') + .get('#username') + .type(user.name) + .get('#password') + .type(user.password) + .get('#kc-login') + .click(); + }); - it('login as test user', () => { - cy.visit('') - .get('#kc-login').should('exist') - .get('#username').type(user.name) - .get('#password').type(user.password) - .get('#kc-login').click(); - }) + it('should display Alfa logo', () => { + waitForSpinnerToDisappear(); - it('should display Alfa logo', () => { - waitForSpinnerToDisappear(); + exist(header.getLogo()); + }); - exist(header.getLogo()); - }) + it('should keep user logged in on reload page', () => { + reload(); + waitForSpinnerToDisappear(); - it('should keep user logged in on reload page', () => { - reload(); - waitForSpinnerToDisappear(); + exist(header.getLogo()); + }); - exist(header.getLogo()); - }) + it('should logout', () => { + header.getCurrentUserProfile().logout(); - it('should logout', () => { - header.getCurrentUserProfile().logout(); - - exist(cy.get('#kc-login')); - }) -}); \ No newline at end of file + exist(cy.get('#kc-login')); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/hint/no-organisations-einheit-id.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/hint/no-organisations-einheit-id.cy.ts index 4d6f23f6071087c579b04c58fce4fcf483655a93..bbedd9540fd9237b8a62483242ecd3dd1ac70a61 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/hint/no-organisations-einheit-id.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/hint/no-organisations-einheit-id.cy.ts @@ -27,49 +27,67 @@ import { EingangE2E, VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { dropCollections } from '../../../support/cypress-helper'; import { exist, notExist } from '../../../support/cypress.util'; -import { ORGANISATIONSEINHEITEN_ID_FOR_KFINDER, ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } from '../../../support/data.util'; +import { + ORGANISATIONSEINHEITEN_ID_FOR_KFINDER, + ORGANISATIONSEINHEITEN_ID_FOR_KORDNER, +} from '../../../support/data.util'; import { loginAsZonk } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; describe('VorgangList', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const hint: HintE2EComponent = mainPage.getHint(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const hint: HintE2EComponent = mainPage.getHint(); - const eingangForKFinder: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KFINDER } }; - const vorgangForKFinder: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangVisibleToKFinder'), eingangs: [eingangForKFinder] }; + const eingangForKFinder: EingangE2E = { + ...createVorgang().eingangs[0], + zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KFINDER }, + }; + const vorgangForKFinder: VorgangE2E = { + ...buildVorgang(objectIds[0], 'VorgangVisibleToKFinder'), + eingangs: [eingangForKFinder], + }; - const eingangForKOrdner: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } }; - const vorgangForKOrdner: VorgangE2E = { ...buildVorgang(objectIds[1], 'VorgangVisibleToKOrdner'), eingangs: [eingangForKOrdner] }; + const eingangForKOrdner: EingangE2E = { + ...createVorgang().eingangs[0], + zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KORDNER }, + }; + const vorgangForKOrdner: VorgangE2E = { + ...buildVorgang(objectIds[1], 'VorgangVisibleToKOrdner'), + eingangs: [eingangForKOrdner], + }; - before(() => { - initVorgaenge([vorgangForKFinder, vorgangForKOrdner]); - }) + before(() => { + initVorgaenge([vorgangForKFinder, vorgangForKOrdner]); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('Vorgänge by user zonk', () => { + describe('Vorgänge by user zonk', () => { + const vorgang: VorgangE2E = createVorgang(); - const vorgang: VorgangE2E = createVorgang(); + before(() => { + loginAsZonk(); - before(() => { - loginAsZonk(); + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + it('should not show Vorgänge', () => { + notExist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot()); + notExist(vorgangList.getListItem(vorgangForKFinder.name).getRoot()); + notExist(vorgangList.getListItem(vorgang.name).getRoot()); + }); - it('should not show Vorgänge', () => { - notExist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot()); - notExist(vorgangList.getListItem(vorgangForKFinder.name).getRoot()); - notExist(vorgangList.getListItem(vorgang.name).getRoot()); - }) - - it('should show noOrganisationId hint', () => { - exist(hint.getNoOrganisationId()); - }) - }) - -}) \ No newline at end of file + it('should show noOrganisationId hint', () => { + exist(hint.getNoOrganisationId()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/historie/historie.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/historie/historie.cy.ts index 493a03c50135410cddc764a41f799763f3374855..0a2d037e60b722045c7ebe29917c8360606b8eca 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/historie/historie.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/historie/historie.cy.ts @@ -24,9 +24,18 @@ import { registerLocaleData } from '@angular/common'; import localeDe from '@angular/common/locales/de'; import localeDeExtra from '@angular/common/locales/extra/de'; -import { KommentarHistorieItemE2EComponent, PostfachNachrichtHistorieItemE2EComponent, VorgangFormularDatenHistorieItemE2EComponent, WiedervorlageHistorieItemE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component'; +import { + KommentarHistorieItemE2EComponent, + PostfachNachrichtHistorieItemE2EComponent, + VorgangFormularDatenHistorieItemE2EComponent, + WiedervorlageHistorieItemE2EComponent, +} from 'apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component'; import { CommandE2E, CommandOrderE2E } from 'apps/alfa-e2e/src/model/command'; -import { HistorieAttachmentE2E, HistorieHeadlineE2E, SYSTEM_USER_NAME } from 'apps/alfa-e2e/src/model/historie'; +import { + HistorieAttachmentE2E, + HistorieHeadlineE2E, + SYSTEM_USER_NAME, +} from 'apps/alfa-e2e/src/model/historie'; import { PostfachE2E } from 'apps/alfa-e2e/src/model/postfach-nachricht'; import { DirectionE2E } from 'apps/alfa-e2e/src/model/vorgang-attached-item'; import { buildCommand, createCommand, initCommands } from 'apps/alfa-e2e/src/support/command-util'; @@ -41,348 +50,440 @@ import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main. import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, notExist } from '../../../support/cypress.util'; -import { getUserManagerUserEmil, getUserManagerUserPeter, getUserManagerUserSabine, getUserSabine, getUserSabineInternalId, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; +import { + getUserManagerUserEmil, + getUserManagerUserPeter, + getUserManagerUserSabine, + getUserSabine, + getUserSabineInternalId, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Historie', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangDatenFormular: VorgangFormularDatenE2EComponent = vorgangPage.getFormularDatenContainer(); - - const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); - - const vorgang: VorgangE2E = createVorgang(); - - const assignUserCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.ASSIGN_USER, vorgang._id.$oid, vorgang._id.$oid), - bodyObject: { assignedTo: getUserSabineInternalId() }, - createdAt: { $date: '2020-01-01T10:00:00.000Z' } - }; - - const createKommentarCommandBody = { itemName: 'Kommentar', item: {...createKommentar(), attachments: 'DummyAttachment'} }; - const createKommentarCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.CREATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), - bodyObject: createKommentarCommandBody, - createdAt: { $date: '2020-01-01T10:01:00.000Z' } - }; - const editKommentarCommandBody = { itemName: 'Kommentar', item: {...createKommentar(), attachments: ['DummyAttachment', 'DummyAttachment2']} }; - const editKommentarCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.UPDATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), - bodyObject: editKommentarCommandBody, - createdAt: { $date: '2020-01-01T10:02:00.000Z' } - }; - - const forwardVorgangCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.FORWARD_VORGANG, vorgang._id.$oid, vorgang._id.$oid), - createdAt: { $date: '2020-01-01T10:03:00.000Z' } - }; - const forwardSuccessfulCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.FORWARD_SUCCESSFUL, vorgang._id.$oid, vorgang._id.$oid), - createdAt: { $date: '2020-01-01T10:04:00.000Z' } - }; - const forwardFailedCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.FORWARD_FAILED, vorgang._id.$oid, vorgang._id.$oid), - createdAt: { $date: '2020-01-01T10:05:00.000Z' } - }; - - const sendPostfachMailCommandBody: PostfachE2E = { - ...createPostfachNachricht(), - mailBody: 'With mail test body!', - subject: 'Send Postfach Mail', - attachments: 'dummyAttachment' - }; - const sendPostfachMailCommand: CommandE2E = { - ...createCommand(), - bodyObject: sendPostfachMailCommandBody, - createdAt: { $date: '2020-01-01T10:06:00.000Z' } - }; - const sendPostfachNachrichtCommandBody: PostfachE2E = { - ...createPostfachNachricht(), - mailBody: 'With nachricht test body!', - subject: 'Send Postfach Nachricht', - attachments: ['dummyAttachment', 'dummyAttachment2'] - }; - const sendPostfachNachrichtCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.SEND_POSTFACH_NACHRICHT, vorgang._id.$oid, vorgang._id.$oid), - bodyObject: sendPostfachNachrichtCommandBody, - createdAt: { $date: '2020-01-01T10:07:00.000Z' } - }; - const receivePostfachNachrichtCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.CREATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), - bodyObject: { - itemName: 'PostfachMail', - item: { - mailBody: 'With nachricht test body!', - attachments: ['dummyAttachment', 'dummyAttachment2'], - subject: 'AW: Send Postfach Nachricht', - direction: DirectionE2E.IN - }, - client: 'OzgCloud_NachrichtenManager', - vorgangId: vorgang._id.$oid - }, - createdBy: null, - createdAt: { $date: '2020-01-01T10:08:00.000Z' } - }; - - const resendPostfachNachricht: CommandE2E = buildCommand(CommandOrderE2E.RESEND_POSTFACH_NACHRICHT, vorgang._id.$oid, vorgang._id.$oid); - - const createWiedervorlageCommandBody = { ...createWiedervorlageItem('Create Wiedervorlage Betreff'), attachments: 'DummyAttachment' }; - const createWiedervorlageCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.CREATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), - bodyObject: { itemName: 'Wiedervorlage', item: createWiedervorlageCommandBody }, - createdAt: { $date: '2020-01-01T10:09:00.000Z' } - }; - const editWiedervorlageCommandBody = { ...createWiedervorlageItem('Edit Wiedervorlage Betreff'), attachments: ['DummyAttachment', 'DummyAttachment2'], done: true }; - const editWiedervorlageCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.UPDATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), - bodyObject: { itemName: 'Wiedervorlage', item: editWiedervorlageCommandBody }, - createdAt: { $date: '2020-01-01T10:10:00.000Z' } - }; - const wiedervorlageErledigenCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.PATCH_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), - bodyObject: { itemName: 'Wiedervorlage', item: { done: 'true' }, vorgangId: vorgang._id.$oid }, - createdAt: { $date: '2020-01-01T10:11:00.000Z' } - }; - const wiedervorlageWiedereroeffnenCommand: CommandE2E = { - ...buildCommand(CommandOrderE2E.PATCH_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), - bodyObject: { itemName: 'Wiedervorlage', item: { done: 'false' }, vorgangId: vorgang._id.$oid }, - createdAt: { $date: '2020-01-01T10:12:00.000Z' } - }; - - before(() => { - initVorgang(vorgang); - initCommands([ - assignUserCommand, - createKommentarCommand, editKommentarCommand, - forwardVorgangCommand, forwardSuccessfulCommand, forwardFailedCommand, - sendPostfachMailCommand, sendPostfachNachrichtCommand, receivePostfachNachrichtCommand, resendPostfachNachricht, - createWiedervorlageCommand, editWiedervorlageCommand, wiedervorlageErledigenCommand, wiedervorlageWiedereroeffnenCommand - ]); - initUsermanagerUsers([getUserManagerUserSabine(), getUserManagerUserPeter(), getUserManagerUserEmil()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('navigate to vorgang detail', () => { - - describe('click on vorgang in list', () => { - - it('should show header', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - }) - }) - - describe('historie in tab', () => { - - it('should show on click on tab', () => { - vorgangDatenFormular.getHistorieTab().click(); - - exist(vorgangDatenFormular.getHistorieContainer().getRoot()); - }) - - it('should show vorgang created at', () => { - exist(vorgangDatenFormular.getHistorieContainer().getCreatedAt()); - }) - - describe('should show historie item for', () => { - - const userName: string = `${getUserSabine().firstName} ${getUserSabine().lastName}`; - - describe('vorgang order', () => { - - it('assign user', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(0); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.ASSIGN_USER); - contains(historieItem.getUser(), userName); - notExist(historieItem.getExpandButton()); - }) - }) - - describe('kommentar order', () => { - - it('create kommentar', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(1); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.CREATE_KOMMENTAR); - contains(historieItem.getUser(), userName); - - historieItem.getExpandButton().click(); - const kommentarItem: KommentarHistorieItemE2EComponent = historieItem.getKommentar(); - - contains(kommentarItem.getText(), createKommentarCommandBody.item.text); - contains(kommentarItem.getAttachment(), HistorieAttachmentE2E.SINGLE_TEXT); - - }) - - it('edit kommentar', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(2); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.EDIT_KOMMENTAR); - contains(historieItem.getUser(), userName); - - historieItem.getExpandButton().click(); - const kommentarItem: KommentarHistorieItemE2EComponent = historieItem.getKommentar(); - - contains(kommentarItem.getText(), editKommentarCommandBody.item.text); - contains(kommentarItem.getAttachment(), HistorieAttachmentE2E.MULTIPLE_TEXT.replace('{countAttachments}', '2')); - }) - }) - - describe('forward order', () => { - - it('forward vorgang', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(3); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.FORWARD_VORGANG); - contains(historieItem.getUser(), userName); - notExist(historieItem.getExpandButton()); - }) - - it('foward successful', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(4); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.FORWARD_SUCCESSFUL); - contains(historieItem.getUser(), userName); - notExist(historieItem.getExpandButton()); - }) - - it('foward failed', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(5); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.FORWARD_FAILED); - contains(historieItem.getUser(), userName); - notExist(historieItem.getExpandButton()); - }) - }) - - describe('postfach nachricht order', () => { - - it('send postfach mail', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(6); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.SEND_POSTFACH_NACHRICHT); - contains(historieItem.getUser(), userName); - - historieItem.getExpandButton().click(); - const postfachNachtichtItem: PostfachNachrichtHistorieItemE2EComponent = historieItem.getPostfachNachricht(); - - contains(postfachNachtichtItem.getPostfachNachrichtSubject(), sendPostfachMailCommandBody.subject); - contains(postfachNachtichtItem.getPostfachNachrichtMailBody(), sendPostfachMailCommandBody.mailBody); - }) - - it('send postfach nachricht', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(7); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.SEND_POSTFACH_NACHRICHT); - contains(historieItem.getUser(), userName); - - historieItem.getExpandButton().click(); - const postfachNachtichtItem: PostfachNachrichtHistorieItemE2EComponent = historieItem.getPostfachNachricht(); - - contains(postfachNachtichtItem.getPostfachNachrichtSubject(), sendPostfachNachrichtCommandBody.subject); - contains(postfachNachtichtItem.getPostfachNachrichtMailBody(), sendPostfachNachrichtCommandBody.mailBody); - }) - - it('receive postfach nachricht', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(8); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.RECEIVE_POSTFACH_NACHRICHT); - notExist(historieItem.getUser()); - contains(historieItem.getSystemUser(), SYSTEM_USER_NAME); - - historieItem.getExpandButton().click(); - const postfachNachtichtItem: PostfachNachrichtHistorieItemE2EComponent = historieItem.getPostfachNachricht(); - - contains(postfachNachtichtItem.getPostfachNachrichtSubject(), receivePostfachNachrichtCommand.bodyObject.item.subject); - contains(postfachNachtichtItem.getPostfachNachrichtMailBody(), receivePostfachNachrichtCommand.bodyObject.item.mailBody); - }) - - it('resend postfach nachricht', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(9); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.RESEND_POSTFACH_NACHRICHT); - contains(historieItem.getUser(), userName); - }) - }) - - describe('wiedervorlage order', () => { - - it('create wiedervorlage', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(10); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.CREATE_WIEDERVORLAGE); - contains(historieItem.getUser(), userName); - - historieItem.getExpandButton().click(); - const wiedervorlageItem: WiedervorlageHistorieItemE2EComponent = historieItem.getWiedervorlage(); - - contains(wiedervorlageItem.getStatus(), 'offen'); - contains(wiedervorlageItem.getBetreff(), createWiedervorlageCommandBody.betreff); - contains(wiedervorlageItem.getBeschreibung(), createWiedervorlageCommandBody.beschreibung); - contains(wiedervorlageItem.getAttachment(), HistorieAttachmentE2E.SINGLE_TEXT); - }) - - it('edit wiedervorlage', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(11); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.EDIT_WIEDERVORLAGE); - contains(historieItem.getUser(), userName); - - historieItem.getExpandButton().click(); - const wiedervorlageItem: WiedervorlageHistorieItemE2EComponent = historieItem.getWiedervorlage(); - - contains(wiedervorlageItem.getStatus(), 'geschlossen'); - contains(wiedervorlageItem.getBetreff(), editWiedervorlageCommandBody.betreff); - contains(wiedervorlageItem.getBeschreibung(), editWiedervorlageCommandBody.beschreibung); - contains(wiedervorlageItem.getAttachment(), HistorieAttachmentE2E.MULTIPLE_TEXT.replace('{countAttachments}', '2')); - }) - - it('wiedervorlage erledigen', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(12); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.WIEDERVORLAGE_ERLEDIGEN); - contains(historieItem.getUser(), userName); - notExist(historieItem.getExpandButton()); - }) - - it('wiedervorlage wiedereroeffnen', () => { - const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular.getHistorieContainer().getListItemByIndex(13); - - exist(historieItem.getRoot()); - contains(historieItem.getHeadline(), HistorieHeadlineE2E.WIEDERVORLAGE_WIEDEREROEFFNEN); - contains(historieItem.getUser(), userName); - notExist(historieItem.getExpandButton()); - }) - }) - }) - }) - }) -}); \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangDatenFormular: VorgangFormularDatenE2EComponent = + vorgangPage.getFormularDatenContainer(); + + const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + + const vorgang: VorgangE2E = createVorgang(); + + const assignUserCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.ASSIGN_USER, vorgang._id.$oid, vorgang._id.$oid), + bodyObject: { assignedTo: getUserSabineInternalId() }, + createdAt: { $date: '2020-01-01T10:00:00.000Z' }, + }; + + const createKommentarCommandBody = { + itemName: 'Kommentar', + item: { ...createKommentar(), attachments: 'DummyAttachment' }, + }; + const createKommentarCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.CREATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), + bodyObject: createKommentarCommandBody, + createdAt: { $date: '2020-01-01T10:01:00.000Z' }, + }; + const editKommentarCommandBody = { + itemName: 'Kommentar', + item: { ...createKommentar(), attachments: ['DummyAttachment', 'DummyAttachment2'] }, + }; + const editKommentarCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.UPDATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), + bodyObject: editKommentarCommandBody, + createdAt: { $date: '2020-01-01T10:02:00.000Z' }, + }; + + const forwardVorgangCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.FORWARD_VORGANG, vorgang._id.$oid, vorgang._id.$oid), + createdAt: { $date: '2020-01-01T10:03:00.000Z' }, + }; + const forwardSuccessfulCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.FORWARD_SUCCESSFUL, vorgang._id.$oid, vorgang._id.$oid), + createdAt: { $date: '2020-01-01T10:04:00.000Z' }, + }; + const forwardFailedCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.FORWARD_FAILED, vorgang._id.$oid, vorgang._id.$oid), + createdAt: { $date: '2020-01-01T10:05:00.000Z' }, + }; + + const sendPostfachMailCommandBody: PostfachE2E = { + ...createPostfachNachricht(), + mailBody: 'With mail test body!', + subject: 'Send Postfach Mail', + attachments: 'dummyAttachment', + }; + const sendPostfachMailCommand: CommandE2E = { + ...createCommand(), + bodyObject: sendPostfachMailCommandBody, + createdAt: { $date: '2020-01-01T10:06:00.000Z' }, + }; + const sendPostfachNachrichtCommandBody: PostfachE2E = { + ...createPostfachNachricht(), + mailBody: 'With nachricht test body!', + subject: 'Send Postfach Nachricht', + attachments: ['dummyAttachment', 'dummyAttachment2'], + }; + const sendPostfachNachrichtCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.SEND_POSTFACH_NACHRICHT, vorgang._id.$oid, vorgang._id.$oid), + bodyObject: sendPostfachNachrichtCommandBody, + createdAt: { $date: '2020-01-01T10:07:00.000Z' }, + }; + const receivePostfachNachrichtCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.CREATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), + bodyObject: { + itemName: 'PostfachMail', + item: { + mailBody: 'With nachricht test body!', + attachments: ['dummyAttachment', 'dummyAttachment2'], + subject: 'AW: Send Postfach Nachricht', + direction: DirectionE2E.IN, + }, + client: 'OzgCloud_NachrichtenManager', + vorgangId: vorgang._id.$oid, + }, + createdBy: null, + createdAt: { $date: '2020-01-01T10:08:00.000Z' }, + }; + + const resendPostfachNachricht: CommandE2E = buildCommand( + CommandOrderE2E.RESEND_POSTFACH_NACHRICHT, + vorgang._id.$oid, + vorgang._id.$oid, + ); + + const createWiedervorlageCommandBody = { + ...createWiedervorlageItem('Create Wiedervorlage Betreff'), + attachments: 'DummyAttachment', + }; + const createWiedervorlageCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.CREATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), + bodyObject: { itemName: 'Wiedervorlage', item: createWiedervorlageCommandBody }, + createdAt: { $date: '2020-01-01T10:09:00.000Z' }, + }; + const editWiedervorlageCommandBody = { + ...createWiedervorlageItem('Edit Wiedervorlage Betreff'), + attachments: ['DummyAttachment', 'DummyAttachment2'], + done: true, + }; + const editWiedervorlageCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.UPDATE_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), + bodyObject: { itemName: 'Wiedervorlage', item: editWiedervorlageCommandBody }, + createdAt: { $date: '2020-01-01T10:10:00.000Z' }, + }; + const wiedervorlageErledigenCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.PATCH_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), + bodyObject: { itemName: 'Wiedervorlage', item: { done: 'true' }, vorgangId: vorgang._id.$oid }, + createdAt: { $date: '2020-01-01T10:11:00.000Z' }, + }; + const wiedervorlageWiedereroeffnenCommand: CommandE2E = { + ...buildCommand(CommandOrderE2E.PATCH_ATTACHED_ITEM, vorgang._id.$oid, vorgang._id.$oid), + bodyObject: { itemName: 'Wiedervorlage', item: { done: 'false' }, vorgangId: vorgang._id.$oid }, + createdAt: { $date: '2020-01-01T10:12:00.000Z' }, + }; + + before(() => { + initVorgang(vorgang); + initCommands([ + assignUserCommand, + createKommentarCommand, + editKommentarCommand, + forwardVorgangCommand, + forwardSuccessfulCommand, + forwardFailedCommand, + sendPostfachMailCommand, + sendPostfachNachrichtCommand, + receivePostfachNachrichtCommand, + resendPostfachNachricht, + createWiedervorlageCommand, + editWiedervorlageCommand, + wiedervorlageErledigenCommand, + wiedervorlageWiedereroeffnenCommand, + ]); + initUsermanagerUsers([ + getUserManagerUserSabine(), + getUserManagerUserPeter(), + getUserManagerUserEmil(), + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('navigate to vorgang detail', () => { + describe('click on vorgang in list', () => { + it('should show header', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + }); + }); + + describe('historie in tab', () => { + it('should show on click on tab', () => { + vorgangDatenFormular.getHistorieTab().click(); + + exist(vorgangDatenFormular.getHistorieContainer().getRoot()); + }); + + it('should show vorgang created at', () => { + exist(vorgangDatenFormular.getHistorieContainer().getCreatedAt()); + }); + + describe('should show historie item for', () => { + const userName: string = `${getUserSabine().firstName} ${getUserSabine().lastName}`; + + describe('vorgang order', () => { + it('assign user', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(0); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.ASSIGN_USER); + contains(historieItem.getUser(), userName); + notExist(historieItem.getExpandButton()); + }); + }); + + describe('kommentar order', () => { + it('create kommentar', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(1); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.CREATE_KOMMENTAR); + contains(historieItem.getUser(), userName); + + historieItem.getExpandButton().click(); + const kommentarItem: KommentarHistorieItemE2EComponent = historieItem.getKommentar(); + + contains(kommentarItem.getText(), createKommentarCommandBody.item.text); + contains(kommentarItem.getAttachment(), HistorieAttachmentE2E.SINGLE_TEXT); + }); + + it('edit kommentar', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(2); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.EDIT_KOMMENTAR); + contains(historieItem.getUser(), userName); + + historieItem.getExpandButton().click(); + const kommentarItem: KommentarHistorieItemE2EComponent = historieItem.getKommentar(); + + contains(kommentarItem.getText(), editKommentarCommandBody.item.text); + contains( + kommentarItem.getAttachment(), + HistorieAttachmentE2E.MULTIPLE_TEXT.replace('{countAttachments}', '2'), + ); + }); + }); + + describe('forward order', () => { + it('forward vorgang', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(3); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.FORWARD_VORGANG); + contains(historieItem.getUser(), userName); + notExist(historieItem.getExpandButton()); + }); + + it('foward successful', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(4); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.FORWARD_SUCCESSFUL); + contains(historieItem.getUser(), userName); + notExist(historieItem.getExpandButton()); + }); + + it('foward failed', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(5); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.FORWARD_FAILED); + contains(historieItem.getUser(), userName); + notExist(historieItem.getExpandButton()); + }); + }); + + describe('postfach nachricht order', () => { + it('send postfach mail', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(6); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.SEND_POSTFACH_NACHRICHT); + contains(historieItem.getUser(), userName); + + historieItem.getExpandButton().click(); + const postfachNachtichtItem: PostfachNachrichtHistorieItemE2EComponent = + historieItem.getPostfachNachricht(); + + contains( + postfachNachtichtItem.getPostfachNachrichtSubject(), + sendPostfachMailCommandBody.subject, + ); + contains( + postfachNachtichtItem.getPostfachNachrichtMailBody(), + sendPostfachMailCommandBody.mailBody, + ); + }); + + it('send postfach nachricht', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(7); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.SEND_POSTFACH_NACHRICHT); + contains(historieItem.getUser(), userName); + + historieItem.getExpandButton().click(); + const postfachNachtichtItem: PostfachNachrichtHistorieItemE2EComponent = + historieItem.getPostfachNachricht(); + + contains( + postfachNachtichtItem.getPostfachNachrichtSubject(), + sendPostfachNachrichtCommandBody.subject, + ); + contains( + postfachNachtichtItem.getPostfachNachrichtMailBody(), + sendPostfachNachrichtCommandBody.mailBody, + ); + }); + + it('receive postfach nachricht', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(8); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.RECEIVE_POSTFACH_NACHRICHT); + notExist(historieItem.getUser()); + contains(historieItem.getSystemUser(), SYSTEM_USER_NAME); + + historieItem.getExpandButton().click(); + const postfachNachtichtItem: PostfachNachrichtHistorieItemE2EComponent = + historieItem.getPostfachNachricht(); + + contains( + postfachNachtichtItem.getPostfachNachrichtSubject(), + receivePostfachNachrichtCommand.bodyObject.item.subject, + ); + contains( + postfachNachtichtItem.getPostfachNachrichtMailBody(), + receivePostfachNachrichtCommand.bodyObject.item.mailBody, + ); + }); + + it('resend postfach nachricht', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(9); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.RESEND_POSTFACH_NACHRICHT); + contains(historieItem.getUser(), userName); + }); + }); + + describe('wiedervorlage order', () => { + it('create wiedervorlage', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(10); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.CREATE_WIEDERVORLAGE); + contains(historieItem.getUser(), userName); + + historieItem.getExpandButton().click(); + const wiedervorlageItem: WiedervorlageHistorieItemE2EComponent = + historieItem.getWiedervorlage(); + + contains(wiedervorlageItem.getStatus(), 'offen'); + contains(wiedervorlageItem.getBetreff(), createWiedervorlageCommandBody.betreff); + contains( + wiedervorlageItem.getBeschreibung(), + createWiedervorlageCommandBody.beschreibung, + ); + contains(wiedervorlageItem.getAttachment(), HistorieAttachmentE2E.SINGLE_TEXT); + }); + + it('edit wiedervorlage', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(11); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.EDIT_WIEDERVORLAGE); + contains(historieItem.getUser(), userName); + + historieItem.getExpandButton().click(); + const wiedervorlageItem: WiedervorlageHistorieItemE2EComponent = + historieItem.getWiedervorlage(); + + contains(wiedervorlageItem.getStatus(), 'geschlossen'); + contains(wiedervorlageItem.getBetreff(), editWiedervorlageCommandBody.betreff); + contains( + wiedervorlageItem.getBeschreibung(), + editWiedervorlageCommandBody.beschreibung, + ); + contains( + wiedervorlageItem.getAttachment(), + HistorieAttachmentE2E.MULTIPLE_TEXT.replace('{countAttachments}', '2'), + ); + }); + + it('wiedervorlage erledigen', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(12); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.WIEDERVORLAGE_ERLEDIGEN); + contains(historieItem.getUser(), userName); + notExist(historieItem.getExpandButton()); + }); + + it('wiedervorlage wiedereroeffnen', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(13); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.WIEDERVORLAGE_WIEDEREROEFFNEN); + contains(historieItem.getUser(), userName); + notExist(historieItem.getExpandButton()); + }); + }); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-connection-timeout.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-connection-timeout.cy.ts index 6a04acea22379cac679d2015cda29fece38f291f..6bd26289a2872ed4835d551f49f3f676a43c0ff2 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-connection-timeout.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-connection-timeout.cy.ts @@ -22,89 +22,104 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; -import { ConnectionTimeoutRetryDialogE2EComponent, ConnectionTimeoutRetryFailDialogE2EComponent } from '../../../components/ui/connection-timeout-retry-dialog.e2e.component'; +import { + ConnectionTimeoutRetryDialogE2EComponent, + ConnectionTimeoutRetryFailDialogE2EComponent, +} from '../../../components/ui/connection-timeout-retry-dialog.e2e.component'; import { VorgangDetailHeaderE2EComponent } from '../../../components/vorgang/vorgang-detail-header.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; -import { dropCollections, interceptWithResponse, waitOfInterceptor } from '../../../support/cypress-helper'; +import { + dropCollections, + interceptWithResponse, + waitOfInterceptor, +} from '../../../support/cypress-helper'; import { contains, exist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; describe('Interceptor Connection Timeout', () => { - const mainPage: MainPage = new MainPage(); + const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const connectionTimeoutRetryDialog: ConnectionTimeoutRetryDialogE2EComponent = + mainPage.getConnectionTimeoutRetryDialog(); + const connectionTimeoutRetryFailDialog: ConnectionTimeoutRetryFailDialogE2EComponent = + mainPage.getConnectionTimeoutRetryFailDialog(); - const connectionTimeoutRetryDialog: ConnectionTimeoutRetryDialogE2EComponent = mainPage.getConnectionTimeoutRetryDialog(); - const connectionTimeoutRetryFailDialog: ConnectionTimeoutRetryFailDialogE2EComponent = mainPage.getConnectionTimeoutRetryFailDialog(); + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + const vorgang: VorgangE2E = createVorgang(); - const vorgang: VorgangE2E = createVorgang(); + before(() => { + initVorgang(vorgang); - before(() => { - initVorgang(vorgang); + loginAsSabine(); - loginAsSabine(); + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + after(() => { + dropCollections(); + }); - after(() => { - dropCollections(); - }) + describe('annehmen', () => { + const interceptor: string = 'doVorgangAnnehmen'; + const statusCode: number = 503; - describe('annehmen', () => { + beforeEach(() => { + const url: string = + '*/vorgangs/602566a807bb665df9a86111/relations/602566a807bb665df9a86111/0/commands'; - const interceptor: string = 'doVorgangAnnehmen'; - const statusCode: number = 503; + interceptWithResponse('POST', url, { statusCode }).as(interceptor); + }); - beforeEach(() => { - const url: string = '*/vorgangs/602566a807bb665df9a86111/relations/602566a807bb665df9a86111/0/commands'; + it('should navigate to vorgang detail', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); - interceptWithResponse('POST', url, { statusCode }).as(interceptor); - }) + exist(vorgangHeader.getRoot()); + }); - it('should navigate to vorgang detail', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); + it('should show retry request dialog', () => { + vorgangFormularButtons.getAnnehmenButton().click(); - exist(vorgangHeader.getRoot()); - }) + waitOfInterceptor(interceptor).then((interception) => { + assert(interception.response.statusCode, statusCode.toString()); + exist(connectionTimeoutRetryDialog.getIcon()); + contains( + connectionTimeoutRetryDialog.getHeader(), + 'Es ist ein Verbindungsfehler aufgetreten ...', + ); + contains(connectionTimeoutRetryDialog.getMessage(), 'Ihre Anfrage wird wiederholt'); + }); + }); - it('should show retry request dialog', () => { - vorgangFormularButtons.getAnnehmenButton().click(); + it.skip('(LOCAL ONLY) should show fail dialog after time is over', () => { + cy.wait(290000); //Hier das BE ausstellen - waitOfInterceptor(interceptor).then((interception) => { - assert(interception.response.statusCode, statusCode.toString()); - exist(connectionTimeoutRetryDialog.getIcon()); - contains(connectionTimeoutRetryDialog.getHeader(), 'Es ist ein Verbindungsfehler aufgetreten ...'); - contains(connectionTimeoutRetryDialog.getMessage(), 'Ihre Anfrage wird wiederholt'); - }) - }) + exist(connectionTimeoutRetryFailDialog.getIcon()); + contains(connectionTimeoutRetryFailDialog.getHeader(), 'Zeitüberschreitung der Verbindung'); + contains( + connectionTimeoutRetryFailDialog.getMessage(), + 'Auch nach weiteren Versuchen konnte keine Verbindung aufgebaut werden', + ); + exist(connectionTimeoutRetryFailDialog.getReloadButton()); + }); - it.skip('(LOCAL ONLY) should show fail dialog after time is over', () => { - cy.wait(290000);//Hier das BE ausstellen + it.skip('(LOCAL ONLY) should reload page on click on button', () => { + connectionTimeoutRetryFailDialog.getReloadButton().click(); - exist(connectionTimeoutRetryFailDialog.getIcon()); - contains(connectionTimeoutRetryFailDialog.getHeader(), 'Zeitüberschreitung der Verbindung'); - contains(connectionTimeoutRetryFailDialog.getMessage(), 'Auch nach weiteren Versuchen konnte keine Verbindung aufgebaut werden'); - exist(connectionTimeoutRetryFailDialog.getReloadButton()); - }) + cy.wait(10000); //Hier das BE anstellen - it.skip('(LOCAL ONLY) should reload page on click on button', () => { - connectionTimeoutRetryFailDialog.getReloadButton().click(); - - cy.wait(10000);//Hier das BE anstellen - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - }) -}) \ No newline at end of file + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-forbidden.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-forbidden.cy.ts index 64296d6cf4ab05f2f8c70026881541cc961c68e5..e3378f0b75e707d9cc4a4b49f28009751291cb2b 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-forbidden.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-forbidden.cy.ts @@ -29,72 +29,78 @@ import { HttpMethodE2E } from '../../../model/util'; import { VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; -import { dropCollections, interceptWithResponse, waitOfInterceptor } from '../../../support/cypress-helper'; +import { + dropCollections, + interceptWithResponse, + waitOfInterceptor, +} from '../../../support/cypress-helper'; import { contains, exist, notExist } from '../../../support/cypress.util'; import { MessagesE2E } from '../../../support/messages'; import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; describe('Interceptor Forbidden', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); - const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); - - const vorgang: VorgangE2E = createVorgang(); - - before(() => { - initVorgang(vorgang); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('click on vorgang', () => { - - const statusCode: number = 403; - const interceptor: string = 'getVorgang'; - - beforeEach(() => { - const url: string = '*/vorgangs/' + vorgang._id.$oid; - - interceptWithResponse(HttpMethodE2E.GET, url, { statusCode, body: { issues: [{ message: '1', messageCode: '2' }] } }).as(interceptor); - }) - - it('should show page and snackbar', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - waitOfInterceptor(interceptor).then((interception) => { - assert(interception.response.statusCode, statusCode.toString()); - notExist(vorgangHeader.getRoot()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - exist(snackbar.getCloseButton()); - notExist(snackbar.getRevokeButton()); - notExist(vorgangPage.getSpinner()); - }) - }) - - it('should close snackbar on close button', () => { - snackbar.getCloseButton().click() - - notExist(snackbar.getMessage()); - }) - - it('should navigate back on back button', () => { - subnavigation.getBackButton().click(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); + + const vorgang: VorgangE2E = createVorgang(); + + before(() => { + initVorgang(vorgang); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('click on vorgang', () => { + const statusCode: number = 403; + const interceptor: string = 'getVorgang'; + + beforeEach(() => { + const url: string = '*/vorgangs/' + vorgang._id.$oid; + + interceptWithResponse(HttpMethodE2E.GET, url, { + statusCode, + body: { issues: [{ message: '1', messageCode: '2' }] }, + }).as(interceptor); + }); + + it('should show page and snackbar', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + waitOfInterceptor(interceptor).then((interception) => { + assert(interception.response.statusCode, statusCode.toString()); + notExist(vorgangHeader.getRoot()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + exist(snackbar.getCloseButton()); + notExist(snackbar.getRevokeButton()); + notExist(vorgangPage.getSpinner()); + }); + }); + + it('should close snackbar on close button', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getMessage()); + }); + + it('should navigate back on back button', () => { + subnavigation.getBackButton().click(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-server-error.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-server-error.cy.ts index e57681f1ff5a596a9f12b28123f2e9ffe69f8531..48a9d690dc329662bb1207858c5c3c835d0959d3 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-server-error.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-server-error.cy.ts @@ -26,53 +26,57 @@ import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-lis import { HttpMethodE2E } from '../../../model/util'; import { VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; -import { dropCollections, interceptWithResponse, waitOfInterceptor } from '../../../support/cypress-helper'; +import { + dropCollections, + interceptWithResponse, + waitOfInterceptor, +} from '../../../support/cypress-helper'; import { contains, exist } from '../../../support/cypress.util'; import { MessagesE2E } from '../../../support/messages'; import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; describe('Interceptor Server Error', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const errorDialog: InternalServerErrorDialogE2EComponent = mainPage.getInternalServerErrorDialog(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const errorDialog: InternalServerErrorDialogE2EComponent = + mainPage.getInternalServerErrorDialog(); - const vorgang: VorgangE2E = createVorgang(); + const vorgang: VorgangE2E = createVorgang(); - before(() => { - initVorgang(vorgang); + before(() => { + initVorgang(vorgang); - loginAsSabine(); + loginAsSabine(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('click on vorgang', () => { + describe('click on vorgang', () => { + const statusCode: number = 500; + const interceptor: string = 'getVorgang'; - const statusCode: number = 500; - const interceptor: string = 'getVorgang'; + beforeEach(() => { + const url: string = '*/vorgangs/' + vorgang._id.$oid; - beforeEach(() => { - const url: string = '*/vorgangs/' + vorgang._id.$oid; + interceptWithResponse(HttpMethodE2E.GET, url, { statusCode }).as(interceptor); + }); - interceptWithResponse(HttpMethodE2E.GET, url, { statusCode }).as(interceptor); - }) + it('should show page', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); - it('should show page', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - - waitOfInterceptor(interceptor).then(interception => { - assert(interception.response.statusCode, statusCode.toString()); - contains(errorDialog.getHeader(), MessagesE2E.HTTP_SERVER_ERROR_DIALOG_HEADER); - exist(errorDialog.getIcon()); - contains(errorDialog.getMessage(), MessagesE2E.HTTP_SERVER_ERROR); - exist(errorDialog.getLogoutButton()); - }) - }) - }) -}) \ No newline at end of file + waitOfInterceptor(interceptor).then((interception) => { + assert(interception.response.statusCode, statusCode.toString()); + contains(errorDialog.getHeader(), MessagesE2E.HTTP_SERVER_ERROR_DIALOG_HEADER); + exist(errorDialog.getIcon()); + contains(errorDialog.getMessage(), MessagesE2E.HTTP_SERVER_ERROR); + exist(errorDialog.getLogoutButton()); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-unauthorized.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-unauthorized.cy.ts index 94c0a7b9c33f9b272687fcb06467554ef841f7e8..79572548dc3bcb4852fdde09345bda7b926e8022 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-unauthorized.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/interceptor/interceptor-unauthorized.cy.ts @@ -28,7 +28,11 @@ import { HttpMethodE2E } from '../../../model/util'; import { VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; -import { dropCollections, interceptWithResponse, waitOfInterceptor } from '../../../support/cypress-helper'; +import { + dropCollections, + interceptWithResponse, + waitOfInterceptor, +} from '../../../support/cypress-helper'; import { contains, exist, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; @@ -36,48 +40,49 @@ import { createVorgang, initVorgang } from '../../../support/vorgang-util'; //FIXME Stand 07.09 => Bei einem 401 wird in der aktuellen Implementierung zum Keycloak weitergeleitet. //Sofern das die richtige Implementierung ist, muss der Test angepasst werden, andernfalls die Implementierung describe('Interceptor unauthorized', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); - const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); - const vorgang: VorgangE2E = createVorgang(); + const vorgang: VorgangE2E = createVorgang(); - before(() => { - initVorgang(vorgang); + before(() => { + initVorgang(vorgang); - loginAsSabine(); + loginAsSabine(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('click on vorgang', () => { + describe('click on vorgang', () => { + const BASE_PATH: string = '*/vorgangs/'; + const statusCode: number = 401; + const interceptorResponseUnauthorized: string = 'getVorgangWithEingangUnauthorized'; - const BASE_PATH: string = '*/vorgangs/'; - const statusCode: number = 401; - const interceptorResponseUnauthorized: string = 'getVorgangWithEingangUnauthorized'; + it('should reload page', () => { + interceptWithResponse(HttpMethodE2E.GET, BASE_PATH + vorgang._id.$oid, { statusCode }).as( + interceptorResponseUnauthorized, + ); - it('should reload page', () => { - interceptWithResponse(HttpMethodE2E.GET, BASE_PATH + vorgang._id.$oid, { statusCode }).as(interceptorResponseUnauthorized); + vorgangList.getListItem(vorgang.name).getRoot().click({ force: true }); + waitForSpinnerToDisappear(); - vorgangList.getListItem(vorgang.name).getRoot().click({ force: true }); - waitForSpinnerToDisappear(); + waitOfInterceptor(interceptorResponseUnauthorized).then((interception) => { + assert(interception.response.statusCode, statusCode.toString()); + notExist(vorgangHeader.getRoot()); + }); + }); - waitOfInterceptor(interceptorResponseUnauthorized).then((interception) => { - assert(interception.response.statusCode, statusCode.toString()); - notExist(vorgangHeader.getRoot()); - }) - }) - - it('should land on Keycloak login page', () => { - exist(cy.get('#kc-login')); - }) - }) -}) \ No newline at end of file + it('should land on Keycloak login page', () => { + exist(cy.get('#kc-login')); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/kommentar-attachment/kommentar-attachment.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/kommentar-attachment/kommentar-attachment.cy.ts index 59d80dfe872a8526b4e15526ddbee572f48755ce..58763b5adc8877cf245467f105d30eb6b7d904bd 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/kommentar-attachment/kommentar-attachment.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/kommentar-attachment/kommentar-attachment.cy.ts @@ -22,7 +22,10 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { sleep } from '@alfa-client/tech-shared'; -import { AttachmentContainerE2EComponent, AttachmentListE2EComponent } from '../../../components/attachment/attachment.e2e.component'; +import { + AttachmentContainerE2EComponent, + AttachmentListE2EComponent, +} from '../../../components/attachment/attachment.e2e.component'; import { KommentareInVorgangE2EComponent } from '../../../components/kommentar/kommentar-list.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { UserE2E } from '../../../model/user'; @@ -37,115 +40,115 @@ import { getUserSabine, loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; describe('Kommentar attachments', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const vorgangPage: VorgangPage = new VorgangPage(); - const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); + const vorgangPage: VorgangPage = new VorgangPage(); + const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); - const attachmentContainer: AttachmentContainerE2EComponent = kommentarContainer.getAttachmentContainer(); - const attachmentList: AttachmentListE2EComponent = attachmentContainer.getList(); + const attachmentContainer: AttachmentContainerE2EComponent = + kommentarContainer.getAttachmentContainer(); + const attachmentList: AttachmentListE2EComponent = attachmentContainer.getList(); - const kommentarText: string = 'Test text to test the test text test'; + const kommentarText: string = 'Test text to test the test text test'; - const vorgang: VorgangE2E = createVorgang(); - const userSabine: UserE2E = getUserSabine(); + const vorgang: VorgangE2E = createVorgang(); + const userSabine: UserE2E = getUserSabine(); - before(() => { - initVorgang(vorgang); + before(() => { + initVorgang(vorgang); - loginAsSabine(); + loginAsSabine(); - waitForSpinnerToDisappear(); - exist(mainPage.getVorgangList().getRoot()); - }) + waitForSpinnerToDisappear(); + exist(mainPage.getVorgangList().getRoot()); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('Upload attachements', () => { + describe('Upload attachements', () => { + it('should navigate to Vorgang', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); - it('should navigate to Vorgang', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }); + it('should show button for uploading attachments when creating new Kommentar', () => { + kommentarContainer.getHinzufuegenButton().click(); + waitForSpinnerToDisappear(); - it('should show button for uploading attachments when creating new Kommentar', () => { - kommentarContainer.getHinzufuegenButton().click(); - waitForSpinnerToDisappear(); + exist(attachmentContainer.getUploadInput()); + }); - exist(attachmentContainer.getUploadInput()); - }); + it('should upload attachements', () => { + uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITH_CONTENT); + waitForSpinnerToDisappear(); - it('should upload attachements', () => { - uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITH_CONTENT); - waitForSpinnerToDisappear(); + uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITHOUT_CONTENT); + waitForSpinnerToDisappear(); - uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITHOUT_CONTENT); - waitForSpinnerToDisappear(); + exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + exist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); + }); - exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - exist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - }); + it('should show attachements after saving Kommentar', () => { + kommentarContainer.getTextInput().type(kommentarText); + kommentarContainer.getFormularSpeichernButton().click(); + waitForSpinnerToDisappear(); - it('should show attachements after saving Kommentar', () => { - kommentarContainer.getTextInput().type(kommentarText); - kommentarContainer.getFormularSpeichernButton().click(); - waitForSpinnerToDisappear(); + exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + exist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); + }); + }); - exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - exist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - }); - }); + describe('Delete attachements', () => { + it('should delete attachments', () => { + kommentarContainer.getKommentar(kommentarText).getRoot().click(); + waitForSpinnerToDisappear(); - describe('Delete attachements', () => { - it('should delete attachments', () => { - kommentarContainer.getKommentar(kommentarText).getRoot().click(); - waitForSpinnerToDisappear(); + attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDeleteButton().click(); + waitForSpinnerToDisappear(); - attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDeleteButton().click(); - waitForSpinnerToDisappear(); + attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getDeleteButton().click(); + waitForSpinnerToDisappear(); - attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getDeleteButton().click(); - waitForSpinnerToDisappear(); + notExist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + notExist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); + }); - notExist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - notExist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - }); + it('should not show attachments after saving Kommentar', () => { + kommentarContainer.getFormularSpeichernButton().click(); + waitForSpinnerToDisappear(); - it('should not show attachments after saving Kommentar', () => { - kommentarContainer.getFormularSpeichernButton().click(); - waitForSpinnerToDisappear(); + notExist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + notExist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); + }); + }); - notExist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - notExist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - }); - }); + describe('Download Kommentar attachments', () => { + it('should upload attachment', () => { + kommentarContainer.getKommentar(kommentarText).getRoot().click(); + waitForSpinnerToDisappear(); - describe('Download Kommentar attachments', () => { - it('should upload attachment', () => { - kommentarContainer.getKommentar(kommentarText).getRoot().click(); - waitForSpinnerToDisappear(); + uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITH_CONTENT); + waitForSpinnerToDisappear(); - uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITH_CONTENT); - waitForSpinnerToDisappear(); + kommentarContainer.getFormularSpeichernButton().click(); + waitForSpinnerToDisappear(); - kommentarContainer.getFormularSpeichernButton().click(); - waitForSpinnerToDisappear(); + exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + }); - exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }); + it('should download uploaded attachment', () => { + sleep(1000); - it('should download uploaded attachment', () => { - sleep(1000); + attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDownloadButton().click(); + waitForSpinnerToDisappear(); - attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDownloadButton().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(TEST_FILE_WITH_CONTENT)); - }); - }); + exist(readFileFromDownloads(TEST_FILE_WITH_CONTENT)); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/kommentar/kommentar.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/kommentar/kommentar.cy.ts index a2969f248a5432e7c46e15da84aa5218e82871be..95db76c31ddf0f46e41cb23ea0f9cb40ded2999b 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/kommentar/kommentar.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/kommentar/kommentar.cy.ts @@ -28,167 +28,198 @@ import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main. import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; -import { getUserManagerUserEmil, getUserManagerUserPeter, getUserManagerUserSabine, getUserSabine, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; +import { + getUserManagerUserEmil, + getUserManagerUserPeter, + getUserManagerUserSabine, + getUserSabine, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; describe('Kommentar', () => { - const mainPage: MainPage = new MainPage(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); - - const kommentarText: string = 'Test text to test the test text test'; - - const vorgang: VorgangE2E = createVorgang(); - const userSabine: UserE2E = getUserSabine(); - - before(() => { - initVorgang(vorgang); - initUsermanagerUsers([getUserManagerUserSabine(), getUserManagerUserPeter(), getUserManagerUserEmil()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(mainPage.getVorgangList().getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('create', () => { - - it('Open Vorgang-Detail-Page', () => { - mainPage.getVorgangList().getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should only show hinzufuegen button initial', () => { - exist(kommentarContainer.getHinzufuegenButton()); - notExist(kommentarContainer.getFormular()); - }) - - describe('click on hinzufuegen button', () => { - - it('should show formular', () => { - kommentarContainer.getHinzufuegenButton().click(); - waitForSpinnerToDisappear(); - - exist(kommentarContainer.getFormular()); - }) - - it('should hide hinzufuegen button', () => { - notExist(kommentarContainer.getHinzufuegenButton()); - }) - - it('should show formular buttons', () => { - exist(kommentarContainer.getFormularAbbrechenButton()); - exist(kommentarContainer.getFormularSpeichernButton()); - }) - }) - - describe('click on hinzufuegen button in formular', () => { - - it('should show error on invalid input', () => { - kommentarContainer.getFormularSpeichernButton().click(); - waitForSpinnerToDisappear(); - - exist(kommentarContainer.getTextError()); - }) - - it('should show only hinzufuegen button on valid input', () => { - kommentarContainer.getTextInput().clear().type(kommentarText); - - kommentarContainer.getFormularSpeichernButton().click(); - exist(vorgangPage.getSpinner()); - notExist(kommentarContainer.getKommentar(kommentarText).getUserProfile().getIconContainer().getAssignedIcon()); - exist(vorgangPage.getSpinner()); - waitForSpinnerToDisappear(); - exist(kommentarContainer.getKommentar(kommentarText).getUserProfile().getIconContainer().getAssignedIcon()); - - notExist(kommentarContainer.getTextError()); - notExist(kommentarContainer.getFormular()); - exist(kommentarContainer.getHinzufuegenButton()); - }) - - it('should show entry in list', () => { - exist(kommentarContainer.getKommentar(kommentarText).getRoot()); - }) - - it('should show user profile at kommentar', () => { - exist(kommentarContainer.getKommentar(kommentarText).getUserProfile().getIconContainer().getAssignedIcon()); - haveText(kommentarContainer.getKommentar(kommentarText).getUserProfile().getIconContainer().getAssignedIcon(), userSabine.initials); - contains(kommentarContainer.getKommentar(kommentarText).getUserProfile().getName(), userSabine.fullName); - exist(kommentarContainer.getKommentar(kommentarText).getCreatedAt()); - }) - }) - - describe('click on abbrechen button in formular', () => { - - it('shoul hide formular', () => { - kommentarContainer.getHinzufuegenButton().click(); - kommentarContainer.getFormularAbbrechenButton().click(); - - notExist(kommentarContainer.getFormular()); - exist(kommentarContainer.getHinzufuegenButton()); - }) - }) - }) - - describe('edit', () => { - - it('should only show hinzufuegen button initial', () => { - exist(kommentarContainer.getHinzufuegenButton()); - notExist(kommentarContainer.getFormular()); - }) - - describe('click on existing kommentar', () => { - - it('should show formular with value', () => { - exist(kommentarContainer.getHinzufuegenButton()); - - kommentarContainer.getKommentar(kommentarText).getRoot().click(); - - exist(kommentarContainer.getFormularAbbrechenButton()); - exist(kommentarContainer.getFormularSpeichernButton()); - }) - - it('should show formular buttons', () => { - exist(kommentarContainer.getFormularAbbrechenButton()); - exist(kommentarContainer.getFormularSpeichernButton()); - }) - }) - - describe('click on "speichern" button in formular', () => { - - const kommentarText: string = 'Test text to test the test text test'; - - it('should show only hinzufuegen button on valid input', () => { - kommentarContainer.getTextInput().clear().type(kommentarText); - - kommentarContainer.getFormularSpeichernButton().click(); - - notExist(kommentarContainer.getTextError()); - notExist(kommentarContainer.getFormular()); - exist(kommentarContainer.getHinzufuegenButton()); - }) - - it('should show entry in list', () => { - exist(kommentarContainer.getKommentar(kommentarText).getRoot()); - }) - }) - - describe('click on abbrechen button in formular', () => { - - it('shoul hide formular', () => { - kommentarContainer.getKommentar(kommentarText).getRoot().click(); - kommentarContainer.getFormularAbbrechenButton().click(); - - notExist(kommentarContainer.getFormular()); - exist(kommentarContainer.getHinzufuegenButton()); - }) - }) - }) + const mainPage: MainPage = new MainPage(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); + + const kommentarText: string = 'Test text to test the test text test'; + + const vorgang: VorgangE2E = createVorgang(); + const userSabine: UserE2E = getUserSabine(); + + before(() => { + initVorgang(vorgang); + initUsermanagerUsers([ + getUserManagerUserSabine(), + getUserManagerUserPeter(), + getUserManagerUserEmil(), + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(mainPage.getVorgangList().getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('create', () => { + it('Open Vorgang-Detail-Page', () => { + mainPage.getVorgangList().getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should only show hinzufuegen button initial', () => { + exist(kommentarContainer.getHinzufuegenButton()); + notExist(kommentarContainer.getFormular()); + }); + + describe('click on hinzufuegen button', () => { + it('should show formular', () => { + kommentarContainer.getHinzufuegenButton().click(); + waitForSpinnerToDisappear(); + + exist(kommentarContainer.getFormular()); + }); + + it('should hide hinzufuegen button', () => { + notExist(kommentarContainer.getHinzufuegenButton()); + }); + + it('should show formular buttons', () => { + exist(kommentarContainer.getFormularAbbrechenButton()); + exist(kommentarContainer.getFormularSpeichernButton()); + }); + }); + + describe('click on hinzufuegen button in formular', () => { + it('should show error on invalid input', () => { + kommentarContainer.getFormularSpeichernButton().click(); + waitForSpinnerToDisappear(); + + exist(kommentarContainer.getTextError()); + }); + + it('should show only hinzufuegen button on valid input', () => { + kommentarContainer.getTextInput().clear().type(kommentarText); + + kommentarContainer.getFormularSpeichernButton().click(); + exist(vorgangPage.getSpinner()); + notExist( + kommentarContainer + .getKommentar(kommentarText) + .getUserProfile() + .getIconContainer() + .getAssignedIcon(), + ); + exist(vorgangPage.getSpinner()); + waitForSpinnerToDisappear(); + exist( + kommentarContainer + .getKommentar(kommentarText) + .getUserProfile() + .getIconContainer() + .getAssignedIcon(), + ); + + notExist(kommentarContainer.getTextError()); + notExist(kommentarContainer.getFormular()); + exist(kommentarContainer.getHinzufuegenButton()); + }); + + it('should show entry in list', () => { + exist(kommentarContainer.getKommentar(kommentarText).getRoot()); + }); + + it('should show user profile at kommentar', () => { + exist( + kommentarContainer + .getKommentar(kommentarText) + .getUserProfile() + .getIconContainer() + .getAssignedIcon(), + ); + haveText( + kommentarContainer + .getKommentar(kommentarText) + .getUserProfile() + .getIconContainer() + .getAssignedIcon(), + userSabine.initials, + ); + contains( + kommentarContainer.getKommentar(kommentarText).getUserProfile().getName(), + userSabine.fullName, + ); + exist(kommentarContainer.getKommentar(kommentarText).getCreatedAt()); + }); + }); + + describe('click on abbrechen button in formular', () => { + it('shoul hide formular', () => { + kommentarContainer.getHinzufuegenButton().click(); + kommentarContainer.getFormularAbbrechenButton().click(); + + notExist(kommentarContainer.getFormular()); + exist(kommentarContainer.getHinzufuegenButton()); + }); + }); + }); + + describe('edit', () => { + it('should only show hinzufuegen button initial', () => { + exist(kommentarContainer.getHinzufuegenButton()); + notExist(kommentarContainer.getFormular()); + }); + + describe('click on existing kommentar', () => { + it('should show formular with value', () => { + exist(kommentarContainer.getHinzufuegenButton()); + + kommentarContainer.getKommentar(kommentarText).getRoot().click(); + + exist(kommentarContainer.getFormularAbbrechenButton()); + exist(kommentarContainer.getFormularSpeichernButton()); + }); + + it('should show formular buttons', () => { + exist(kommentarContainer.getFormularAbbrechenButton()); + exist(kommentarContainer.getFormularSpeichernButton()); + }); + }); + + describe('click on "speichern" button in formular', () => { + const kommentarText: string = 'Test text to test the test text test'; + + it('should show only hinzufuegen button on valid input', () => { + kommentarContainer.getTextInput().clear().type(kommentarText); + + kommentarContainer.getFormularSpeichernButton().click(); + + notExist(kommentarContainer.getTextError()); + notExist(kommentarContainer.getFormular()); + exist(kommentarContainer.getHinzufuegenButton()); + }); + + it('should show entry in list', () => { + exist(kommentarContainer.getKommentar(kommentarText).getRoot()); + }); + }); + + describe('click on abbrechen button in formular', () => { + it('shoul hide formular', () => { + kommentarContainer.getKommentar(kommentarText).getRoot().click(); + kommentarContainer.getFormularAbbrechenButton().click(); + + notExist(kommentarContainer.getFormular()); + exist(kommentarContainer.getHinzufuegenButton()); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/endgueltig-loeschen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/endgueltig-loeschen.cy.ts index d3bca623600749c32d325d65dac97a084cb5ac84..345e125ef3eb75403a07869be209c083256614fd 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/endgueltig-loeschen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/endgueltig-loeschen.cy.ts @@ -10,126 +10,138 @@ import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; import { loginAsLudwig, loginAsSabine } from '../../../support/user-util'; -import { createLoeschAnforderungAttachedItem, initVorgangAttachedItem } from '../../../support/vorgang-attached-item-util'; +import { + createLoeschAnforderungAttachedItem, + initVorgangAttachedItem, +} from '../../../support/vorgang-attached-item-util'; import { buildVorgang, initVorgang, objectIds } from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang endgültig löschen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const basicDialog: BasicDialogE2EComponent = mainPage.getBasicDialog(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const basicDialog: BasicDialogE2EComponent = mainPage.getBasicDialog(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangId: string = objectIds[0]; + + const vorgangZuLoeschen: VorgangE2E = { + ...buildVorgang(vorgangId, 'DoZuLoeschenEndgueltigLoeschen'), + status: VorgangStatusE2E.ZU_LOESCHEN, + }; - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangId: string = objectIds[0]; - - const vorgangZuLoeschen: VorgangE2E = { - ...buildVorgang(vorgangId, 'DoZuLoeschenEndgueltigLoeschen'), status: VorgangStatusE2E.ZU_LOESCHEN - }; - - after(() => { - dropCollections(); - }) - - describe('Endgültig Löschen (ludwig löscht den Vorgang für den die sabine die Löschanforderung gestellt hat)', () => { - - before(() => { - initVorgang(vorgangZuLoeschen); - initVorgangAttachedItem([createLoeschAnforderungAttachedItem(objectIds[1], vorgangId)]); - - loginAsLudwig(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - it('Open Vorgang zum Löschen', () => { - vorgangList.getListItem(vorgangZuLoeschen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should have status Zu Löschen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZuLoeschen.status]); - }) - - it('should show Endgültig Löschen Bestätigungsdialog', () => { - vorgangFormularButtons.getEndgueltigLoeschenButton().click(); - waitForSpinnerToDisappear(); - - exist(basicDialog.getHeader()); - }) - - it('should show header text in Bestätigungsdialog', () => { - contains(basicDialog.getHeader(), 'Möchten Sie den Vorgang endgültig löschen?'); - }) - - it('should show warning message in Bestätigungsdialog', () => { - contains(basicDialog.getMessage(), 'Diese Aktion kann nicht widerrufen werden.'); - }) - - it('should have confirmation button', () => { - exist(basicDialog.getConfirmationButton()); - }) - - it('should have cancel button', () => { - exist(basicDialog.getCancelButton()); - }) - - it('should cancel das Löschen', () => { - basicDialog.getCancelButton().click(); - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - vorgangList.getListItem(vorgangZuLoeschen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZuLoeschen.status]); - }) - - it('should be redirected to vorgang list after endgültig löschen', () => { - vorgangFormularButtons.getEndgueltigLoeschenButton().click(); - - waitForSpinnerToDisappear(); - basicDialog.getConfirmationButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('vorgang should not exist', () => { - notExist(vorgangList.getListItem(vorgangZuLoeschen.name).getRoot()); - }) - }) - - describe('Endgültig Löschen (sabine löscht den Vorgang für den sabine die Löschanforderung gestellt hat)', () => { - - before(() => { - initVorgang(vorgangZuLoeschen); - initVorgangAttachedItem([createLoeschAnforderungAttachedItem(objectIds[1], vorgangId)]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - it('Open Vorgang zum Löschen', () => { - vorgangList.getListItem(vorgangZuLoeschen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should have status Zu Löschen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZuLoeschen.status]); - }) - - it('should not show Endgültig Löschen button', () => { - notExist(vorgangFormularButtons.getEndgueltigLoeschenButton()); - }) - }) + after(() => { + dropCollections(); + }); + + describe('Endgültig Löschen (ludwig löscht den Vorgang für den die sabine die Löschanforderung gestellt hat)', () => { + before(() => { + initVorgang(vorgangZuLoeschen); + initVorgangAttachedItem([createLoeschAnforderungAttachedItem(objectIds[1], vorgangId)]); + + loginAsLudwig(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + it('Open Vorgang zum Löschen', () => { + vorgangList.getListItem(vorgangZuLoeschen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should have status Zu Löschen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangZuLoeschen.status], + ); + }); + + it('should show Endgültig Löschen Bestätigungsdialog', () => { + vorgangFormularButtons.getEndgueltigLoeschenButton().click(); + waitForSpinnerToDisappear(); + + exist(basicDialog.getHeader()); + }); + + it('should show header text in Bestätigungsdialog', () => { + contains(basicDialog.getHeader(), 'Möchten Sie den Vorgang endgültig löschen?'); + }); + + it('should show warning message in Bestätigungsdialog', () => { + contains(basicDialog.getMessage(), 'Diese Aktion kann nicht widerrufen werden.'); + }); + + it('should have confirmation button', () => { + exist(basicDialog.getConfirmationButton()); + }); + + it('should have cancel button', () => { + exist(basicDialog.getCancelButton()); + }); + + it('should cancel das Löschen', () => { + basicDialog.getCancelButton().click(); + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + vorgangList.getListItem(vorgangZuLoeschen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangZuLoeschen.status], + ); + }); + + it('should be redirected to vorgang list after endgültig löschen', () => { + vorgangFormularButtons.getEndgueltigLoeschenButton().click(); + + waitForSpinnerToDisappear(); + basicDialog.getConfirmationButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('vorgang should not exist', () => { + notExist(vorgangList.getListItem(vorgangZuLoeschen.name).getRoot()); + }); + }); + + describe('Endgültig Löschen (sabine löscht den Vorgang für den sabine die Löschanforderung gestellt hat)', () => { + before(() => { + initVorgang(vorgangZuLoeschen); + initVorgangAttachedItem([createLoeschAnforderungAttachedItem(objectIds[1], vorgangId)]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + it('Open Vorgang zum Löschen', () => { + vorgangList.getListItem(vorgangZuLoeschen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should have status Zu Löschen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangZuLoeschen.status], + ); + }); + + it('should not show Endgültig Löschen button', () => { + notExist(vorgangFormularButtons.getEndgueltigLoeschenButton()); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loesch-anforderung-zuruecknehmen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loesch-anforderung-zuruecknehmen.cy.ts index 0f3e80f5fe8ab74de9df09aa8d1ffda310adca8b..7c730c254d5d01ffccce80b3380e02bb4696545a 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loesch-anforderung-zuruecknehmen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loesch-anforderung-zuruecknehmen.cy.ts @@ -11,169 +11,199 @@ import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { createLoeschAnforderungAttachedItem, initVorgangAttachedItem } from '../../../support/vorgang-attached-item-util'; +import { + createLoeschAnforderungAttachedItem, + initVorgangAttachedItem, +} from '../../../support/vorgang-attached-item-util'; import { buildVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('LoeschAnforderung zurücknehmen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); - - const vorgang: VorgangE2E = {...buildVorgang(objectIds[0], 'DoLoeschenAnforderungZuruecknehmen'), status: VorgangStatusE2E.ZU_LOESCHEN}; - const vorgangLoeschAnforderung: VorgangAttachedItemE2E = createLoeschAnforderungAttachedItem(objectIds[1], vorgang._id.$oid); - - const vorgangRevoke: VorgangE2E = { ...buildVorgang(objectIds[2], 'DoRevokeLoeschenAnforderungZuruecknehmen'), status: VorgangStatusE2E.ZU_LOESCHEN }; - const vorgangRevokeLoeschAnforderung: VorgangAttachedItemE2E = createLoeschAnforderungAttachedItem(objectIds[3], vorgangRevoke._id.$oid); - - before(() => { - initVorgaenge([vorgang, vorgangRevoke]); - initVorgangAttachedItem([vorgangLoeschAnforderung, vorgangRevokeLoeschAnforderung]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('zuruecknehmen by button', () => { - - describe('navigate', () => { - - it('should open Vorgang on item click', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - }) - - describe('ui elements', () => { - - it('should have status Zu Löschen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgang.status]); - }) - - it('should show zuruecknehmen button', () => { - exist(vorgangFormularButtons.getLoeschAnforderungZuruecknehmenButton()); - }) - }) - - describe('on click on zuruecknehmen button', () => { - - before(() => { - vorgangFormularButtons.getLoeschAnforderungZuruecknehmenButton().click(); - }) - - it('should show snackbar', () => { - contains(mainPage.getSnackBar().getMessage(), 'Für den Vorgang wurde die Löschanforderung zurückgenommen.'); - exist(mainPage.getSnackBar().getCloseButton()); - exist(mainPage.getSnackBar().getRevokeButton()); - }) - - it('should close snackbar on close button', () => { - mainPage.getSnackBar().getCloseButton().click(); - - notExist(mainPage.getSnackBar().getMessage()); - }) - - it('should change status', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - - it('should hide zuruecknehmen button', () => { - notExist(vorgangFormularButtons.getLoeschAnforderungZuruecknehmenButton()); - }) - - it('should show loschenAnfordern button', () => { - exist(vorgangFormularButtons.getLoeschenAnfordernButton()); - }) - - it('should navigate to list on back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Abgeschlossen', () => { - haveText(vorgangList.getListItem(vorgang.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - }) - }) - - describe('zuruecknehmen und rückgängig machen by icon button', () => { - - describe('navigate', () => { - - it('should open Vorgang on item click', () => { - vorgangList.getListItem(vorgangRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - }) - - describe('ui elements', () => { - - it('should have status Zu Löschen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgang.status]); - }) - - it('should show zuruecknehmen icon button', () => { - exist(subnavigation.getLoeschAnforderungZuruecknehmenIconButton()); - }) - }) - - describe('on click on zuruecknehmen button', () => { - - before(() => { - subnavigation.getLoeschAnforderungZuruecknehmenIconButton().click(); - }) - - it('should show snackbar', () => { - contains(mainPage.getSnackBar().getMessage(), 'Für den Vorgang wurde die Löschanforderung zurückgenommen.'); - exist(mainPage.getSnackBar().getCloseButton()); - exist(mainPage.getSnackBar().getRevokeButton()); - }) - - it('should show progress bar on revoke button', () => { - mainPage.getSnackBar().getRevokeButton().click(); - - exist(vorgangPage.getProgressBar()); - waitForSpinnerToDisappear(); - }) - - it('should keep status', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN]); - }) - - it('should show zuruecknehmen button', () => { - exist(subnavigation.getLoeschAnforderungZuruecknehmenIconButton()); - }) - - it('should hide loschenAnfordern button', () => { - notExist(vorgangFormularButtons.getLoeschenAnfordernButton()); - }) - - it('should navigate to list on back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status ZU_LOESCHEN', () => { - haveText(vorgangList.getListItem(vorgangRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN]); - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); + + const vorgang: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoLoeschenAnforderungZuruecknehmen'), + status: VorgangStatusE2E.ZU_LOESCHEN, + }; + const vorgangLoeschAnforderung: VorgangAttachedItemE2E = createLoeschAnforderungAttachedItem( + objectIds[1], + vorgang._id.$oid, + ); + + const vorgangRevoke: VorgangE2E = { + ...buildVorgang(objectIds[2], 'DoRevokeLoeschenAnforderungZuruecknehmen'), + status: VorgangStatusE2E.ZU_LOESCHEN, + }; + const vorgangRevokeLoeschAnforderung: VorgangAttachedItemE2E = + createLoeschAnforderungAttachedItem(objectIds[3], vorgangRevoke._id.$oid); + + before(() => { + initVorgaenge([vorgang, vorgangRevoke]); + initVorgangAttachedItem([vorgangLoeschAnforderung, vorgangRevokeLoeschAnforderung]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('zuruecknehmen by button', () => { + describe('navigate', () => { + it('should open Vorgang on item click', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + }); + + describe('ui elements', () => { + it('should have status Zu Löschen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgang.status], + ); + }); + + it('should show zuruecknehmen button', () => { + exist(vorgangFormularButtons.getLoeschAnforderungZuruecknehmenButton()); + }); + }); + + describe('on click on zuruecknehmen button', () => { + before(() => { + vorgangFormularButtons.getLoeschAnforderungZuruecknehmenButton().click(); + }); + + it('should show snackbar', () => { + contains( + mainPage.getSnackBar().getMessage(), + 'Für den Vorgang wurde die Löschanforderung zurückgenommen.', + ); + exist(mainPage.getSnackBar().getCloseButton()); + exist(mainPage.getSnackBar().getRevokeButton()); + }); + + it('should close snackbar on close button', () => { + mainPage.getSnackBar().getCloseButton().click(); + + notExist(mainPage.getSnackBar().getMessage()); + }); + + it('should change status', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + + it('should hide zuruecknehmen button', () => { + notExist(vorgangFormularButtons.getLoeschAnforderungZuruecknehmenButton()); + }); + + it('should show loschenAnfordern button', () => { + exist(vorgangFormularButtons.getLoeschenAnfordernButton()); + }); + + it('should navigate to list on back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Abgeschlossen', () => { + haveText( + vorgangList.getListItem(vorgang.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + }); + }); + + describe('zuruecknehmen und rückgängig machen by icon button', () => { + describe('navigate', () => { + it('should open Vorgang on item click', () => { + vorgangList.getListItem(vorgangRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + }); + + describe('ui elements', () => { + it('should have status Zu Löschen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgang.status], + ); + }); + + it('should show zuruecknehmen icon button', () => { + exist(subnavigation.getLoeschAnforderungZuruecknehmenIconButton()); + }); + }); + + describe('on click on zuruecknehmen button', () => { + before(() => { + subnavigation.getLoeschAnforderungZuruecknehmenIconButton().click(); + }); + + it('should show snackbar', () => { + contains( + mainPage.getSnackBar().getMessage(), + 'Für den Vorgang wurde die Löschanforderung zurückgenommen.', + ); + exist(mainPage.getSnackBar().getCloseButton()); + exist(mainPage.getSnackBar().getRevokeButton()); + }); + + it('should show progress bar on revoke button', () => { + mainPage.getSnackBar().getRevokeButton().click(); + + exist(vorgangPage.getProgressBar()); + waitForSpinnerToDisappear(); + }); + + it('should keep status', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN], + ); + }); + + it('should show zuruecknehmen button', () => { + exist(subnavigation.getLoeschAnforderungZuruecknehmenIconButton()); + }); + + it('should hide loschenAnfordern button', () => { + notExist(vorgangFormularButtons.getLoeschenAnfordernButton()); + }); + + it('should navigate to list on back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status ZU_LOESCHEN', () => { + haveText( + vorgangList.getListItem(vorgangRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loeschen-anfordern.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loeschen-anfordern.cy.ts index 6126d4a156677af914a66aab790a4a9216f5f25c..6ae63d71c0d8c4d0c7477a53749f5784fcd19a96 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loeschen-anfordern.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/loesch-anforderung/loeschen-anfordern.cy.ts @@ -7,10 +7,18 @@ import { UserProfileE2EComponent } from 'apps/alfa-e2e/src/components/user-profi import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { WiedervorlageInVorgangE2EComponent } from 'apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-in-vorgang.e2e.component'; import { initVorgangAttachedItem } from 'apps/alfa-e2e/src/support/vorgang-attached-item-util'; -import { createWiedervorlageAttachedItem, createWiedervorlageUriByVorgangIdAndWiedervorlageId } from 'apps/alfa-e2e/src/support/wiedervorlage-util'; +import { + createWiedervorlageAttachedItem, + createWiedervorlageUriByVorgangIdAndWiedervorlageId, +} from 'apps/alfa-e2e/src/support/wiedervorlage-util'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections, visitUrl } from '../../../support/cypress-helper'; @@ -21,340 +29,405 @@ import { buildVorgang, initVorgaenge, initVorgang, objectIds } from '../../../su registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Löschen anfordern', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangNichtLoeschbar: VorgangE2E = { ...buildVorgang(objectIds[5], 'DoNichtLoeschbar'), status: VorgangStatusE2E.ABGESCHLOSSEN }; - - const vorgangAbgeschlossenLoeschenAnfordern: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoAbgeschlossenLoeschenAnfordern'), status: VorgangStatusE2E.ABGESCHLOSSEN }; - const vorgangAbgeschlossenLoeschenAnfordernRevoke: VorgangE2E = { ...buildVorgang(objectIds[1], 'DoAbgeschlossenRevokeLoeschenAnfordern'), status: VorgangStatusE2E.ABGESCHLOSSEN }; - - const vorgangVerworfenLoeschenAnfordern: VorgangE2E = { ...buildVorgang(objectIds[2], 'DoVerworfenLoeschenAnfordern'), status: VorgangStatusE2E.VERWORFEN }; - const vorgangVerworfenLoeschenAnfordernRevoke: VorgangE2E = { ...buildVorgang(objectIds[3], 'DoVerworfenRevokeLoeschenAnfordern'), status: VorgangStatusE2E.VERWORFEN }; - - const wiedervorlageAttachedItem = createWiedervorlageAttachedItem(objectIds[4], vorgangAbgeschlossenLoeschenAnfordern._id.$oid); - const wiedervorlageUrl = createWiedervorlageUriByVorgangIdAndWiedervorlageId(objectIds[0], objectIds[4]); - - - describe('Nicht löschen (Ludwig kann keinen Vorgang löschen, für den er selbst die Löschanforderung gestellt hat)', () => { - before(() => { - initVorgang(vorgangNichtLoeschbar); - - loginAsLudwig(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - it('Öffne Vorgang für Löschanforderung', () => { - vorgangList.getListItem(vorgangNichtLoeschbar.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('Vorgang ist im Status: Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E.ABGESCHLOSSEN); - }) - - it('Löschen anfordern klicken', () => { - vorgangFormularButtons.getLoeschenAnfordernButton().click(); - waitForSpinnerToDisappear(); - }) - - it('Vorgang ist im Status: Zu Löschen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E.ZU_LOESCHEN); - }) - - it('Button zum Endgültig löschen ist nicht vorhanden', () => { - waitForSpinnerToDisappear(); - notExist(vorgangFormularButtons.getEndgueltigLoeschenButton()); - }) - }) - - describe('with user Sabine', () => { - before(() => { - initVorgaenge([vorgangAbgeschlossenLoeschenAnfordern, vorgangAbgeschlossenLoeschenAnfordernRevoke, vorgangVerworfenLoeschenAnfordern, vorgangVerworfenLoeschenAnfordernRevoke]); - initVorgangAttachedItem([wiedervorlageAttachedItem]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('Abgeschlossen: löschen anfordern', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordern.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbgeschlossenLoeschenAnfordern.status]); - }) - - it('should click Löschen anfordern button', () => { - vorgangFormularButtons.getLoeschenAnfordernButton().click(); - waitForSpinnerToDisappear(); - }) - - it('should show snackBar message', () => { - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN) - }) - - it('should close snackBar', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status zu Löschen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN]); - }) - - it('should redirect Wiedervorlage link to Vorgang', () => { - visitUrl(wiedervorlageUrl); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should show snackBar message', () => { - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.WIEDERVORLAGE_BEARBEITEN_NICHT_MOEGLICH) - }) - - it('should close snackBar', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status zu Löschen', () => { - haveText(vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordern.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN]); - }) - }) - }) - - describe('Disable functions', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordern.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should not have add comment button', () => { - const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); - - notExist(kommentarContainer.getHinzufuegenButton()); - }) - - it('should disable edit comment', () => { - const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); - - notExist(kommentarContainer.getFormular()); - }) - - it('should not have create postfach mail buttons', () => { - const postfachMailContainer: PostfachMailE2EComponent = vorgangPage.getPostfachMailcontainer(); - - notExist(postfachMailContainer.getCreateButtonWithoutText()); - notExist(postfachMailContainer.getCreateButtonWithText()); - }) - - it('should not have add wiedervorlage button', () => { - const createWiedervorlageButton = vorgangPage.getWiedervorlagenContainer().getCreateWiedervorlageButton(); - - notExist(createWiedervorlageButton); - }) - - it('should disable open Wiedervorlage-Page link ', () => { - const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer().getWiedervorlage('Wiedervorlage'); - - notExist(wiedervorlageInVorgang.getLink()); - }) - - it('should not have user assign button', () => { - const userProfileContainer: UserProfileE2EComponent = vorgangPage.getVorgangDetailHeader().getUserContainer(); - - notExist(userProfileContainer.getRoot()); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - }) - - describe('Abgeschlossen: löschen anfordern und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordernRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbgeschlossenLoeschenAnfordernRevoke.status]); - }) - - it('should show snackBar message', () => { - vorgangPage.getSubnavigation().getLoeschenAnfordernByIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Abgeschlossen', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Abgeschlossen', () => { - haveText(vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordernRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]) - }) - }) - }) - - describe('Verworfen: löschen anfordern', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangVerworfenLoeschenAnfordern.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Verworfen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangVerworfenLoeschenAnfordern.status]); - }) - - it('should show snackBar message', () => { - vorgangFormularButtons.getLoeschenAnfordernButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN) - }) - - it('should close snackBar', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status zu Löschen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status zu Löschen', () => { - haveText(vorgangList.getListItem(vorgangVerworfenLoeschenAnfordern.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN]); - }) - }) - }) - - describe('Verworfen: löschen anfordern und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangVerworfenLoeschenAnfordernRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Verworfen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangVerworfenLoeschenAnfordernRevoke.status]); - }) - - it('should show snackBar message', () => { - vorgangPage.getSubnavigation().getLoeschenAnfordernByIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Verworfen', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Verworfen', () => { - haveText(vorgangList.getListItem(vorgangVerworfenLoeschenAnfordernRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]) - }) - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangNichtLoeschbar: VorgangE2E = { + ...buildVorgang(objectIds[5], 'DoNichtLoeschbar'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + + const vorgangAbgeschlossenLoeschenAnfordern: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoAbgeschlossenLoeschenAnfordern'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + const vorgangAbgeschlossenLoeschenAnfordernRevoke: VorgangE2E = { + ...buildVorgang(objectIds[1], 'DoAbgeschlossenRevokeLoeschenAnfordern'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + + const vorgangVerworfenLoeschenAnfordern: VorgangE2E = { + ...buildVorgang(objectIds[2], 'DoVerworfenLoeschenAnfordern'), + status: VorgangStatusE2E.VERWORFEN, + }; + const vorgangVerworfenLoeschenAnfordernRevoke: VorgangE2E = { + ...buildVorgang(objectIds[3], 'DoVerworfenRevokeLoeschenAnfordern'), + status: VorgangStatusE2E.VERWORFEN, + }; + + const wiedervorlageAttachedItem = createWiedervorlageAttachedItem( + objectIds[4], + vorgangAbgeschlossenLoeschenAnfordern._id.$oid, + ); + const wiedervorlageUrl = createWiedervorlageUriByVorgangIdAndWiedervorlageId( + objectIds[0], + objectIds[4], + ); + + describe('Nicht löschen (Ludwig kann keinen Vorgang löschen, für den er selbst die Löschanforderung gestellt hat)', () => { + before(() => { + initVorgang(vorgangNichtLoeschbar); + + loginAsLudwig(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + it('Öffne Vorgang für Löschanforderung', () => { + vorgangList.getListItem(vorgangNichtLoeschbar.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('Vorgang ist im Status: Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E.ABGESCHLOSSEN, + ); + }); + + it('Löschen anfordern klicken', () => { + vorgangFormularButtons.getLoeschenAnfordernButton().click(); + waitForSpinnerToDisappear(); + }); + + it('Vorgang ist im Status: Zu Löschen', () => { + haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E.ZU_LOESCHEN); + }); + + it('Button zum Endgültig löschen ist nicht vorhanden', () => { + waitForSpinnerToDisappear(); + notExist(vorgangFormularButtons.getEndgueltigLoeschenButton()); + }); + }); + + describe('with user Sabine', () => { + before(() => { + initVorgaenge([ + vorgangAbgeschlossenLoeschenAnfordern, + vorgangAbgeschlossenLoeschenAnfordernRevoke, + vorgangVerworfenLoeschenAnfordern, + vorgangVerworfenLoeschenAnfordernRevoke, + ]); + initVorgangAttachedItem([wiedervorlageAttachedItem]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('Abgeschlossen: löschen anfordern', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordern.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbgeschlossenLoeschenAnfordern.status], + ); + }); + + it('should click Löschen anfordern button', () => { + vorgangFormularButtons.getLoeschenAnfordernButton().click(); + waitForSpinnerToDisappear(); + }); + + it('should show snackBar message', () => { + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); + }); + + it('should close snackBar', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status zu Löschen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN], + ); + }); + + it('should redirect Wiedervorlage link to Vorgang', () => { + visitUrl(wiedervorlageUrl); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should show snackBar message', () => { + exist(snackBar.getCloseButton()); + contains( + snackBar.getMessage(), + VorgangMessagesE2E.WIEDERVORLAGE_BEARBEITEN_NICHT_MOEGLICH, + ); + }); + + it('should close snackBar', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status zu Löschen', () => { + haveText( + vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordern.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN], + ); + }); + }); + }); + + describe('Disable functions', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordern.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should not have add comment button', () => { + const kommentarContainer: KommentareInVorgangE2EComponent = + vorgangPage.getKommentarContainer(); + + notExist(kommentarContainer.getHinzufuegenButton()); + }); + + it('should disable edit comment', () => { + const kommentarContainer: KommentareInVorgangE2EComponent = + vorgangPage.getKommentarContainer(); + + notExist(kommentarContainer.getFormular()); + }); + + it('should not have create postfach mail buttons', () => { + const postfachMailContainer: PostfachMailE2EComponent = + vorgangPage.getPostfachMailcontainer(); + + notExist(postfachMailContainer.getCreateButtonWithoutText()); + notExist(postfachMailContainer.getCreateButtonWithText()); + }); + + it('should not have add wiedervorlage button', () => { + const createWiedervorlageButton = vorgangPage + .getWiedervorlagenContainer() + .getCreateWiedervorlageButton(); + + notExist(createWiedervorlageButton); + }); + + it('should disable open Wiedervorlage-Page link ', () => { + const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage + .getWiedervorlagenContainer() + .getWiedervorlage('Wiedervorlage'); + + notExist(wiedervorlageInVorgang.getLink()); + }); + + it('should not have user assign button', () => { + const userProfileContainer: UserProfileE2EComponent = vorgangPage + .getVorgangDetailHeader() + .getUserContainer(); + + notExist(userProfileContainer.getRoot()); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + }); + + describe('Abgeschlossen: löschen anfordern und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordernRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbgeschlossenLoeschenAnfordernRevoke.status], + ); + }); + + it('should show snackBar message', () => { + vorgangPage.getSubnavigation().getLoeschenAnfordernByIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Abgeschlossen', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Abgeschlossen', () => { + haveText( + vorgangList.getListItem(vorgangAbgeschlossenLoeschenAnfordernRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + }); + }); + + describe('Verworfen: löschen anfordern', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangVerworfenLoeschenAnfordern.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Verworfen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangVerworfenLoeschenAnfordern.status], + ); + }); + + it('should show snackBar message', () => { + vorgangFormularButtons.getLoeschenAnfordernButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); + }); + + it('should close snackBar', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status zu Löschen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status zu Löschen', () => { + haveText( + vorgangList.getListItem(vorgangVerworfenLoeschenAnfordern.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ZU_LOESCHEN], + ); + }); + }); + }); + + describe('Verworfen: löschen anfordern und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangVerworfenLoeschenAnfordernRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Verworfen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangVerworfenLoeschenAnfordernRevoke.status], + ); + }); + + it('should show snackBar message', () => { + vorgangPage.getSubnavigation().getLoeschenAnfordernByIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.LOESCHEN_ANFORDERN); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Verworfen', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Verworfen', () => { + haveText( + vorgangList.getListItem(vorgangVerworfenLoeschenAnfordernRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + }); + }); + }); }); - - diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/navigation/navigation.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/navigation/navigation.cy.ts index 476373c8c33da9b2819e2ab7bed4db7be6452d56..0e7644c2ecba18389d796c2455aeedfe51a8cc9b 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/navigation/navigation.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/navigation/navigation.cy.ts @@ -31,148 +31,168 @@ import { HeaderE2EComponent } from 'apps/alfa-e2e/src/page-objects/header.po'; import { MainPage, waitForSpinnerToDisappear } from 'apps/alfa-e2e/src/page-objects/main.po'; import { dropCollections, dropSearchIndex } from 'apps/alfa-e2e/src/support/cypress-helper'; import { enterWith, exist, haveText, notExist } from 'apps/alfa-e2e/src/support/cypress.util'; -import { getUserManagerUserEmil, getUserManagerUserPeter, getUserManagerUserSabine, getUserSabineInternalId, initUsermanagerUsers, loginAsSabine } from 'apps/alfa-e2e/src/support/user-util'; -import { buildVorgang, createVorgang, initSearchIndex, initVorgaenge, objectIds } from 'apps/alfa-e2e/src/support/vorgang-util'; +import { + getUserManagerUserEmil, + getUserManagerUserPeter, + getUserManagerUserSabine, + getUserSabineInternalId, + initUsermanagerUsers, + loginAsSabine, +} from 'apps/alfa-e2e/src/support/user-util'; +import { + buildVorgang, + createVorgang, + initSearchIndex, + initVorgaenge, + objectIds, +} from 'apps/alfa-e2e/src/support/vorgang-util'; describe('Navigation', () => { - const mainPage: MainPage = new MainPage(); - - const header: HeaderE2EComponent = mainPage.getHeader(); - const vorgangSearch: VorgangSearchE2EComponent = header.getVorgangSearch(); - - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const navigation: NavigationE2EComponent = mainPage.getNavigation(); - - const views: VorgangViewsE2EComponent = mainPage.getViews(); - - const usermanagerUserSabine: UsermanagerUserE2E = getUserManagerUserSabine(); - - const vorgang: VorgangE2E = createVorgang(); - const vorgangNotBeFiltered: VorgangE2E = { ...buildVorgang(objectIds[0], 'vorgangNotBeFiltered') }; - const vorgangAssigned: VorgangE2E = { ...buildVorgang(objectIds[1], 'vorgangAssigned'), assignedTo: getUserSabineInternalId() }; - const vorgangAssignedNotBeFiltered: VorgangE2E = { ...buildVorgang(objectIds[2], 'vorgangAssignedNotBeFiltered'), assignedTo: getUserSabineInternalId() }; - - const searchString: string = 'NotBeFiltered'; - - before(() => { - initVorgaenge([vorgang, vorgangNotBeFiltered, vorgangAssigned, vorgangAssignedNotBeFiltered]); - initSearchIndex([vorgang, vorgangNotBeFiltered, vorgangAssigned, vorgangAssignedNotBeFiltered]); - initUsermanagerUsers([usermanagerUserSabine, getUserManagerUserEmil(), getUserManagerUserPeter()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - navigation.getAlleFilter().click(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - dropSearchIndex(); - }) - - describe('navigation item myVorgaenge', () => { - - it('should exists', () => { - exist(navigation.getMeineVorgaengeFilter()); - }) - }) - - describe('navigation item allVorgaenge', () => { - - it('should exists', () => { - exist(navigation.getAlleFilter()); - }) - }) - - describe('click on my vorgaenge', () => { - - it('should hide not to user assigned vorgaenge', () => { - navigation.getMeineVorgaengeFilter().click(); - waitForSpinnerToDisappear(); - - notExist(vorgangList.getListItem(vorgang.name).getRoot()); - notExist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); - exist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); - exist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); - }) - - it('should hide not matching vorgaenge after do search', () => { - doSearch(searchString); - waitForSpinnerToDisappear(); - - notExist(vorgangList.getListItem(vorgang.name).getRoot()); - notExist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); - notExist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); - exist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); - }) - }) - - describe('click on all vorgaenge', () => { - - it('should show all vorgaenge', () => { - navigation.getAlleFilter().click(); - waitForSpinnerToDisappear(); - views.getVorgangList().getRoot().click(); - - waitForSpinnerToDisappear(); - - exist(vorgangList.getListItem(vorgang.name).getRoot()); - exist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); - exist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); - exist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); - }) - - it('should hide not matching vorgaenge after do search', () => { - doSearch(searchString); - waitForSpinnerToDisappear(); - - notExist(vorgangList.getListItem(vorgang.name).getRoot()); - exist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); - notExist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); - exist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); - }) - }) - - describe('click on Suche view', () => { - - it('and alle filter should show empty list', () => { - vorgangSearch.getClearButton().click(); - - waitForSpinnerToDisappear(); - - views.getSuche().getRoot().click(); - - waitForSpinnerToDisappear(); - - notExist(vorgangList.getListItem(vorgang.name).getRoot()); - notExist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); - notExist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); - notExist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); - - //TODO sauber implementieren - haveText(cy.getTestElement('empty-list-text'), 'Bitte geben Sie einen Suchbegriff ein.'); - }) - - it('and meine filter should show empty list', () => { - navigation.getMeineVorgaengeFilter().click(); - - waitForSpinnerToDisappear(); - - notExist(vorgangList.getListItem(vorgang.name).getRoot()); - notExist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); - notExist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); - notExist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); - - //TODO sauber implementieren - haveText(cy.getTestElement('empty-list-text'), 'Bitte geben Sie einen Suchbegriff ein.'); - }) - }) - - function doSearch(searchString: string): void { - enterWith(vorgangSearch.getInput(), searchString); - } -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + + const header: HeaderE2EComponent = mainPage.getHeader(); + const vorgangSearch: VorgangSearchE2EComponent = header.getVorgangSearch(); + + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const navigation: NavigationE2EComponent = mainPage.getNavigation(); + + const views: VorgangViewsE2EComponent = mainPage.getViews(); + + const usermanagerUserSabine: UsermanagerUserE2E = getUserManagerUserSabine(); + + const vorgang: VorgangE2E = createVorgang(); + const vorgangNotBeFiltered: VorgangE2E = { + ...buildVorgang(objectIds[0], 'vorgangNotBeFiltered'), + }; + const vorgangAssigned: VorgangE2E = { + ...buildVorgang(objectIds[1], 'vorgangAssigned'), + assignedTo: getUserSabineInternalId(), + }; + const vorgangAssignedNotBeFiltered: VorgangE2E = { + ...buildVorgang(objectIds[2], 'vorgangAssignedNotBeFiltered'), + assignedTo: getUserSabineInternalId(), + }; + + const searchString: string = 'NotBeFiltered'; + + before(() => { + initVorgaenge([vorgang, vorgangNotBeFiltered, vorgangAssigned, vorgangAssignedNotBeFiltered]); + initSearchIndex([vorgang, vorgangNotBeFiltered, vorgangAssigned, vorgangAssignedNotBeFiltered]); + initUsermanagerUsers([ + usermanagerUserSabine, + getUserManagerUserEmil(), + getUserManagerUserPeter(), + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + navigation.getAlleFilter().click(); + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + dropSearchIndex(); + }); + + describe('navigation item myVorgaenge', () => { + it('should exists', () => { + exist(navigation.getMeineVorgaengeFilter()); + }); + }); + + describe('navigation item allVorgaenge', () => { + it('should exists', () => { + exist(navigation.getAlleFilter()); + }); + }); + + describe('click on my vorgaenge', () => { + it('should hide not to user assigned vorgaenge', () => { + navigation.getMeineVorgaengeFilter().click(); + waitForSpinnerToDisappear(); + + notExist(vorgangList.getListItem(vorgang.name).getRoot()); + notExist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); + exist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); + exist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); + }); + + it('should hide not matching vorgaenge after do search', () => { + doSearch(searchString); + waitForSpinnerToDisappear(); + + notExist(vorgangList.getListItem(vorgang.name).getRoot()); + notExist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); + notExist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); + exist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); + }); + }); + + describe('click on all vorgaenge', () => { + it('should show all vorgaenge', () => { + navigation.getAlleFilter().click(); + waitForSpinnerToDisappear(); + views.getVorgangList().getRoot().click(); + + waitForSpinnerToDisappear(); + + exist(vorgangList.getListItem(vorgang.name).getRoot()); + exist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); + exist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); + exist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); + }); + + it('should hide not matching vorgaenge after do search', () => { + doSearch(searchString); + waitForSpinnerToDisappear(); + + notExist(vorgangList.getListItem(vorgang.name).getRoot()); + exist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); + notExist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); + exist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); + }); + }); + + describe('click on Suche view', () => { + it('and alle filter should show empty list', () => { + vorgangSearch.getClearButton().click(); + + waitForSpinnerToDisappear(); + + views.getSuche().getRoot().click(); + + waitForSpinnerToDisappear(); + + notExist(vorgangList.getListItem(vorgang.name).getRoot()); + notExist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); + notExist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); + notExist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); + + //TODO sauber implementieren + haveText(cy.getTestElement('empty-list-text'), 'Bitte geben Sie einen Suchbegriff ein.'); + }); + + it('and meine filter should show empty list', () => { + navigation.getMeineVorgaengeFilter().click(); + + waitForSpinnerToDisappear(); + + notExist(vorgangList.getListItem(vorgang.name).getRoot()); + notExist(vorgangList.getListItem(vorgangNotBeFiltered.name).getRoot()); + notExist(vorgangList.getListItem(vorgangAssigned.name).getRoot()); + notExist(vorgangList.getListItem(vorgangAssignedNotBeFiltered.name).getRoot()); + + //TODO sauber implementieren + haveText(cy.getTestElement('empty-list-text'), 'Bitte geben Sie einen Suchbegriff ein.'); + }); + }); + + function doSearch(searchString: string): void { + enterWith(vorgangSearch.getInput(), searchString); + } +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail-error.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail-error.cy.ts index 474854b017e90d98cfa90ef5f859a1ec882cbab0..08ebf64544051400213f29df6cb3d4e1114ac11b 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail-error.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail-error.cy.ts @@ -21,154 +21,168 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { PostfachMailE2EComponent, PostfachMailListItem } from '../../../components/postfach/postfach-mail.e2e.component'; +import { + PostfachMailE2EComponent, + PostfachMailListItem, +} from '../../../components/postfach/postfach-mail.e2e.component'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { VorgangSubnavigationE2EComponent } from '../../../components/vorgang/vorgang-subnavigation'; import { VorgangE2E } from '../../../model/vorgang'; -import { DirectionE2E, PostfachMailItemE2E, PostfachNachrichtMessageCodeE2E, PostfachNachrichtMessageCodeMessagesE2E, PostfachNachrichtSnackbarMessageE2E, VorgangAttachedItemE2E } from '../../../model/vorgang-attached-item'; +import { + DirectionE2E, + PostfachMailItemE2E, + PostfachNachrichtMessageCodeE2E, + PostfachNachrichtMessageCodeMessagesE2E, + PostfachNachrichtSnackbarMessageE2E, + VorgangAttachedItemE2E, +} from '../../../model/vorgang-attached-item'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { PostfachMailPage } from '../../../page-objects/postfach-mail.component.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, notExist } from '../../../support/cypress.util'; import { getUserSabineInternalId, loginAsSabine } from '../../../support/user-util'; -import { createPostfachNachrichtAttachedItem, createPostfachNachrichtReplyItem, initVorgangAttachedItem } from '../../../support/vorgang-attached-item-util'; +import { + createPostfachNachrichtAttachedItem, + createPostfachNachrichtReplyItem, + initVorgangAttachedItem, +} from '../../../support/vorgang-attached-item-util'; import { createVorgang, initVorgang, objectIds } from '../../../support/vorgang-util'; describe('PostfachMail error', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const postfachMailContainer: PostfachMailE2EComponent = vorgangPage.getPostfachMailcontainer(); - const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); - - const postfachMailPage: PostfachMailPage = new PostfachMailPage(); - - const vorgang: VorgangE2E = createVorgang(); - const postfachMailItem: PostfachMailItemE2E = { - ...createPostfachNachrichtReplyItem(), - createdBy: getUserSabineInternalId(), - direction: DirectionE2E.OUT, - sentAt: '2022-12-02T15:00:00.790Z[UTC]', - sentSuccessful: false, - messageCode: PostfachNachrichtMessageCodeE2E.PROCESSING_FAILED - } - - const vorgangAttachedItem: VorgangAttachedItemE2E = { ...createPostfachNachrichtAttachedItem(objectIds[0], vorgang._id.$oid), item: postfachMailItem }; - - before(() => { - initVorgang(vorgang); - initVorgangAttachedItem([vorgangAttachedItem]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('navigate to vorgang detail', () => { - - it('should open vorgang detail', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should show postfach mail button', () => { - exist(postfachMailContainer.getCreateButtonWithText()); - }) - - it('should show postfach mail button in subnavigation', () => { - exist(subnavigation.getPostfachMailIconButton()); - }) - - it('should show postfach mail list', () => { - exist(postfachMailContainer.getList()); - }) - }) - - describe('postfach mail list', () => { - - let listItem: PostfachMailListItem; - - beforeEach(() => { - listItem = postfachMailPage.getListItem(postfachMailItem.subject); - }) - - describe('contains failed sent mail item', () => { - - - it('should show mail subject', () => { - contains(listItem.getSubject(), postfachMailItem.subject); - }) - - it('should show user profile', () => { - exist(listItem.getUserProfile().getRoot()); - }) - - it('should show sent date', () => { - exist(listItem.getSentAt()); - }) - - it('should show text', () => { - contains(listItem.getMailSendErrorText(), PostfachNachrichtMessageCodeMessagesE2E.PROCESSING_FAILED); - }) - - it('should show error message', () => { - exist(listItem.getMailSendErrorIcon()); - }) - - it('should show button', () => { - exist(listItem.getResendButton()); - }) - }) - - describe('resend mail', () => { - - it('click on resend button should hide error', () => { - listItem.getResendButton().click(); - waitForSpinnerToDisappear(); - - notExist(listItem.getMailSendErrorIcon()); - }) - - describe('resend mail item', () => { - - it('should show snackbar', () => { - contains(snackbar.getMessage(), PostfachNachrichtSnackbarMessageE2E.SEND_SUCCESSFUL); - notExist(snackbar.getRevokeButton()); - }) - - it('should close snackbar on close button', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getMessage()); - }) - - it('should show mail subject', () => { - contains(listItem.getSubject(), postfachMailItem.subject); - }) - - it('should show user profile', () => { - exist(listItem.getUserProfile().getRoot()); - }) - - it('should show date', () => { - exist(listItem.getSentAt()); - }) - - it('should show text', () => { - contains(listItem.getText(), postfachMailItem.mailBody); - }) - }); - }) - }) -}) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const postfachMailContainer: PostfachMailE2EComponent = vorgangPage.getPostfachMailcontainer(); + const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); + + const postfachMailPage: PostfachMailPage = new PostfachMailPage(); + + const vorgang: VorgangE2E = createVorgang(); + const postfachMailItem: PostfachMailItemE2E = { + ...createPostfachNachrichtReplyItem(), + createdBy: getUserSabineInternalId(), + direction: DirectionE2E.OUT, + sentAt: '2022-12-02T15:00:00.790Z[UTC]', + sentSuccessful: false, + messageCode: PostfachNachrichtMessageCodeE2E.PROCESSING_FAILED, + }; + + const vorgangAttachedItem: VorgangAttachedItemE2E = { + ...createPostfachNachrichtAttachedItem(objectIds[0], vorgang._id.$oid), + item: postfachMailItem, + }; + + before(() => { + initVorgang(vorgang); + initVorgangAttachedItem([vorgangAttachedItem]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('navigate to vorgang detail', () => { + it('should open vorgang detail', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should show postfach mail button', () => { + exist(postfachMailContainer.getCreateButtonWithText()); + }); + + it('should show postfach mail button in subnavigation', () => { + exist(subnavigation.getPostfachMailIconButton()); + }); + + it('should show postfach mail list', () => { + exist(postfachMailContainer.getList()); + }); + }); + + describe('postfach mail list', () => { + let listItem: PostfachMailListItem; + + beforeEach(() => { + listItem = postfachMailPage.getListItem(postfachMailItem.subject); + }); + + describe('contains failed sent mail item', () => { + it('should show mail subject', () => { + contains(listItem.getSubject(), postfachMailItem.subject); + }); + + it('should show user profile', () => { + exist(listItem.getUserProfile().getRoot()); + }); + + it('should show sent date', () => { + exist(listItem.getSentAt()); + }); + + it('should show text', () => { + contains( + listItem.getMailSendErrorText(), + PostfachNachrichtMessageCodeMessagesE2E.PROCESSING_FAILED, + ); + }); + + it('should show error message', () => { + exist(listItem.getMailSendErrorIcon()); + }); + + it('should show button', () => { + exist(listItem.getResendButton()); + }); + }); + + describe('resend mail', () => { + it('click on resend button should hide error', () => { + listItem.getResendButton().click(); + waitForSpinnerToDisappear(); + + notExist(listItem.getMailSendErrorIcon()); + }); + + describe('resend mail item', () => { + it('should show snackbar', () => { + contains(snackbar.getMessage(), PostfachNachrichtSnackbarMessageE2E.SEND_SUCCESSFUL); + notExist(snackbar.getRevokeButton()); + }); + + it('should close snackbar on close button', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getMessage()); + }); + + it('should show mail subject', () => { + contains(listItem.getSubject(), postfachMailItem.subject); + }); + + it('should show user profile', () => { + exist(listItem.getUserProfile().getRoot()); + }); + + it('should show date', () => { + exist(listItem.getSentAt()); + }); + + it('should show text', () => { + contains(listItem.getText(), postfachMailItem.mailBody); + }); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail.cy.ts index 2185d3220edbb9acfadcc9a20eab19db517882ff..b3d0c3f6fc2e27d6e96e2c7f1b70d91b05a7de81 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail.cy.ts @@ -22,497 +22,561 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { faker } from '@faker-js/faker'; -import { AttachmentContainerE2EComponent, AttachmentListE2EComponent } from 'apps/alfa-e2e/src/components/attachment/attachment.e2e.component'; +import { + AttachmentContainerE2EComponent, + AttachmentListE2EComponent, +} from 'apps/alfa-e2e/src/components/attachment/attachment.e2e.component'; import { BinaryFileSnackbarMessageE2E } from 'apps/alfa-e2e/src/model/binary-file'; import { PostfachMailFormularE2EComponent } from '../../../components/postfach/postfach-mail-formular.e2e.component'; -import { PostfachMailE2EComponent, PostfachMailListItem } from '../../../components/postfach/postfach-mail.e2e.component'; +import { + PostfachMailE2EComponent, + PostfachMailListItem, +} from '../../../components/postfach/postfach-mail.e2e.component'; import { FixedDialogE2EComponent } from '../../../components/ui/fixed-dialog.e2e.component'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { VorgangSubnavigationE2EComponent } from '../../../components/vorgang/vorgang-subnavigation'; import { ClientAttributeNameE2E, ClientAttributesE2E, VorgangE2E } from '../../../model/vorgang'; -import { PostfachMailItemE2E, PostfachNachrichtSnackbarMessageE2E, VorgangAttachedItemClientE2E, VorgangAttachedItemE2E } from '../../../model/vorgang-attached-item'; +import { + PostfachMailItemE2E, + PostfachNachrichtSnackbarMessageE2E, + VorgangAttachedItemClientE2E, + VorgangAttachedItemE2E, +} from '../../../model/vorgang-attached-item'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { PostfachMailPage } from '../../../page-objects/postfach-mail.component.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections, readFileFromDownloads } from '../../../support/cypress-helper'; -import { containClass, contains, exist, notBeVisible, notContainClass, notExist, visible } from '../../../support/cypress.util'; -import { TEST_FILE_WITHOUT_CONTENT, TEST_FILE_WITH_CONTENT, TEST_FILE_WITH_CONTENT_4_MB } from '../../../support/data.util'; +import { + containClass, + contains, + exist, + notBeVisible, + notContainClass, + notExist, + visible, +} from '../../../support/cypress.util'; +import { + TEST_FILE_WITHOUT_CONTENT, + TEST_FILE_WITH_CONTENT, + TEST_FILE_WITH_CONTENT_4_MB, +} from '../../../support/data.util'; import { uploadEmptyFile, uploadFile } from '../../../support/file-upload'; -import { getUserManagerUserSabine, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; -import { createPostfachNachrichtAttachedItem, createPostfachNachrichtReplyItem, initVorgangAttachedItem } from '../../../support/vorgang-attached-item-util'; -import { buildVorgang, createHasNewPostfachNachrichtClientAttribute, createHasPostfachNachrichtClientAttribute, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + getUserManagerUserSabine, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; +import { + createPostfachNachrichtAttachedItem, + createPostfachNachrichtReplyItem, + initVorgangAttachedItem, +} from '../../../support/vorgang-attached-item-util'; +import { + buildVorgang, + createHasNewPostfachNachrichtClientAttribute, + createHasPostfachNachrichtClientAttribute, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; import { expectIconWithBadge, expectIconWithoutBadge } from '../../../support/angular.util'; describe('PostfachMail', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const postfachMailContainer: PostfachMailE2EComponent = vorgangPage.getPostfachMailcontainer(); - const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); - const fixedDialog: FixedDialogE2EComponent = vorgangPage.getFixedDialog(); - const postfachMailFormular: PostfachMailFormularE2EComponent = vorgangPage.getPostfachMailFormular(); - const attachmentContainer: AttachmentContainerE2EComponent = postfachMailFormular.getAttachmentContainer(); - const attachmentList: AttachmentListE2EComponent = attachmentContainer.getList(); - - const postfachMailPage: PostfachMailPage = new PostfachMailPage(); - - const clientAttributes: ClientAttributesE2E = { - [VorgangAttachedItemClientE2E.OZGCLOUD_NACHRICHTEN_MANAGER]: { - [ClientAttributeNameE2E.HAS_NEW_POSTFACH_NACHRICHT]: createHasNewPostfachNachrichtClientAttribute(true), - [ClientAttributeNameE2E.HAS_POSTFACH_NACHRICHT]: createHasPostfachNachrichtClientAttribute(true) - } - }; - - const vorgang: VorgangE2E = createVorgang(); - const vorgangWithReply: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangWithReply'), clientAttributes }; - - const vorgangWithoutPostfach: VorgangE2E = createVorgangWithoutPostfachId(); - function createVorgangWithoutPostfachId(): VorgangE2E { - return { ...buildVorgang(objectIds[2], 'VorgangWithoutPostfachId'), eingangs: [...vorgang.eingangs], header: { serviceKonto: null} }; - } - - const postfachMailReply: PostfachMailItemE2E = createPostfachNachrichtReplyItem(); - const postfachNachrichtAttachedItem: VorgangAttachedItemE2E = { ...createPostfachNachrichtAttachedItem(objectIds[1], vorgangWithReply._id.$oid), item: postfachMailReply }; - - before(() => { - initVorgaenge([vorgang, vorgangWithoutPostfach, vorgangWithReply]); - initVorgangAttachedItem([postfachNachrichtAttachedItem]); - initUsermanagerUsers([getUserManagerUserSabine()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('mail icon', () => { - - it('should not be visible', () => { - notExist(vorgangList.getListItem(vorgang.name).getPostfachIcon()); - }) - - }) - - describe('mail icon with badge', () => { - - it('should be visible and have a badge', () => { - const postfachStatusIcon: HTMLElement = vorgangList.getListItem(vorgangWithReply.name).getPostfachIconMatIcon(); - expectIconWithBadge(postfachStatusIcon); - }) - }) - - describe('navigate to vorgang detail', () => { - - it('should open vorgang detail', () => { - waitForSpinnerToDisappear(); - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should show postfach mail button with text', () => { - exist(postfachMailContainer.getCreateButtonWithText()); - }) - - it('should show postfach mail button without text', () => { - exist(postfachMailContainer.getCreateButtonWithoutText()); - }) - - it('should show postfach mail button in subnavigation', () => { - exist(subnavigation.getPostfachMailIconButton()); - }) - - it('should show postfach mail list', () => { - exist(postfachMailContainer.getList()); - }) - }) - - describe('postfach mail', () => { - - const postfachMailToSend: PostfachMailItemE2E = <any>{ - subject: 'Huhu', - mailBody: faker.lorem.words(10) - } - - describe('click on button should open dialog', () => { - - it('should show fixed dialog header and content', () => { - postfachMailContainer.getCreateButtonWithText().click(); - waitForSpinnerToDisappear(); - - exist(fixedDialog.getDialogHeader()); - exist(fixedDialog.getDialogContent()); - }) - - - it('should show postfach mail formular', () => { - exist(postfachMailFormular.getEmpfaenger()); - exist(postfachMailFormular.getBetreff()); - exist(postfachMailFormular.getText()); - exist(postfachMailFormular.getSendButton()); - exist(postfachMailFormular.getAttachmentContainer().getUploadInput()); - exist(postfachMailFormular.getReplyOption().getRoot()); - }) - - - it('should show filled empfaenger', () => { - contains(postfachMailFormular.getEmpfaenger(), 'Max Testermann'); - }) - - it('should close Dialog if click on "X"', () => { - fixedDialog.getCloseButton().click(); - - notExist(postfachMailFormular.getEmpfaenger()); - }) - - it('should open dialog click on icon button', () => { - subnavigation.getPostfachMailIconButton().click(); - waitForSpinnerToDisappear(); - - exist(postfachMailFormular.getEmpfaenger()); - }) - - it('should hide dialog content click on minimize', () => { - fixedDialog.getMinMaxButton().click(); - - notBeVisible(fixedDialog.getDialogContent()); - exist(fixedDialog.getCloseButton()); - }) - - it('should show dialog content click on maximize', () => { - fixedDialog.getMinMaxButton().click(); - - visible(fixedDialog.getDialogContent()); - }) - }) - - describe('formular fields', () => { - - it('should show error on subject if send empty', () => { - postfachMailFormular.getSendButton().click(); - waitForSpinnerToDisappear(); - - exist(postfachMailFormular.getBetreffError()); - }) - - it('should show validation error on to long subject', () => { - postfachMailFormular.getBetreff().clear().type(faker.random.alphaNumeric(71)); - postfachMailFormular.getSendButton().click(); - - exist(postfachMailFormular.getBetreffError()); - }) - - it('should show error on text if send empty', () => { - postfachMailFormular.getSendButton().click(); - - exist(postfachMailFormular.getTextError()); - }) - - it('should be fillable', () => { - postfachMailFormular.getBetreff().clear().type(postfachMailToSend.subject); - postfachMailFormular.getText().clear().type(postfachMailToSend.mailBody); - }) - }) - - describe('attach files', () => { - - it('should show empty attachment after uploading it', () => { - uploadEmptyFile(attachmentContainer.getUploadInput(), TEST_FILE_WITHOUT_CONTENT) - waitForSpinnerToDisappear(); - - exist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - }) - - it('should show attachment with content after uploading it', () => { - uploadFile(postfachMailFormular.getAttachmentContainer().getUploadInput(), TEST_FILE_WITH_CONTENT); - waitForSpinnerToDisappear(); - - exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }) - - it('should download empty attachment on click', () => { - attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getDownloadButton().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(TEST_FILE_WITHOUT_CONTENT)); - }) - - it('should download attachment with content on click', () => { - attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDownloadButton().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(TEST_FILE_WITH_CONTENT)); - }) - - it('should not show empty attachment after deleting it', () => { - attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getDeleteButton().click(); - waitForSpinnerToDisappear(); - - notExist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - }) - }); - - describe('attach file > 3 MB', () => { - - it('should show error snackbar', () => { - uploadFile(postfachMailFormular.getAttachmentContainer().getUploadInput(), TEST_FILE_WITH_CONTENT_4_MB); - waitForSpinnerToDisappear(); - - exist(snackbar.getMessage()); - contains(snackbar.getMessage(), BinaryFileSnackbarMessageE2E.ATTACHMENT_NOT_ADDED.replace('{size}', '3MB')); - }) - - it('should close snackbar on close button', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getCloseButton()); - notExist(snackbar.getMessage()); - }) - - }) - - describe('click on reply option button', () => { - - it('should show reply options', () => { - postfachMailFormular.getReplyOption().getRoot().click(); - - exist(postfachMailFormular.getReplyOption().getPossibleOption()); - exist(postfachMailFormular.getReplyOption().getForbiddenOption()); - }) - - it('should change reply option to possible', () => { - postfachMailFormular.getReplyOption().getPossibleOption().click(); - }) - }) - - describe('send postfach mail', () => { - - it('should close dialog', () => { - postfachMailFormular.getSendButton().click(); - waitForSpinnerToDisappear(); - - notExist(postfachMailFormular.getEmpfaenger()); - }) - - it('should show snackbar', () => { - contains(snackbar.getMessage(), PostfachNachrichtSnackbarMessageE2E.SEND_SUCCESSFUL); - notExist(snackbar.getRevokeButton()); - }) - - it('should close snackbar on close button', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getMessage()); - }) - - it('should show postfach mail in list', () => { - const postfachMailItem: PostfachMailListItem = postfachMailContainer.getListItem(postfachMailToSend.subject); - - exist(postfachMailItem.getRoot()); - exist(postfachMailItem.getUserProfile().getRoot()); - exist(postfachMailItem.getSentAt()); - contains(postfachMailItem.getSubject(), postfachMailToSend.subject); - contains(postfachMailItem.getText(), postfachMailToSend.mailBody); - }) - - }) - - describe('click on postfach mail item with attachment', () => { - - it('should show postfach item list', () => { - const postfachMailItem: PostfachMailListItem = postfachMailContainer.getListItem(postfachMailToSend.subject); - postfachMailItem.getRoot().click(); - waitForSpinnerToDisappear(); - - exist(postfachMailPage.getRoot()); - }); - - it('should contain mail item with attachment', () => { - const postfachListItem: PostfachMailListItem = postfachMailPage.getListItem(postfachMailToSend.subject); - - exist(postfachListItem.getAttachmentContainer().getList().getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }); - - it('should download attachment after click', () => { - const postfachListItem: PostfachMailListItem = postfachMailPage.getListItem(postfachMailToSend.subject); - - postfachListItem.getAttachmentContainer().getList().getItem(TEST_FILE_WITH_CONTENT).getDownloadButton().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(TEST_FILE_WITHOUT_CONTENT)); - }); - }); - - describe('click on back button', () => { - - it('should navigate to vorgang detail', () => { - postfachMailPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should navigate back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - }) - - describe('mail icon', () => { - it('should be visible', () => { - exist(vorgangList.getListItem(vorgang.name).getPostfachIcon()); - }) - }) - }) - - describe('navigate to vorgang detail', () => { - - it('should open vorgang detail', () => { - waitForSpinnerToDisappear(); - vorgangList.getListItem(vorgangWithoutPostfach.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should not show postfach mail button', () => { - notExist(postfachMailContainer.getCreateButtonWithText()); - }) - - it('should not show postfach mail button in subnavigation', () => { - notExist(subnavigation.getPostfachMailIconButton()); - }) - - it('should show text for no postfach attached', () => { - contains(postfachMailContainer.getNoPostfachText(), 'Dieser Vorgang ist nicht mit einem Postfach verknüpft.'); - }) - - it('should navigate back to list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - }) - - describe('navigate to vorgang detail', () => { - - it('should open vorgang detail', () => { - vorgangList.getListItem(vorgangWithReply.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should show postfach mail button', () => { - exist(postfachMailContainer.getCreateButtonWithText()); - }) - - it('should show postfach mail button in subnavigation', () => { - exist(subnavigation.getPostfachMailIconButton()); - }) - - it('should show postfach mail list', () => { - exist(postfachMailContainer.getList()); - }) - - it('should show postfach reply mail in list', () => { - exist(postfachMailContainer.getListItem(postfachMailReply.subject).getRoot()); - }) - - it('should show item reply icon', () => { - exist(postfachMailContainer.getListItem(postfachMailReply.subject).getReplyIcon()); - }) - - it('should show date', () => { - exist(postfachMailContainer.getListItem(postfachMailReply.subject).getCreatedAt()); - }) - - it('should show text', () => { - contains(postfachMailContainer.getListItem(postfachMailReply.subject).getText(), postfachMailReply.mailBody); - }) - }) - - describe('click on postfach mail item', () => { - - let postfachMailReplyItem: PostfachMailListItem; - - beforeEach(() => { - postfachMailReplyItem = postfachMailPage.getListItem(postfachMailReply.subject); - }) - - describe('postfach page', () => { - - it('should open full view of postfachMailList', () => { - postfachMailReplyItem.getRoot().click(); - waitForSpinnerToDisappear(); - - exist(postfachMailPage.getRoot()); - }) - - it('should show subnavigation', () => { - exist(postfachMailPage.getSubnavigation().getBackButton()); - }) - - it('should show breadcrumb', () => { - contains(postfachMailPage.getBreadcrump(), vorgangWithReply.aktenzeichen); - }) - }) - - describe('reply item', () => { - - it('should show item reply icon', () => { - exist(postfachMailReplyItem.getReplyIcon()); - }) - - it('should show reply subject', () => { - contains(postfachMailReplyItem.getSubject(), postfachMailReply.subject); - }) - - it('should show date', () => { - exist(postfachMailReplyItem.getCreatedAt()); - }) - - it('should show reply text', () => { - contains(postfachMailReplyItem.getText(), postfachMailReply.mailBody); - }) - }) - - describe('click on back button', () => { - - it('should navigate to vorgang detail', () => { - postfachMailPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - }) - }) - - describe('mail icon', () => { - - it('should navigate back to list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should be visible and not have a badge', () => { - const postfachStatusIcon: HTMLElement = vorgangList.getListItem(vorgangWithReply.name).getPostfachIconMatIcon(); - expectIconWithoutBadge(postfachStatusIcon); - }) - - }) - -}) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const postfachMailContainer: PostfachMailE2EComponent = vorgangPage.getPostfachMailcontainer(); + const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); + const fixedDialog: FixedDialogE2EComponent = vorgangPage.getFixedDialog(); + const postfachMailFormular: PostfachMailFormularE2EComponent = + vorgangPage.getPostfachMailFormular(); + const attachmentContainer: AttachmentContainerE2EComponent = + postfachMailFormular.getAttachmentContainer(); + const attachmentList: AttachmentListE2EComponent = attachmentContainer.getList(); + + const postfachMailPage: PostfachMailPage = new PostfachMailPage(); + + const clientAttributes: ClientAttributesE2E = { + [VorgangAttachedItemClientE2E.OZGCLOUD_NACHRICHTEN_MANAGER]: { + [ClientAttributeNameE2E.HAS_NEW_POSTFACH_NACHRICHT]: + createHasNewPostfachNachrichtClientAttribute(true), + [ClientAttributeNameE2E.HAS_POSTFACH_NACHRICHT]: + createHasPostfachNachrichtClientAttribute(true), + }, + }; + + const vorgang: VorgangE2E = createVorgang(); + const vorgangWithReply: VorgangE2E = { + ...buildVorgang(objectIds[0], 'VorgangWithReply'), + clientAttributes, + }; + + const vorgangWithoutPostfach: VorgangE2E = createVorgangWithoutPostfachId(); + function createVorgangWithoutPostfachId(): VorgangE2E { + return { + ...buildVorgang(objectIds[2], 'VorgangWithoutPostfachId'), + eingangs: [...vorgang.eingangs], + header: { serviceKonto: null }, + }; + } + + const postfachMailReply: PostfachMailItemE2E = createPostfachNachrichtReplyItem(); + const postfachNachrichtAttachedItem: VorgangAttachedItemE2E = { + ...createPostfachNachrichtAttachedItem(objectIds[1], vorgangWithReply._id.$oid), + item: postfachMailReply, + }; + + before(() => { + initVorgaenge([vorgang, vorgangWithoutPostfach, vorgangWithReply]); + initVorgangAttachedItem([postfachNachrichtAttachedItem]); + initUsermanagerUsers([getUserManagerUserSabine()]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('mail icon', () => { + it('should not be visible', () => { + notExist(vorgangList.getListItem(vorgang.name).getPostfachIcon()); + }); + }); + + describe('mail icon with badge', () => { + it('should be visible and have a badge', () => { + const postfachStatusIcon: HTMLElement = vorgangList + .getListItem(vorgangWithReply.name) + .getPostfachIconMatIcon(); + expectIconWithBadge(postfachStatusIcon); + }); + }); + + describe('navigate to vorgang detail', () => { + it('should open vorgang detail', () => { + waitForSpinnerToDisappear(); + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should show postfach mail button with text', () => { + exist(postfachMailContainer.getCreateButtonWithText()); + }); + + it('should show postfach mail button without text', () => { + exist(postfachMailContainer.getCreateButtonWithoutText()); + }); + + it('should show postfach mail button in subnavigation', () => { + exist(subnavigation.getPostfachMailIconButton()); + }); + + it('should show postfach mail list', () => { + exist(postfachMailContainer.getList()); + }); + }); + + describe('postfach mail', () => { + const postfachMailToSend: PostfachMailItemE2E = <any>{ + subject: 'Huhu', + mailBody: faker.lorem.words(10), + }; + + describe('click on button should open dialog', () => { + it('should show fixed dialog header and content', () => { + postfachMailContainer.getCreateButtonWithText().click(); + waitForSpinnerToDisappear(); + + exist(fixedDialog.getDialogHeader()); + exist(fixedDialog.getDialogContent()); + }); + + it('should show postfach mail formular', () => { + exist(postfachMailFormular.getEmpfaenger()); + exist(postfachMailFormular.getBetreff()); + exist(postfachMailFormular.getText()); + exist(postfachMailFormular.getSendButton()); + exist(postfachMailFormular.getAttachmentContainer().getUploadInput()); + exist(postfachMailFormular.getReplyOption().getRoot()); + }); + + it('should show filled empfaenger', () => { + contains(postfachMailFormular.getEmpfaenger(), 'Max Testermann'); + }); + + it('should close Dialog if click on "X"', () => { + fixedDialog.getCloseButton().click(); + + notExist(postfachMailFormular.getEmpfaenger()); + }); + + it('should open dialog click on icon button', () => { + subnavigation.getPostfachMailIconButton().click(); + waitForSpinnerToDisappear(); + + exist(postfachMailFormular.getEmpfaenger()); + }); + + it('should hide dialog content click on minimize', () => { + fixedDialog.getMinMaxButton().click(); + + notBeVisible(fixedDialog.getDialogContent()); + exist(fixedDialog.getCloseButton()); + }); + + it('should show dialog content click on maximize', () => { + fixedDialog.getMinMaxButton().click(); + + visible(fixedDialog.getDialogContent()); + }); + }); + + describe('formular fields', () => { + it('should show error on subject if send empty', () => { + postfachMailFormular.getSendButton().click(); + waitForSpinnerToDisappear(); + + exist(postfachMailFormular.getBetreffError()); + }); + + it('should show validation error on to long subject', () => { + postfachMailFormular.getBetreff().clear().type(faker.random.alphaNumeric(71)); + postfachMailFormular.getSendButton().click(); + + exist(postfachMailFormular.getBetreffError()); + }); + + it('should show error on text if send empty', () => { + postfachMailFormular.getSendButton().click(); + + exist(postfachMailFormular.getTextError()); + }); + + it('should be fillable', () => { + postfachMailFormular.getBetreff().clear().type(postfachMailToSend.subject); + postfachMailFormular.getText().clear().type(postfachMailToSend.mailBody); + }); + }); + + describe('attach files', () => { + it('should show empty attachment after uploading it', () => { + uploadEmptyFile(attachmentContainer.getUploadInput(), TEST_FILE_WITHOUT_CONTENT); + waitForSpinnerToDisappear(); + + exist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); + }); + + it('should show attachment with content after uploading it', () => { + uploadFile( + postfachMailFormular.getAttachmentContainer().getUploadInput(), + TEST_FILE_WITH_CONTENT, + ); + waitForSpinnerToDisappear(); + + exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + }); + + it('should download empty attachment on click', () => { + attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getDownloadButton().click(); + waitForSpinnerToDisappear(); + + exist(readFileFromDownloads(TEST_FILE_WITHOUT_CONTENT)); + }); + + it('should download attachment with content on click', () => { + attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDownloadButton().click(); + waitForSpinnerToDisappear(); + + exist(readFileFromDownloads(TEST_FILE_WITH_CONTENT)); + }); + + it('should not show empty attachment after deleting it', () => { + attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getDeleteButton().click(); + waitForSpinnerToDisappear(); + + notExist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); + }); + }); + + describe('attach file > 3 MB', () => { + it('should show error snackbar', () => { + uploadFile( + postfachMailFormular.getAttachmentContainer().getUploadInput(), + TEST_FILE_WITH_CONTENT_4_MB, + ); + waitForSpinnerToDisappear(); + + exist(snackbar.getMessage()); + contains( + snackbar.getMessage(), + BinaryFileSnackbarMessageE2E.ATTACHMENT_NOT_ADDED.replace('{size}', '3MB'), + ); + }); + + it('should close snackbar on close button', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getCloseButton()); + notExist(snackbar.getMessage()); + }); + }); + + describe('click on reply option button', () => { + it('should show reply options', () => { + postfachMailFormular.getReplyOption().getRoot().click(); + + exist(postfachMailFormular.getReplyOption().getPossibleOption()); + exist(postfachMailFormular.getReplyOption().getForbiddenOption()); + }); + + it('should change reply option to possible', () => { + postfachMailFormular.getReplyOption().getPossibleOption().click(); + }); + }); + + describe('send postfach mail', () => { + it('should close dialog', () => { + postfachMailFormular.getSendButton().click(); + waitForSpinnerToDisappear(); + + notExist(postfachMailFormular.getEmpfaenger()); + }); + + it('should show snackbar', () => { + contains(snackbar.getMessage(), PostfachNachrichtSnackbarMessageE2E.SEND_SUCCESSFUL); + notExist(snackbar.getRevokeButton()); + }); + + it('should close snackbar on close button', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getMessage()); + }); + + it('should show postfach mail in list', () => { + const postfachMailItem: PostfachMailListItem = postfachMailContainer.getListItem( + postfachMailToSend.subject, + ); + + exist(postfachMailItem.getRoot()); + exist(postfachMailItem.getUserProfile().getRoot()); + exist(postfachMailItem.getSentAt()); + contains(postfachMailItem.getSubject(), postfachMailToSend.subject); + contains(postfachMailItem.getText(), postfachMailToSend.mailBody); + }); + }); + + describe('click on postfach mail item with attachment', () => { + it('should show postfach item list', () => { + const postfachMailItem: PostfachMailListItem = postfachMailContainer.getListItem( + postfachMailToSend.subject, + ); + postfachMailItem.getRoot().click(); + waitForSpinnerToDisappear(); + + exist(postfachMailPage.getRoot()); + }); + + it('should contain mail item with attachment', () => { + const postfachListItem: PostfachMailListItem = postfachMailPage.getListItem( + postfachMailToSend.subject, + ); + + exist( + postfachListItem + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITH_CONTENT) + .getRoot(), + ); + }); + + it('should download attachment after click', () => { + const postfachListItem: PostfachMailListItem = postfachMailPage.getListItem( + postfachMailToSend.subject, + ); + + postfachListItem + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITH_CONTENT) + .getDownloadButton() + .click(); + waitForSpinnerToDisappear(); + + exist(readFileFromDownloads(TEST_FILE_WITHOUT_CONTENT)); + }); + }); + + describe('click on back button', () => { + it('should navigate to vorgang detail', () => { + postfachMailPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should navigate back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + }); + + describe('mail icon', () => { + it('should be visible', () => { + exist(vorgangList.getListItem(vorgang.name).getPostfachIcon()); + }); + }); + }); + + describe('navigate to vorgang detail', () => { + it('should open vorgang detail', () => { + waitForSpinnerToDisappear(); + vorgangList.getListItem(vorgangWithoutPostfach.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should not show postfach mail button', () => { + notExist(postfachMailContainer.getCreateButtonWithText()); + }); + + it('should not show postfach mail button in subnavigation', () => { + notExist(subnavigation.getPostfachMailIconButton()); + }); + + it('should show text for no postfach attached', () => { + contains( + postfachMailContainer.getNoPostfachText(), + 'Dieser Vorgang ist nicht mit einem Postfach verknüpft.', + ); + }); + + it('should navigate back to list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + }); + + describe('navigate to vorgang detail', () => { + it('should open vorgang detail', () => { + vorgangList.getListItem(vorgangWithReply.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should show postfach mail button', () => { + exist(postfachMailContainer.getCreateButtonWithText()); + }); + + it('should show postfach mail button in subnavigation', () => { + exist(subnavigation.getPostfachMailIconButton()); + }); + + it('should show postfach mail list', () => { + exist(postfachMailContainer.getList()); + }); + + it('should show postfach reply mail in list', () => { + exist(postfachMailContainer.getListItem(postfachMailReply.subject).getRoot()); + }); + + it('should show item reply icon', () => { + exist(postfachMailContainer.getListItem(postfachMailReply.subject).getReplyIcon()); + }); + + it('should show date', () => { + exist(postfachMailContainer.getListItem(postfachMailReply.subject).getCreatedAt()); + }); + + it('should show text', () => { + contains( + postfachMailContainer.getListItem(postfachMailReply.subject).getText(), + postfachMailReply.mailBody, + ); + }); + }); + + describe('click on postfach mail item', () => { + let postfachMailReplyItem: PostfachMailListItem; + + beforeEach(() => { + postfachMailReplyItem = postfachMailPage.getListItem(postfachMailReply.subject); + }); + + describe('postfach page', () => { + it('should open full view of postfachMailList', () => { + postfachMailReplyItem.getRoot().click(); + waitForSpinnerToDisappear(); + + exist(postfachMailPage.getRoot()); + }); + + it('should show subnavigation', () => { + exist(postfachMailPage.getSubnavigation().getBackButton()); + }); + + it('should show breadcrumb', () => { + contains(postfachMailPage.getBreadcrump(), vorgangWithReply.aktenzeichen); + }); + }); + + describe('reply item', () => { + it('should show item reply icon', () => { + exist(postfachMailReplyItem.getReplyIcon()); + }); + + it('should show reply subject', () => { + contains(postfachMailReplyItem.getSubject(), postfachMailReply.subject); + }); + + it('should show date', () => { + exist(postfachMailReplyItem.getCreatedAt()); + }); + + it('should show reply text', () => { + contains(postfachMailReplyItem.getText(), postfachMailReply.mailBody); + }); + }); + + describe('click on back button', () => { + it('should navigate to vorgang detail', () => { + postfachMailPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + }); + }); + + describe('mail icon', () => { + it('should navigate back to list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should be visible and not have a badge', () => { + const postfachStatusIcon: HTMLElement = vorgangList + .getListItem(vorgangWithReply.name) + .getPostfachIconMatIcon(); + expectIconWithoutBadge(postfachStatusIcon); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail.filtered-by-organisationseinheit.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail.filtered-by-organisationseinheit.cy.ts index 50e569cf23e1d08d5106406998eecc1edeb3e8a2..888db3fd22c6a58c04b437ccc9173389aa95481c 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail.filtered-by-organisationseinheit.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-mail.filtered-by-organisationseinheit.cy.ts @@ -29,111 +29,125 @@ import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main. import { PostfachMailPage } from '../../../page-objects/postfach-mail.component.po'; import { dropCollections, visitUrl } from '../../../support/cypress-helper'; import { contains, exist, notExist } from '../../../support/cypress.util'; -import { ORGANISATIONSEINHEITEN_ID_FOR_KFINDER, ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } from '../../../support/data.util'; +import { + ORGANISATIONSEINHEITEN_ID_FOR_KFINDER, + ORGANISATIONSEINHEITEN_ID_FOR_KORDNER, +} from '../../../support/data.util'; import { MessagesE2E } from '../../../support/messages'; import { loginAsKfinder, loginAsKordner } from '../../../support/user-util'; import { buildVorgang, createVorgang, initVorgaenge } from '../../../support/vorgang-util'; describe('PostfachNachrichten filtered by organisationseinheit', () => { - - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const postfachMailPage: PostfachMailPage = new PostfachMailPage(); - - const vorgangIdForKFinder: string = '601bc78eabc134051570aab8'; - const vorgangUrlVisibleToKFinder: string = `${createPostfachUriByVorgangId(vorgangIdForKFinder)}`; - - const eingangForKFinder: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KFINDER } }; - const vorgangForKFinder: VorgangE2E = { ...buildVorgang(vorgangIdForKFinder, 'VorgangVisibleToKFinder'), eingangs: [eingangForKFinder] }; - - const vorgangIdForKOrdner: string = '60250b9d383c182943f6ba79'; - const vorgangUrlVisibleToKOrdner: string = `${createPostfachUriByVorgangId(vorgangIdForKOrdner)}`; - - const eingangForKOrdner: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } }; - const vorgangForKOrdner: VorgangE2E = { ...buildVorgang(vorgangIdForKOrdner, 'VorgangVisibleToKOrdner'), eingangs: [eingangForKOrdner] }; - - before(() => { - initVorgaenge([vorgangForKFinder, vorgangForKOrdner]); - }) - - after(() => { - dropCollections(); - }) - - describe('on user kfinder', () => { - const authorizedUrl = vorgangUrlVisibleToKFinder; - const forbiddenUrl = vorgangUrlVisibleToKOrdner; - - before(() => { - loginAsKfinder(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - it('should open postfachNachrichten page', () => { - logInParts(authorizedUrl); - visitUrl(authorizedUrl); - waitForSpinnerToDisappear(); - - exist(postfachMailPage.getBreadcrump()); - }); - - it('should not open postfachNachrichten page', () => { - logInParts(forbiddenUrl); - visitUrl(forbiddenUrl); - waitForSpinnerToDisappear(); - - notExist(postfachMailPage.getBreadcrump()); - }) - - it('should show snackbar', () => { - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - }) - - describe('on user kordner', () => { - const authorizedUrl = vorgangUrlVisibleToKOrdner; - const forbiddenUrl = vorgangUrlVisibleToKFinder; - - before(() => { - loginAsKordner(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - it('should open postfachNachrichten page', () => { - logInParts(authorizedUrl); - visitUrl(authorizedUrl); - waitForSpinnerToDisappear(); - - exist(postfachMailPage.getBreadcrump()) - }) - - it('should not open postfachNachrichten page', () => { - logInParts(forbiddenUrl); - visitUrl(forbiddenUrl); - waitForSpinnerToDisappear(); - - notExist(postfachMailPage.getBreadcrump()) - }) - - it('should show snackbar', () => { - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - }) - - function logInParts(toLog: string): void { - const step: number = 10; - for (let i = 0; i < toLog.length;) { - const subUrl: string = toLog.slice(i, i + step); - Cypress.log({ name: `u.p.: ${subUrl}` }); - i += step; - } - } -}); \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const postfachMailPage: PostfachMailPage = new PostfachMailPage(); + + const vorgangIdForKFinder: string = '601bc78eabc134051570aab8'; + const vorgangUrlVisibleToKFinder: string = `${createPostfachUriByVorgangId(vorgangIdForKFinder)}`; + + const eingangForKFinder: EingangE2E = { + ...createVorgang().eingangs[0], + zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KFINDER }, + }; + const vorgangForKFinder: VorgangE2E = { + ...buildVorgang(vorgangIdForKFinder, 'VorgangVisibleToKFinder'), + eingangs: [eingangForKFinder], + }; + + const vorgangIdForKOrdner: string = '60250b9d383c182943f6ba79'; + const vorgangUrlVisibleToKOrdner: string = `${createPostfachUriByVorgangId(vorgangIdForKOrdner)}`; + + const eingangForKOrdner: EingangE2E = { + ...createVorgang().eingangs[0], + zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KORDNER }, + }; + const vorgangForKOrdner: VorgangE2E = { + ...buildVorgang(vorgangIdForKOrdner, 'VorgangVisibleToKOrdner'), + eingangs: [eingangForKOrdner], + }; + + before(() => { + initVorgaenge([vorgangForKFinder, vorgangForKOrdner]); + }); + + after(() => { + dropCollections(); + }); + + describe('on user kfinder', () => { + const authorizedUrl = vorgangUrlVisibleToKFinder; + const forbiddenUrl = vorgangUrlVisibleToKOrdner; + + before(() => { + loginAsKfinder(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + it('should open postfachNachrichten page', () => { + logInParts(authorizedUrl); + visitUrl(authorizedUrl); + waitForSpinnerToDisappear(); + + exist(postfachMailPage.getBreadcrump()); + }); + + it('should not open postfachNachrichten page', () => { + logInParts(forbiddenUrl); + visitUrl(forbiddenUrl); + waitForSpinnerToDisappear(); + + notExist(postfachMailPage.getBreadcrump()); + }); + + it('should show snackbar', () => { + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + }); + + describe('on user kordner', () => { + const authorizedUrl = vorgangUrlVisibleToKOrdner; + const forbiddenUrl = vorgangUrlVisibleToKFinder; + + before(() => { + loginAsKordner(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + it('should open postfachNachrichten page', () => { + logInParts(authorizedUrl); + visitUrl(authorizedUrl); + waitForSpinnerToDisappear(); + + exist(postfachMailPage.getBreadcrump()); + }); + + it('should not open postfachNachrichten page', () => { + logInParts(forbiddenUrl); + visitUrl(forbiddenUrl); + waitForSpinnerToDisappear(); + + notExist(postfachMailPage.getBreadcrump()); + }); + + it('should show snackbar', () => { + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + }); + + function logInParts(toLog: string): void { + const step: number = 10; + for (let i = 0; i < toLog.length; ) { + const subUrl: string = toLog.slice(i, i + step); + Cypress.log({ name: `u.p.: ${subUrl}` }); + i += step; + } + } +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachicht-reply-button.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachicht-reply-button.cy.ts index 757d7fb4d85740020369a2756df12b2951b96b3b..cb19920313105bbdfaee952467d914e1cabbf07b 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachicht-reply-button.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachicht-reply-button.cy.ts @@ -32,85 +32,87 @@ import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgaenge } from '../../../support/vorgang-util'; describe('Postfach Nachricht reply button', () => { - const vorgangList: VorgangListE2EComponent = new MainPage().getVorgangList(); - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangWithOsiServiceKonto: VorgangE2E = createVorgang(); - const vorgangWithBayernIdServiceKonto: VorgangE2E = { - ...createVorgang(), - _id: { - $oid: generate12ByteId() - }, - name: 'BayernID Vorgang', - header: { - serviceKonto: { - type: "BayernId", - postfachAddress: [{ - type: 1, - identifier: new Map([['postfachId', new Object('04d39269-81c5-4838-8b73-08d9567f06d7')]]) - }] - } - } - }; - - before(() => { - initVorgaenge([vorgangWithOsiServiceKonto, vorgangWithBayernIdServiceKonto]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('navigate to vorgang detail with OSI service konto', () => { - - it('should open vorgang detail', () => { - vorgangList.getListItem(vorgangWithOsiServiceKonto.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should open new message editor', () => { - vorgangPage.getPostfachMailcontainer().getCreateButtonWithText().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getPostfachMailFormular().getSendButton()); - }) - - it('should have reply option available', () => { - exist(vorgangPage.getPostfachMailFormular().getReplyOption().getRoot()); - }); - }) - - describe('navigate to vorgang detail with BayernID service konto', () => { - - it('should navigate to vorgang list page', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }); - - it('should open vorgang detail', () => { - vorgangList.getListItem(vorgangWithBayernIdServiceKonto.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should open new message editor', () => { - vorgangPage.getPostfachMailcontainer().getCreateButtonWithText().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getPostfachMailFormular().getSendButton()); - }) - - it('should not have reply option available', () => { - notExist(vorgangPage.getPostfachMailFormular().getReplyOption().getRoot()); - }); - }) -}) \ No newline at end of file + const vorgangList: VorgangListE2EComponent = new MainPage().getVorgangList(); + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangWithOsiServiceKonto: VorgangE2E = createVorgang(); + const vorgangWithBayernIdServiceKonto: VorgangE2E = { + ...createVorgang(), + _id: { + $oid: generate12ByteId(), + }, + name: 'BayernID Vorgang', + header: { + serviceKonto: { + type: 'BayernId', + postfachAddress: [ + { + type: 1, + identifier: new Map([ + ['postfachId', new Object('04d39269-81c5-4838-8b73-08d9567f06d7')], + ]), + }, + ], + }, + }, + }; + + before(() => { + initVorgaenge([vorgangWithOsiServiceKonto, vorgangWithBayernIdServiceKonto]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('navigate to vorgang detail with OSI service konto', () => { + it('should open vorgang detail', () => { + vorgangList.getListItem(vorgangWithOsiServiceKonto.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should open new message editor', () => { + vorgangPage.getPostfachMailcontainer().getCreateButtonWithText().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getPostfachMailFormular().getSendButton()); + }); + + it('should have reply option available', () => { + exist(vorgangPage.getPostfachMailFormular().getReplyOption().getRoot()); + }); + }); + + describe('navigate to vorgang detail with BayernID service konto', () => { + it('should navigate to vorgang list page', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should open vorgang detail', () => { + vorgangList.getListItem(vorgangWithBayernIdServiceKonto.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should open new message editor', () => { + vorgangPage.getPostfachMailcontainer().getCreateButtonWithText().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getPostfachMailFormular().getSendButton()); + }); + + it('should not have reply option available', () => { + notExist(vorgangPage.getPostfachMailFormular().getReplyOption().getRoot()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachricht-authorize-by-role.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachricht-authorize-by-role.cy.ts index 523f58d5b8e757a012bd74f70ff032b7c77786c9..8c3249d22d492ae7c45fd02178c8bda5053ec246 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachricht-authorize-by-role.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachricht-authorize-by-role.cy.ts @@ -33,72 +33,92 @@ import { UserRoleE2E, loginAsPeter } from 'apps/alfa-e2e/src/support/user-util'; import { buildVorgang, initVorgaenge } from 'apps/alfa-e2e/src/support/vorgang-util'; describe('Postfach Nachricht should be authorized by role', () => { - - const mainPage: MainPage = new MainPage(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const postfachNachrichtPage: PostfachMailPage = new PostfachMailPage(); - - describe(`for user Peter with role ${UserRoleE2E.VERWALTUNG_POSTSTELLE}`, () => { - - const vorgangInStatusNeuId: string = '601bc78eabc134051570aab8'; - const vorgangInStatusNeuUrl: string = createPostfachUriByVorgangId(vorgangInStatusNeuId); - const vorgangInStatusNeu: VorgangE2E = { ...buildVorgang(vorgangInStatusNeuId, 'VorgangInStatusNeu'), status: VorgangStatusE2E.NEU }; - - const vorgangInStatusInBearbeitungId = '60250b9d383c182943f6ba79'; - const vorgangInStatusInBearbeitungUrl: string = createPostfachUriByVorgangId(vorgangInStatusInBearbeitungId); - const vorgangInStatusInBearbeitung: VorgangE2E = { ...buildVorgang(vorgangInStatusInBearbeitungId, 'vorgangInStatusInBearbeitung'), status: VorgangStatusE2E.IN_BEARBEITUNG }; - - const vorgangInStatusAbgeschlossenId: string = '602566a807bb665df9a86e87'; - const vorgangInStatusAbgeschlossenUrl: string = createPostfachUriByVorgangId(vorgangInStatusAbgeschlossenId); - const vorgangInStatusAbgeschlossen: VorgangE2E = { ...buildVorgang(vorgangInStatusAbgeschlossenId, 'vorgangInStatusAbgeschlossen'), status: VorgangStatusE2E.ABGESCHLOSSEN }; - - const vorgangInStatusBeschiedenId: string = '602566a207bb665df9a86e86'; - const vorgangInStatusBeschiedenUrl: string = createPostfachUriByVorgangId(vorgangInStatusBeschiedenId); - const vorgangInStatusBeschieden: VorgangE2E = { ...buildVorgang(vorgangInStatusBeschiedenId, 'vorgangInStatusBeschieden'), status: VorgangStatusE2E.BESCHIEDEN }; - - beforeEach(() => { - initVorgaenge([vorgangInStatusNeu, vorgangInStatusInBearbeitung, vorgangInStatusAbgeschlossen, vorgangInStatusBeschieden]); - - loginAsPeter(); - }) - - after(() => { - dropCollections(); - }) - - it(`should show vorgang in Stauts ${VorgangStatusE2E.NEU}`, () => { - visitUrl(vorgangInStatusNeuUrl); - waitForSpinnerToDisappear(); - - exist(postfachNachrichtPage.getRoot()); - }) - - describe('should hide vorgang in status', () => { - - it(`${VorgangStatusE2E.IN_BEARBEITUNG}`, () => { - visitUrl(vorgangInStatusInBearbeitungUrl); - waitForSpinnerToDisappear(); - - notExist(postfachNachrichtPage.getRoot()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - - it(`${VorgangStatusE2E.ABGESCHLOSSEN}`, () => { - visitUrl(vorgangInStatusAbgeschlossenUrl); - waitForSpinnerToDisappear(); - - notExist(postfachNachrichtPage.getRoot()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - - it(`${VorgangStatusE2E.BESCHIEDEN}`, () => { - visitUrl(vorgangInStatusBeschiedenUrl); - waitForSpinnerToDisappear(); - - notExist(postfachNachrichtPage.getRoot()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - }) - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const postfachNachrichtPage: PostfachMailPage = new PostfachMailPage(); + + describe(`for user Peter with role ${UserRoleE2E.VERWALTUNG_POSTSTELLE}`, () => { + const vorgangInStatusNeuId: string = '601bc78eabc134051570aab8'; + const vorgangInStatusNeuUrl: string = createPostfachUriByVorgangId(vorgangInStatusNeuId); + const vorgangInStatusNeu: VorgangE2E = { + ...buildVorgang(vorgangInStatusNeuId, 'VorgangInStatusNeu'), + status: VorgangStatusE2E.NEU, + }; + + const vorgangInStatusInBearbeitungId = '60250b9d383c182943f6ba79'; + const vorgangInStatusInBearbeitungUrl: string = createPostfachUriByVorgangId( + vorgangInStatusInBearbeitungId, + ); + const vorgangInStatusInBearbeitung: VorgangE2E = { + ...buildVorgang(vorgangInStatusInBearbeitungId, 'vorgangInStatusInBearbeitung'), + status: VorgangStatusE2E.IN_BEARBEITUNG, + }; + + const vorgangInStatusAbgeschlossenId: string = '602566a807bb665df9a86e87'; + const vorgangInStatusAbgeschlossenUrl: string = createPostfachUriByVorgangId( + vorgangInStatusAbgeschlossenId, + ); + const vorgangInStatusAbgeschlossen: VorgangE2E = { + ...buildVorgang(vorgangInStatusAbgeschlossenId, 'vorgangInStatusAbgeschlossen'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + + const vorgangInStatusBeschiedenId: string = '602566a207bb665df9a86e86'; + const vorgangInStatusBeschiedenUrl: string = createPostfachUriByVorgangId( + vorgangInStatusBeschiedenId, + ); + const vorgangInStatusBeschieden: VorgangE2E = { + ...buildVorgang(vorgangInStatusBeschiedenId, 'vorgangInStatusBeschieden'), + status: VorgangStatusE2E.BESCHIEDEN, + }; + + beforeEach(() => { + initVorgaenge([ + vorgangInStatusNeu, + vorgangInStatusInBearbeitung, + vorgangInStatusAbgeschlossen, + vorgangInStatusBeschieden, + ]); + + loginAsPeter(); + }); + + after(() => { + dropCollections(); + }); + + it(`should show vorgang in Stauts ${VorgangStatusE2E.NEU}`, () => { + visitUrl(vorgangInStatusNeuUrl); + waitForSpinnerToDisappear(); + + exist(postfachNachrichtPage.getRoot()); + }); + + describe('should hide vorgang in status', () => { + it(`${VorgangStatusE2E.IN_BEARBEITUNG}`, () => { + visitUrl(vorgangInStatusInBearbeitungUrl); + waitForSpinnerToDisappear(); + + notExist(postfachNachrichtPage.getRoot()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + + it(`${VorgangStatusE2E.ABGESCHLOSSEN}`, () => { + visitUrl(vorgangInStatusAbgeschlossenUrl); + waitForSpinnerToDisappear(); + + notExist(postfachNachrichtPage.getRoot()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + + it(`${VorgangStatusE2E.BESCHIEDEN}`, () => { + visitUrl(vorgangInStatusBeschiedenUrl); + waitForSpinnerToDisappear(); + + notExist(postfachNachrichtPage.getRoot()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachrichten.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachrichten.cy.ts index da761e11d027585bfe566b673de10abef2dc3a1e..77d778c365f4ce284e47123783e5847b3cf44f16 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachrichten.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/postfach-mail/postfach-nachrichten.cy.ts @@ -23,7 +23,11 @@ */ import { PostfachMailE2EComponent } from 'apps/alfa-e2e/src/components/postfach/postfach-mail.e2e.component'; import { PostfachMailPage } from 'apps/alfa-e2e/src/page-objects/postfach-mail.component.po'; -import { createPostfachNachrichtAttachedItem, createPostfachNachrichtReplyItem, initVorgangAttachedItem } from 'apps/alfa-e2e/src/support/vorgang-attached-item-util'; +import { + createPostfachNachrichtAttachedItem, + createPostfachNachrichtReplyItem, + initVorgangAttachedItem, +} from 'apps/alfa-e2e/src/support/vorgang-attached-item-util'; import { CyHttpMessages } from 'cypress/types/net-stubbing'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { HttpMethodE2E } from '../../../model/util'; @@ -31,109 +35,122 @@ import { VorgangE2E } from '../../../model/vorgang'; import { PostfachMailItemE2E, VorgangAttachedItemE2E } from '../../../model/vorgang-attached-item'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; -import { countDownloadFiles, deleteDownloadFolder, dropCollections, interceptWithResponse } from '../../../support/cypress-helper'; +import { + countDownloadFiles, + deleteDownloadFolder, + dropCollections, + interceptWithResponse, +} from '../../../support/cypress-helper'; import { exist, notExist } from '../../../support/cypress.util'; import { LinkRelE2E } from '../../../support/linkrels'; import { removeLinkFromResource } from '../../../support/tech.util'; -import { getUserManagerUserSabine, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; - +import { + getUserManagerUserSabine, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; describe('Postfach Nachrichten', () => { - const vorgangList: VorgangListE2EComponent = new MainPage().getVorgangList(); - const vorgangPage: VorgangPage = new VorgangPage(); - const postfachMailContainer: PostfachMailE2EComponent = vorgangPage.getPostfachMailcontainer(); - const postfachMailPage: PostfachMailPage = new PostfachMailPage(); - - const vorgang: VorgangE2E = createVorgang(); - const vorgangWithReply: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangWithReply') }; - - const postfachMailReply: PostfachMailItemE2E = createPostfachNachrichtReplyItem(); - const postfachNachrichtAttachedItem: VorgangAttachedItemE2E = { ...createPostfachNachrichtAttachedItem(objectIds[1], objectIds[0]), item: postfachMailReply }; - - before(() => { - initVorgaenge([vorgang, vorgangWithReply]); - initVorgangAttachedItem([postfachNachrichtAttachedItem]); - initUsermanagerUsers([getUserManagerUserSabine()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('navigate to vorgangDetail', () => { - - beforeEach(() => { - interceptWithResponse(HttpMethodE2E.GET, '*/vorgangs/*', (req) => modifyResponse(req)); - }) - - function modifyResponse(req: CyHttpMessages.IncomingHttpRequest): void { - req.reply(res => res.send(removeLinkFromResource(res.body, LinkRelE2E.POSTFACH_NACHRICHTEN))); - } - - it('navigate to vorgangDetail', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should hide postfach nachrichten area if no postfach is configured', () => { - notExist(vorgangPage.getPostfachMailcontainer().getRoot()); - }) - }) - - describe('download nachrichten as pdf', () => { - - describe('by download button on vorgang main page', () => { - - it('should be visible as icon button', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - vorgangList.getListItem(vorgangWithReply.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(postfachMailContainer.getDownloadButtonWithLabel()); - }) - - it('should have 1 file in download folder after click on download', () => { - deleteDownloadFolder(); - postfachMailContainer.getDownloadButtonWithLabel().click(); - waitForSpinnerToDisappear(); - - countDownloadFiles().then((count) => { - expect(count).to.eq(1); - }); - }) - }) - - describe('by download button on nachrichten details page', () => { - - it ('should show an overview of all nachrichten after clicking on nachricht', () => { - postfachMailContainer.getList().click(); - waitForSpinnerToDisappear(); - - exist(postfachMailPage.getRoot()); - }) - - it ('should exist a pdf download button', () => { - exist(postfachMailPage.getDownloadButton()); - }) - - it('should have 1 file in download folder after click on download', () => { - deleteDownloadFolder(); - postfachMailPage.getDownloadButton().click(); - waitForSpinnerToDisappear(); - - countDownloadFiles().then((count) => { - expect(count).to.eq(1); - }); - }) - }) - - }) -}) \ No newline at end of file + const vorgangList: VorgangListE2EComponent = new MainPage().getVorgangList(); + const vorgangPage: VorgangPage = new VorgangPage(); + const postfachMailContainer: PostfachMailE2EComponent = vorgangPage.getPostfachMailcontainer(); + const postfachMailPage: PostfachMailPage = new PostfachMailPage(); + + const vorgang: VorgangE2E = createVorgang(); + const vorgangWithReply: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangWithReply') }; + + const postfachMailReply: PostfachMailItemE2E = createPostfachNachrichtReplyItem(); + const postfachNachrichtAttachedItem: VorgangAttachedItemE2E = { + ...createPostfachNachrichtAttachedItem(objectIds[1], objectIds[0]), + item: postfachMailReply, + }; + + before(() => { + initVorgaenge([vorgang, vorgangWithReply]); + initVorgangAttachedItem([postfachNachrichtAttachedItem]); + initUsermanagerUsers([getUserManagerUserSabine()]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('navigate to vorgangDetail', () => { + beforeEach(() => { + interceptWithResponse(HttpMethodE2E.GET, '*/vorgangs/*', (req) => modifyResponse(req)); + }); + + function modifyResponse(req: CyHttpMessages.IncomingHttpRequest): void { + req.reply((res) => + res.send(removeLinkFromResource(res.body, LinkRelE2E.POSTFACH_NACHRICHTEN)), + ); + } + + it('navigate to vorgangDetail', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should hide postfach nachrichten area if no postfach is configured', () => { + notExist(vorgangPage.getPostfachMailcontainer().getRoot()); + }); + }); + + describe('download nachrichten as pdf', () => { + describe('by download button on vorgang main page', () => { + it('should be visible as icon button', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + vorgangList.getListItem(vorgangWithReply.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(postfachMailContainer.getDownloadButtonWithLabel()); + }); + + it('should have 1 file in download folder after click on download', () => { + deleteDownloadFolder(); + postfachMailContainer.getDownloadButtonWithLabel().click(); + waitForSpinnerToDisappear(); + + countDownloadFiles().then((count) => { + expect(count).to.eq(1); + }); + }); + }); + + describe('by download button on nachrichten details page', () => { + it('should show an overview of all nachrichten after clicking on nachricht', () => { + postfachMailContainer.getList().click(); + waitForSpinnerToDisappear(); + + exist(postfachMailPage.getRoot()); + }); + + it('should exist a pdf download button', () => { + exist(postfachMailPage.getDownloadButton()); + }); + + it('should have 1 file in download folder after click on download', () => { + deleteDownloadFolder(); + postfachMailPage.getDownloadButton().click(); + waitForSpinnerToDisappear(); + + countDownloadFiles().then((count) => { + expect(count).to.eq(1); + }); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts index 5e70ef93ee76652108a1bd5ef1de637418207fb0..7730e9aaf50e98e8def88c877f52c2fda19d31cd 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-assistance/help-menu.cy.ts @@ -6,35 +6,33 @@ import { exist } from 'apps/alfa-e2e/src/support/cypress.util'; import { loginAsSabine } from 'apps/alfa-e2e/src/support/user-util'; describe('Help Menu', () => { - const mainPage: MainPage = new MainPage(); - const header: HeaderE2EComponent = mainPage.getHeader(); - const helpMenu: HelpMenuE2EComponent = header.getHelpMenu(); + const mainPage: MainPage = new MainPage(); + const header: HeaderE2EComponent = mainPage.getHeader(); + const helpMenu: HelpMenuE2EComponent = header.getHelpMenu(); - before(() => { - loginAsSabine(); + before(() => { + loginAsSabine(); - waitForSpinnerToDisappear(); - exist(header.getRoot()); - }) + waitForSpinnerToDisappear(); + exist(header.getRoot()); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('open documentation', () => { + describe('open documentation', () => { + it('should show "open documentation" button', () => { + helpMenu.getRoot().click(); - it('should show "open documentation" button', () => { - helpMenu.getRoot().click(); + exist(helpMenu.getOpenDocumentationButton()); + }); - exist(helpMenu.getOpenDocumentationButton()); - }) + // TODO: Get URL of documentation from /api request + it.skip('should open file', () => { + helpMenu.getOpenDocumentationButton().find('a').invoke('removeAttr', 'target').click(); - // TODO: Get URL of documentation from /api request - it.skip('should open file', () => { - helpMenu.getOpenDocumentationButton().find('a').invoke('removeAttr', 'target').click(); - - // urlShouldInclude('Benutzerleitfaden'); - }) - }) - -}) \ No newline at end of file + // urlShouldInclude('Benutzerleitfaden'); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-current-user-icon.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-current-user-icon.cy.ts index cc7aa7d1541ce33faa348b3e375117dcf18a7709..828731e4561a47418fa208dae58fa09be8734225 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-current-user-icon.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-current-user-icon.cy.ts @@ -24,45 +24,56 @@ import { CurrentUserProfileE2EComponent } from 'apps/alfa-e2e/src/components/user-profile/current-user-profile.component.e2e'; import { UserE2E } from 'apps/alfa-e2e/src/model/user'; import { HeaderE2EComponent } from 'apps/alfa-e2e/src/page-objects/header.po'; -import { MainPage, waitForSpinnerToDisappear, waitforSpinnerToAppear } from 'apps/alfa-e2e/src/page-objects/main.po'; +import { + MainPage, + waitForSpinnerToDisappear, + waitforSpinnerToAppear, +} from 'apps/alfa-e2e/src/page-objects/main.po'; import { dropCollections } from 'apps/alfa-e2e/src/support/cypress-helper'; import { exist, haveText } from 'apps/alfa-e2e/src/support/cypress.util'; -import { getUserManagerUserSabine, getUserSabine, initUsermanagerUsers, loginAsSabine } from 'apps/alfa-e2e/src/support/user-util'; +import { + getUserManagerUserSabine, + getUserSabine, + initUsermanagerUsers, + loginAsSabine, +} from 'apps/alfa-e2e/src/support/user-util'; describe('Current User Profile', () => { - const mainPage: MainPage = new MainPage(); + const mainPage: MainPage = new MainPage(); - const header: HeaderE2EComponent = mainPage.getHeader(); - const currentUserProfile: CurrentUserProfileE2EComponent = header.getCurrentUserProfile(); + const header: HeaderE2EComponent = mainPage.getHeader(); + const currentUserProfile: CurrentUserProfileE2EComponent = header.getCurrentUserProfile(); - const userSabine: UserE2E = getUserSabine(); + const userSabine: UserE2E = getUserSabine(); - describe('for sabine', () => { + describe('for sabine', () => { + before(() => { + initUsermanagerUsers([getUserManagerUserSabine()]); - before(() => { - initUsermanagerUsers([getUserManagerUserSabine()]); + loginAsSabine(); - loginAsSabine(); + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + exist(header.getRoot()); + }); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - exist(header.getRoot()); - }) + after(() => { + dropCollections(); + }); - after(() => { - dropCollections(); - }) + it('should show current user profile', () => { + exist(currentUserProfile.getRoot()); + }); - it('should show current user profile', () => { - exist(currentUserProfile.getRoot()); - }) + it('should show assigned icon', () => { + exist(currentUserProfile.getUserProfile().getIconContainer().getAssignedIcon()); + }); - it('should show assigned icon', () => { - exist(currentUserProfile.getUserProfile().getIconContainer().getAssignedIcon()); - }) - - it('should show initials', () => { - haveText(currentUserProfile.getUserProfile().getIconContainer().getAssignedIcon(), userSabine.initials); - }) - }) -}) \ No newline at end of file + it('should show initials', () => { + haveText( + currentUserProfile.getUserProfile().getIconContainer().getAssignedIcon(), + userSabine.initials, + ); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-assign-unassign.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-assign-unassign.cy.ts index bcfddd084bc8ec429fd218c339ea26aa77f43241..a968e8044084fa66d06dfce6e09cba3f663ac777 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-assign-unassign.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-assign-unassign.cy.ts @@ -26,167 +26,191 @@ import { VorgangListItemE2EComponent } from '../../../components/vorgang/vorgang import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { UserE2E } from '../../../model/user'; import { VorgangE2E } from '../../../model/vorgang'; -import { MainPage, waitForSpinnerToDisappear, waitforSpinnerToAppear } from '../../../page-objects/main.po'; +import { + MainPage, + waitForSpinnerToDisappear, + waitforSpinnerToAppear, +} from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections, wait } from '../../../support/cypress-helper'; import { enter, exist, haveText, notExist } from '../../../support/cypress.util'; -import { getUserDorothea, getUserManagerUserDorothea, getUserManagerUserSabine, getUserSabine, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; +import { + getUserDorothea, + getUserManagerUserDorothea, + getUserManagerUserSabine, + getUserSabine, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; describe('User Profile im ausgewählten Vorgang', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const userProfileContainer: UserProfileE2EComponent = vorgangPage.getVorgangDetailHeader().getUserContainer(); - - const vorgang: VorgangE2E = createVorgang(); - - const userSabine: UserE2E = getUserSabine(); - const userDorothea: UserE2E = getUserDorothea(); - - before(() => { - initVorgang(vorgang); - initUsermanagerUsers([getUserManagerUserSabine(), getUserManagerUserDorothea()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('icon in list', () => { - - it('should have icon', () => { - const item: VorgangListItemE2EComponent = vorgangList.getListItem(vorgang.name); - - exist(item.getUserProfile().getRoot()); - }) - }) - - describe('icon in vorgang detail', () => { - - it('open vorgang detail', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should show icon', () => { - exist(userProfileContainer.getIconContainer().getRoot()); - }) - - it('should show formular on icon click', () => { - userProfileContainer.getIconContainer().getRoot().click(); - - exist(userProfileContainer.getSearchContainer().getRoot()); - }) - - describe('fill formular', () => { - - it('should show error on enter wrong input', () => { - userProfileContainer.getSearchContainer().getInput().clear().type('Clark Kent'); - enter(userProfileContainer.getSearchContainer().getInput()); - - exist(userProfileContainer.getSearchContainer().getError()); - exist(userProfileContainer.getIconContainer().getUnassignedIcon()); - }) - - it('should show error on enter empty field', () => { - enter(userProfileContainer.getSearchContainer().getInput()); - - exist(userProfileContainer.getSearchContainer().getError()); - exist(userProfileContainer.getIconContainer().getUnassignedIcon()); - }) - - describe('on valid formular', () => { - - it('should hide formular', () => { - userProfileContainer.getSearchContainer().getInput().clear().type(userSabine.name); - exist(userProfileContainer.getSearchContainer().getSearchOption(userSabine.dataTestId)); - userProfileContainer.getSearchContainer().getSearchOption(userSabine.dataTestId).click(); - - notExist(userProfileContainer.getSearchContainer().getError()); - }) - - it('should show assign icon', { defaultCommandTimeout: 30000 }, () => { - waitForSpinnerToDisappear(); - exist(userProfileContainer.getIconContainer().getAssignedIcon()); - haveText(userProfileContainer.getIconContainer().getAssignedIcon(), userSabine.initials) - }) - }) - }) - - describe('navigate to list', () => { - - it('should show assigned icon', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - - exist(vorgangList.getRoot()); - waitForSpinnerToDisappear(); - - exist(vorgangList.getListItem(vorgang.name).getUserProfile().getRoot()); - haveText(vorgangList.getListItem(vorgang.name).getUserProfile().getIconContainer().getAssignedIcon(), userSabine.initials); - }) - }) - - describe('open vorgang detail', () => { - - it('open vorgang detail', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - }) - - describe('click on subnavigation icon button', () => { - - it('should show formular on icon click', () => { - vorgangPage.getSubnavigation().getAssignUserProfileIconButton().click(); - - exist(userProfileContainer.getSearchContainer().getRoot()); - }) - - describe('on valid formular', () => { - - it('should hide formular', () => { - userProfileContainer.getSearchContainer().getInput().clear().type(userDorothea.name); - exist(userProfileContainer.getSearchContainer().getSearchOption(userDorothea.dataTestId)); - userProfileContainer.getSearchContainer().getSearchOption(userDorothea.dataTestId).click(); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - notExist(userProfileContainer.getSearchContainer().getError()); - }) - - it('should show assign icon', { defaultCommandTimeout: 30000 }, () => { - waitForSpinnerToDisappear(); - // WORKAROUND Hier muss aufs Verarbeiten im Backend gewartet werden - oder: wait(500) - wait(500); - exist(userProfileContainer.getIconContainer().getAssignedIcon()); - haveText(userProfileContainer.getIconContainer().getAssignedIcon(), userDorothea.initials) - }) - }) - }) - - describe('navigate to list', () => { - - it('should show assigned icon', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - - exist(vorgangList.getRoot()); - waitForSpinnerToDisappear(); - - exist(vorgangList.getListItem(vorgang.name).getUserProfile().getRoot()); - haveText(vorgangList.getListItem(vorgang.name).getUserProfile().getIconContainer().getAssignedIcon(), userDorothea.initials); - }) - }) - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const userProfileContainer: UserProfileE2EComponent = vorgangPage + .getVorgangDetailHeader() + .getUserContainer(); + + const vorgang: VorgangE2E = createVorgang(); + + const userSabine: UserE2E = getUserSabine(); + const userDorothea: UserE2E = getUserDorothea(); + + before(() => { + initVorgang(vorgang); + initUsermanagerUsers([getUserManagerUserSabine(), getUserManagerUserDorothea()]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('icon in list', () => { + it('should have icon', () => { + const item: VorgangListItemE2EComponent = vorgangList.getListItem(vorgang.name); + + exist(item.getUserProfile().getRoot()); + }); + }); + + describe('icon in vorgang detail', () => { + it('open vorgang detail', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should show icon', () => { + exist(userProfileContainer.getIconContainer().getRoot()); + }); + + it('should show formular on icon click', () => { + userProfileContainer.getIconContainer().getRoot().click(); + + exist(userProfileContainer.getSearchContainer().getRoot()); + }); + + describe('fill formular', () => { + it('should show error on enter wrong input', () => { + userProfileContainer.getSearchContainer().getInput().clear().type('Clark Kent'); + enter(userProfileContainer.getSearchContainer().getInput()); + + exist(userProfileContainer.getSearchContainer().getError()); + exist(userProfileContainer.getIconContainer().getUnassignedIcon()); + }); + + it('should show error on enter empty field', () => { + enter(userProfileContainer.getSearchContainer().getInput()); + + exist(userProfileContainer.getSearchContainer().getError()); + exist(userProfileContainer.getIconContainer().getUnassignedIcon()); + }); + + describe('on valid formular', () => { + it('should hide formular', () => { + userProfileContainer.getSearchContainer().getInput().clear().type(userSabine.name); + exist(userProfileContainer.getSearchContainer().getSearchOption(userSabine.dataTestId)); + userProfileContainer.getSearchContainer().getSearchOption(userSabine.dataTestId).click(); + + notExist(userProfileContainer.getSearchContainer().getError()); + }); + + it('should show assign icon', { defaultCommandTimeout: 30000 }, () => { + waitForSpinnerToDisappear(); + exist(userProfileContainer.getIconContainer().getAssignedIcon()); + haveText(userProfileContainer.getIconContainer().getAssignedIcon(), userSabine.initials); + }); + }); + }); + + describe('navigate to list', () => { + it('should show assigned icon', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + + exist(vorgangList.getRoot()); + waitForSpinnerToDisappear(); + + exist(vorgangList.getListItem(vorgang.name).getUserProfile().getRoot()); + haveText( + vorgangList + .getListItem(vorgang.name) + .getUserProfile() + .getIconContainer() + .getAssignedIcon(), + userSabine.initials, + ); + }); + }); + + describe('open vorgang detail', () => { + it('open vorgang detail', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + }); + + describe('click on subnavigation icon button', () => { + it('should show formular on icon click', () => { + vorgangPage.getSubnavigation().getAssignUserProfileIconButton().click(); + + exist(userProfileContainer.getSearchContainer().getRoot()); + }); + + describe('on valid formular', () => { + it('should hide formular', () => { + userProfileContainer.getSearchContainer().getInput().clear().type(userDorothea.name); + exist(userProfileContainer.getSearchContainer().getSearchOption(userDorothea.dataTestId)); + userProfileContainer + .getSearchContainer() + .getSearchOption(userDorothea.dataTestId) + .click(); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + notExist(userProfileContainer.getSearchContainer().getError()); + }); + + it('should show assign icon', { defaultCommandTimeout: 30000 }, () => { + waitForSpinnerToDisappear(); + // WORKAROUND Hier muss aufs Verarbeiten im Backend gewartet werden - oder: wait(500) + wait(500); + exist(userProfileContainer.getIconContainer().getAssignedIcon()); + haveText( + userProfileContainer.getIconContainer().getAssignedIcon(), + userDorothea.initials, + ); + }); + }); + }); + + describe('navigate to list', () => { + it('should show assigned icon', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + + exist(vorgangList.getRoot()); + waitForSpinnerToDisappear(); + + exist(vorgangList.getListItem(vorgang.name).getUserProfile().getRoot()); + haveText( + vorgangList + .getListItem(vorgang.name) + .getUserProfile() + .getIconContainer() + .getAssignedIcon(), + userDorothea.initials, + ); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-kommentar-error.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-kommentar-error.cy.ts index 115d402bf21f2122ba24974497ea670de0b5dfd7..8c54689f4bc9ea388c788f337b8bfd949e37fdc3 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-kommentar-error.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-kommentar-error.cy.ts @@ -28,7 +28,12 @@ import { KommentarE2E } from '../../../model/kommentar'; import { VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; -import { dropCollections, interceptWithResponse, scrollToWindowBottom, waitOfInterceptor } from '../../../support/cypress-helper'; +import { + dropCollections, + interceptWithResponse, + scrollToWindowBottom, + waitOfInterceptor, +} from '../../../support/cypress-helper'; import { exist, notExist } from '../../../support/cypress.util'; import { createKommentar } from '../../../support/kommentar.util'; import { loginAsSabine } from '../../../support/user-util'; @@ -37,101 +42,102 @@ import { createVorgang, initVorgang } from '../../../support/vorgang-util'; // TODO Deaktiviert, weil die beiden Testfälle in user-profile-icon-in-postfach-nachricht-error.e2e-spec.ts abgedeckt sind. // Zudem funktioniert der Test seit OZG-1523 so nicht länger. describe.skip('Kommentar user profile backend error', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const vorgangPage: VorgangPage = new VorgangPage(); - const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); + const vorgangPage: VorgangPage = new VorgangPage(); + const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); - const kommentar: KommentarE2E = { ...createKommentar(), createdBy: 'idNotExist' }; - const vorgang: VorgangE2E = { ...createVorgang(), kommentars: [kommentar] }; + const kommentar: KommentarE2E = { ...createKommentar(), createdBy: 'idNotExist' }; + const vorgang: VorgangE2E = { ...createVorgang(), kommentars: [kommentar] }; - before(() => { - initVorgang(vorgang); + before(() => { + initVorgang(vorgang); - loginAsSabine(); + loginAsSabine(); - exist(vorgangList.getRoot()); - }) + exist(vorgangList.getRoot()); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('on status 404', () => { + describe('on status 404', () => { + let kommentarToExist; - let kommentarToExist; + it('should navigate to vorgang detail', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); - it('should navigate to vorgang detail', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + waitForSpinnerToDisappear(); + }); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - waitForSpinnerToDisappear(); - }) + it('should show kommentar', () => { + scrollToWindowBottom(); - it('should show kommentar', () => { - scrollToWindowBottom(); + kommentarToExist = kommentarContainer.getKommentar(kommentar.text); - kommentarToExist = kommentarContainer.getKommentar(kommentar.text); + exist(kommentarToExist.getRoot()); + }); - exist(kommentarToExist.getRoot()); - }) + it('should show error not found icon', () => { + exist(kommentarToExist.getUserProfile().getIconContainer().getErrorResourceNotFoundIcon()); + }); - it('should show error not found icon', () => { - exist(kommentarToExist.getUserProfile().getIconContainer().getErrorResourceNotFoundIcon()); - }) + it('should hide user profile name', () => { + notExist(kommentarToExist.getUserProfile().getName()); + }); - it('should hide user profile name', () => { - notExist(kommentarToExist.getUserProfile().getName()); - }) + it('should navigate back to list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + }); + }); - it('should navigate back to list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - }) - }) + describe('on status 503', () => { + const statusCode: number = 503; + const getUserProfileInterceptor: string = 'getUserProfileInterceptor'; - describe('on status 503', () => { + let kommentarToExist; - const statusCode: number = 503; - const getUserProfileInterceptor: string = 'getUserProfileInterceptor'; + beforeEach(() => { + interceptWithResponse(HttpMethodE2E.GET, '/api/userProfiles/*', { + statusCode, + body: { issues: [{ messageCode: MessageCodeE2E.SERVICE_UNAVAILABLE }] }, + }).as(getUserProfileInterceptor); + }); - let kommentarToExist; + it('should show vorgang detail after click on vorgang', () => { + waitForSpinnerToDisappear(); + vorgangList.getListItem(vorgang.name).getRoot().click(); - beforeEach(() => { - interceptWithResponse(HttpMethodE2E.GET, '/api/userProfiles/*', { statusCode, body: { issues: [{ messageCode: MessageCodeE2E.SERVICE_UNAVAILABLE }] } }).as(getUserProfileInterceptor); - }) + waitOfInterceptor(getUserProfileInterceptor).then((interception) => { + assert(interception.response.statusCode, statusCode.toString()); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + waitForSpinnerToDisappear(); + }); + }); - it('should show vorgang detail after click on vorgang', () => { - waitForSpinnerToDisappear(); - vorgangList.getListItem(vorgang.name).getRoot().click(); + it('should show kommentar', () => { + scrollToWindowBottom(); - waitOfInterceptor(getUserProfileInterceptor).then((interception) => { - assert(interception.response.statusCode, statusCode.toString()); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - waitForSpinnerToDisappear(); - }) - }) + kommentarToExist = kommentarContainer.getKommentar(kommentar.text); - it('should show kommentar', () => { - scrollToWindowBottom(); + exist(kommentarToExist.getRoot()); + }); - kommentarToExist = kommentarContainer.getKommentar(kommentar.text); + it('should show error service unavailable icon', () => { + scrollToWindowBottom(); - exist(kommentarToExist.getRoot()); - }) + exist(kommentarToExist.getUserProfile().getIconContainer().getErrorServiceUnavailableIcon()); + }); - it('should show error service unavailable icon', () => { - scrollToWindowBottom(); + it('should hide user profile name', () => { + notExist(kommentarToExist.getUserProfile().getName()); + }); - exist(kommentarToExist.getUserProfile().getIconContainer().getErrorServiceUnavailableIcon()); - }) - - it('should hide user profile name', () => { - notExist(kommentarToExist.getUserProfile().getName()); - }) - - it('should navigate back', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - }) - }) -}) \ No newline at end of file + it('should navigate back', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-postfach-nachricht-error.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-postfach-nachricht-error.cy.ts index f5557de7cb31ca4599ac2ee831d984c1e1dadf3f..1b585f6ca84665d853d07b887290beea5ede2758 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-postfach-nachricht-error.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-postfach-nachricht-error.cy.ts @@ -25,108 +25,155 @@ import { PostfachMailE2EComponent } from '../../../components/postfach/postfach- import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { HttpMethodE2E, MessageCodeE2E } from '../../../model/util'; import { VorgangE2E } from '../../../model/vorgang'; -import { DirectionE2E, PostfachMailItemE2E, VorgangAttachedItemE2E } from '../../../model/vorgang-attached-item'; +import { + DirectionE2E, + PostfachMailItemE2E, + VorgangAttachedItemE2E, +} from '../../../model/vorgang-attached-item'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; -import { dropCollections, interceptWithResponse, waitOfInterceptor } from '../../../support/cypress-helper'; +import { + dropCollections, + interceptWithResponse, + waitOfInterceptor, +} from '../../../support/cypress-helper'; import { exist, notExist } from '../../../support/cypress.util'; -import { getUserManagerUserEmil, getUserManagerUserPeter, getUserManagerUserSabine, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; -import { createPostfachNachrichtAttachedItem, createPostfachNachrichtReplyItem, initVorgangAttachedItem } from '../../../support/vorgang-attached-item-util'; +import { + getUserManagerUserEmil, + getUserManagerUserPeter, + getUserManagerUserSabine, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; +import { + createPostfachNachrichtAttachedItem, + createPostfachNachrichtReplyItem, + initVorgangAttachedItem, +} from '../../../support/vorgang-attached-item-util'; import { createVorgang, initVorgang, objectIds } from '../../../support/vorgang-util'; describe('Postfach nachricht user profile on backend error', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const postfachNachrichtenContainer: PostfachMailE2EComponent = vorgangPage.getPostfachMailcontainer(); - - const vorgang: VorgangE2E = createVorgang(); - - const postfachMailItem: PostfachMailItemE2E = { - ...createPostfachNachrichtReplyItem(), - createdBy: '6287e7507433b51bfc87cfe9', - direction: DirectionE2E.OUT, - sentAt: '2022-12-02T15:00:00.790Z[UTC]', - sentSuccessful: true - }; - const vorgangAttachedItem: VorgangAttachedItemE2E = { ...createPostfachNachrichtAttachedItem(objectIds[0], vorgang._id.$oid), item: postfachMailItem }; - - before(() => { - initVorgang(vorgang); - initVorgangAttachedItem([vorgangAttachedItem]); - initUsermanagerUsers([getUserManagerUserSabine(), getUserManagerUserPeter(), getUserManagerUserEmil()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('on status 404', () => { - - it('should navigate to vorgang detail', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - waitForSpinnerToDisappear(); - }) - - it('should show error not found icon', () => { - exist(postfachNachrichtenContainer.getListItem(postfachMailItem.subject).getUserProfile().getIconContainer().getErrorResourceNotFoundIcon()); - }) - - it('should hide user profile name', () => { - notExist(postfachNachrichtenContainer.getListItem(postfachMailItem.subject).getUserProfile().getName()); - }) - - it('should navigate back to list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - }) - - describe('on status 503', () => { - - const statusCode: number = 503; - const getUserProfileInterceptor: string = 'getUserProfileInterceptor'; - - beforeEach(() => { - interceptWithResponse(HttpMethodE2E.GET, '/api/userProfiles/*', { - statusCode, body: { issues: [{ messageCode: MessageCodeE2E.SERVICE_UNAVAILABLE }] } - }).as(getUserProfileInterceptor); - }) - - it('should manipulate response on vorgang detail navigation', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - - waitOfInterceptor(getUserProfileInterceptor).then(interception => { - assert(interception.response.statusCode, statusCode.toString()); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - waitForSpinnerToDisappear(); - }); - }) - - it('should show error service unavailable icon', () => { - exist(postfachNachrichtenContainer.getListItem(postfachMailItem.subject).getUserProfile().getIconContainer().getErrorServiceUnavailableIcon()); - }) - - it('should hide user profile name', () => { - notExist(postfachNachrichtenContainer.getListItem(postfachMailItem.subject).getUserProfile().getName()); - }) - - it('should navigate back', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - }) -}) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const postfachNachrichtenContainer: PostfachMailE2EComponent = + vorgangPage.getPostfachMailcontainer(); + + const vorgang: VorgangE2E = createVorgang(); + + const postfachMailItem: PostfachMailItemE2E = { + ...createPostfachNachrichtReplyItem(), + createdBy: '6287e7507433b51bfc87cfe9', + direction: DirectionE2E.OUT, + sentAt: '2022-12-02T15:00:00.790Z[UTC]', + sentSuccessful: true, + }; + const vorgangAttachedItem: VorgangAttachedItemE2E = { + ...createPostfachNachrichtAttachedItem(objectIds[0], vorgang._id.$oid), + item: postfachMailItem, + }; + + before(() => { + initVorgang(vorgang); + initVorgangAttachedItem([vorgangAttachedItem]); + initUsermanagerUsers([ + getUserManagerUserSabine(), + getUserManagerUserPeter(), + getUserManagerUserEmil(), + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('on status 404', () => { + it('should navigate to vorgang detail', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + waitForSpinnerToDisappear(); + }); + + it('should show error not found icon', () => { + exist( + postfachNachrichtenContainer + .getListItem(postfachMailItem.subject) + .getUserProfile() + .getIconContainer() + .getErrorResourceNotFoundIcon(), + ); + }); + + it('should hide user profile name', () => { + notExist( + postfachNachrichtenContainer + .getListItem(postfachMailItem.subject) + .getUserProfile() + .getName(), + ); + }); + + it('should navigate back to list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + }); + + describe('on status 503', () => { + const statusCode: number = 503; + const getUserProfileInterceptor: string = 'getUserProfileInterceptor'; + + beforeEach(() => { + interceptWithResponse(HttpMethodE2E.GET, '/api/userProfiles/*', { + statusCode, + body: { issues: [{ messageCode: MessageCodeE2E.SERVICE_UNAVAILABLE }] }, + }).as(getUserProfileInterceptor); + }); + + it('should manipulate response on vorgang detail navigation', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + + waitOfInterceptor(getUserProfileInterceptor).then((interception) => { + assert(interception.response.statusCode, statusCode.toString()); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + waitForSpinnerToDisappear(); + }); + }); + + it('should show error service unavailable icon', () => { + exist( + postfachNachrichtenContainer + .getListItem(postfachMailItem.subject) + .getUserProfile() + .getIconContainer() + .getErrorServiceUnavailableIcon(), + ); + }); + + it('should hide user profile name', () => { + notExist( + postfachNachrichtenContainer + .getListItem(postfachMailItem.subject) + .getUserProfile() + .getName(), + ); + }); + + it('should navigate back', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-vorgang-error.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-vorgang-error.cy.ts index 730efd510c6e2471922c80bd4e70b90388b4335b..f789a829fe7b7ce63f7a9787bac5d62f4e4ec969 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-vorgang-error.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-profile/user-profile-icon-in-vorgang-error.cy.ts @@ -29,127 +29,158 @@ import { VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { hasTooltip } from '../../../support/angular.util'; -import { dropCollections, interceptWithResponse, waitOfInterceptor } from '../../../support/cypress-helper'; +import { + dropCollections, + interceptWithResponse, + waitOfInterceptor, +} from '../../../support/cypress-helper'; import { exist } from '../../../support/cypress.util'; import { MessagesE2E } from '../../../support/messages'; -import { getUserManagerUserEmil, getUserManagerUserPeter, getUserManagerUserSabine, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; +import { + getUserManagerUserEmil, + getUserManagerUserPeter, + getUserManagerUserSabine, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; describe('User profile assigned to vorgang', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const userProfileContainer: UserProfileE2EComponent = vorgangPage.getVorgangDetailHeader().getUserContainer(); - - const vorgang: VorgangE2E = { ...createVorgang(), assignedTo: '6287e7507433b51bfc87cfe9' }; - - before(() => { - initVorgang(vorgang); - initUsermanagerUsers([getUserManagerUserSabine(), getUserManagerUserPeter(), getUserManagerUserEmil()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('on response status 404', () => { - - describe('in vorgang detail', () => { - - it('should navigate to vorgang detail', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should show icon', () => { - exist(userProfileContainer.getIconContainer().getErrorResourceNotFoundIcon()); - }) - - it('should have tooltip', () => { - hasTooltip(userProfileContainer.getIconContainer().getErrorResourceNotFoundIcon(), MessagesE2E.USER_PROFILE_RESOURCE_NOT_FOUND); - }) - - it('should navigate back', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - }) - - describe('in vorgang list', () => { - - const userProfile: UserProfileIconE2EComponent = vorgangList.getListItem(vorgang.name).getUserProfile().getIconContainer(); - - it('should show icon', () => { - exist(userProfile.getErrorResourceNotFoundIcon()); - }) - - it('should have tooltip', () => { - hasTooltip(userProfile.getErrorResourceNotFoundIcon(), MessagesE2E.USER_PROFILE_RESOURCE_NOT_FOUND); - }) - }) - }) - - describe('on response status 503', () => { - - const statusCode: number = 503; - const getUserProfileInterceptor: string = 'getUserProfileInterceptor'; - - beforeEach(() => { - interceptWithResponse(HttpMethodE2E.GET, '/api/userProfiles/*', { statusCode, body: { issues: [{ messageCode: MessageCodeE2E.SERVICE_UNAVAILABLE }] } }).as(getUserProfileInterceptor); - }) - - describe('in vorgang detail', () => { - - it('should manipulate response', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - - waitOfInterceptor(getUserProfileInterceptor).then((interception) => { - assert(interception.response.statusCode, statusCode.toString()); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - waitForSpinnerToDisappear(); - }); - }) - - it('should show icon', () => { - exist(userProfileContainer.getIconContainer().getErrorServiceUnavailableIcon()); - }) - - it('should have tooltip', () => { - hasTooltip(userProfileContainer.getIconContainer().getErrorServiceUnavailableIcon(), MessagesE2E.USER_PROFILE_SERVICE_UNAVAILABLE); - }) - }) - - describe('in vorgang list', () => { - - const userProfile: UserProfileIconE2EComponent = vorgangList.getListItem(vorgang.name).getUserProfile().getIconContainer(); - - it('should navigate to list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - - waitOfInterceptor(getUserProfileInterceptor).then((interception) => { - assert(interception.response.statusCode, statusCode.toString()); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }); - }) - - it('should show icon', () => { - exist(userProfile.getErrorServiceUnavailableIcon()); - }) - - it('should have tooltip', () => { - hasTooltip(userProfile.getErrorServiceUnavailableIcon(), MessagesE2E.USER_PROFILE_SERVICE_UNAVAILABLE); - }) - }) - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const userProfileContainer: UserProfileE2EComponent = vorgangPage + .getVorgangDetailHeader() + .getUserContainer(); + + const vorgang: VorgangE2E = { ...createVorgang(), assignedTo: '6287e7507433b51bfc87cfe9' }; + + before(() => { + initVorgang(vorgang); + initUsermanagerUsers([ + getUserManagerUserSabine(), + getUserManagerUserPeter(), + getUserManagerUserEmil(), + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('on response status 404', () => { + describe('in vorgang detail', () => { + it('should navigate to vorgang detail', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should show icon', () => { + exist(userProfileContainer.getIconContainer().getErrorResourceNotFoundIcon()); + }); + + it('should have tooltip', () => { + hasTooltip( + userProfileContainer.getIconContainer().getErrorResourceNotFoundIcon(), + MessagesE2E.USER_PROFILE_RESOURCE_NOT_FOUND, + ); + }); + + it('should navigate back', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + }); + + describe('in vorgang list', () => { + const userProfile: UserProfileIconE2EComponent = vorgangList + .getListItem(vorgang.name) + .getUserProfile() + .getIconContainer(); + + it('should show icon', () => { + exist(userProfile.getErrorResourceNotFoundIcon()); + }); + + it('should have tooltip', () => { + hasTooltip( + userProfile.getErrorResourceNotFoundIcon(), + MessagesE2E.USER_PROFILE_RESOURCE_NOT_FOUND, + ); + }); + }); + }); + + describe('on response status 503', () => { + const statusCode: number = 503; + const getUserProfileInterceptor: string = 'getUserProfileInterceptor'; + + beforeEach(() => { + interceptWithResponse(HttpMethodE2E.GET, '/api/userProfiles/*', { + statusCode, + body: { issues: [{ messageCode: MessageCodeE2E.SERVICE_UNAVAILABLE }] }, + }).as(getUserProfileInterceptor); + }); + + describe('in vorgang detail', () => { + it('should manipulate response', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + + waitOfInterceptor(getUserProfileInterceptor).then((interception) => { + assert(interception.response.statusCode, statusCode.toString()); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + waitForSpinnerToDisappear(); + }); + }); + + it('should show icon', () => { + exist(userProfileContainer.getIconContainer().getErrorServiceUnavailableIcon()); + }); + + it('should have tooltip', () => { + hasTooltip( + userProfileContainer.getIconContainer().getErrorServiceUnavailableIcon(), + MessagesE2E.USER_PROFILE_SERVICE_UNAVAILABLE, + ); + }); + }); + + describe('in vorgang list', () => { + const userProfile: UserProfileIconE2EComponent = vorgangList + .getListItem(vorgang.name) + .getUserProfile() + .getIconContainer(); + + it('should navigate to list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + + waitOfInterceptor(getUserProfileInterceptor).then((interception) => { + assert(interception.response.statusCode, statusCode.toString()); + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + }); + + it('should show icon', () => { + exist(userProfile.getErrorServiceUnavailableIcon()); + }); + + it('should have tooltip', () => { + hasTooltip( + userProfile.getErrorServiceUnavailableIcon(), + MessagesE2E.USER_PROFILE_SERVICE_UNAVAILABLE, + ); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-settings/user-settings.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-settings/user-settings.cy.ts index db92a54665aaea2a5821ac4704e0aabaffe14d9d..4af63bc725d7dedc3db1f954eabfde871e4af577 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-settings/user-settings.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/user-settings/user-settings.cy.ts @@ -29,75 +29,82 @@ import { MainPage, waitForSpinnerToDisappear } from 'apps/alfa-e2e/src/page-obje import { isChecked, isNotChecked } from 'apps/alfa-e2e/src/support/angular.util'; import { dropCollections, reload } from 'apps/alfa-e2e/src/support/cypress-helper'; import { exist } from 'apps/alfa-e2e/src/support/cypress.util'; -import { getUserManagerUserEmil, getUserManagerUserPeter, getUserManagerUserSabine, initUsermanagerUsers, loginAsSabine } from 'apps/alfa-e2e/src/support/user-util'; +import { + getUserManagerUserEmil, + getUserManagerUserPeter, + getUserManagerUserSabine, + initUsermanagerUsers, + loginAsSabine, +} from 'apps/alfa-e2e/src/support/user-util'; import { createVorgang, initVorgang } from 'apps/alfa-e2e/src/support/vorgang-util'; describe('User Settings', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const header: HeaderE2EComponent = mainPage.getHeader(); - const userSettings: UserSettingsE2EComponent = header.getUserSettings(); - const vorgang: VorgangE2E = createVorgang(); - - before(() => { - initVorgang(vorgang); - initUsermanagerUsers([getUserManagerUserSabine(), getUserManagerUserPeter(), getUserManagerUserEmil()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('click on settings icon', () => { - - before(() => { - userSettings.getRoot().click(); - }) - - it('should show notificationsSendsFor toggle', () => { - exist(userSettings.getEmailBenachrichtigung().getRoot()); - }) - - it('should show darkMode toggle', () => { - exist(userSettings.getDarkMode().getRoot()); - }) - }) - - describe('click on notificationSendsFor toggle', () => { - - it('should have initial unchecked toggle', () => { - isNotChecked(userSettings.getEmailBenachrichtigung().getToggle()); - }) - - it('should switch toggle status', () => { - userSettings.getEmailBenachrichtigung().getToggle().click(); - - isChecked(userSettings.getEmailBenachrichtigung().getToggle()); - }) - - it('should be loaded after page reload', () => { - reload(); - - userSettings.getRoot().click(); - isChecked(userSettings.getEmailBenachrichtigung().getToggle()); - }) - }) - - describe('click on darkMode toggle', () => { - - it('should have initial unchecked toggle', () => { - isNotChecked(userSettings.getDarkMode().getToggle()); - }) - - it('should switch toggle status', () => { - userSettings.getDarkMode().getToggle().click(); - - isChecked(userSettings.getDarkMode().getToggle()); - }) - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const header: HeaderE2EComponent = mainPage.getHeader(); + const userSettings: UserSettingsE2EComponent = header.getUserSettings(); + const vorgang: VorgangE2E = createVorgang(); + + before(() => { + initVorgang(vorgang); + initUsermanagerUsers([ + getUserManagerUserSabine(), + getUserManagerUserPeter(), + getUserManagerUserEmil(), + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('click on settings icon', () => { + before(() => { + userSettings.getRoot().click(); + }); + + it('should show notificationsSendsFor toggle', () => { + exist(userSettings.getEmailBenachrichtigung().getRoot()); + }); + + it('should show darkMode toggle', () => { + exist(userSettings.getDarkMode().getRoot()); + }); + }); + + describe('click on notificationSendsFor toggle', () => { + it('should have initial unchecked toggle', () => { + isNotChecked(userSettings.getEmailBenachrichtigung().getToggle()); + }); + + it('should switch toggle status', () => { + userSettings.getEmailBenachrichtigung().getToggle().click(); + + isChecked(userSettings.getEmailBenachrichtigung().getToggle()); + }); + + it('should be loaded after page reload', () => { + reload(); + + userSettings.getRoot().click(); + isChecked(userSettings.getEmailBenachrichtigung().getToggle()); + }); + }); + + describe('click on darkMode toggle', () => { + it('should have initial unchecked toggle', () => { + isNotChecked(userSettings.getDarkMode().getToggle()); + }); + + it('should switch toggle status', () => { + userSettings.getDarkMode().getToggle().click(); + + isChecked(userSettings.getDarkMode().getToggle()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/anhang-herunterladen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/anhang-herunterladen.cy.ts index 49b03dc4c3aec0ccae8f25a67c89353d63e97f5d..69dfac76104a5ea135bb876ffc97766877219999 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/anhang-herunterladen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-anhang/anhang-herunterladen.cy.ts @@ -31,137 +31,156 @@ import { FileDataE2E } from '../../../model/binary-file'; import { EingangE2E, VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; -import { createJpgAttachment, createJpgGridFsData, createPdfAttachment, createPdfGridFsData, createXmlGridFsData, createXmlRepresentation, initGridFs } from '../../../support/binary-file-util'; +import { + createJpgAttachment, + createJpgGridFsData, + createPdfAttachment, + createPdfGridFsData, + createXmlGridFsData, + createXmlRepresentation, + initGridFs, +} from '../../../support/binary-file-util'; import { dropCollections, readFileFromDownloads } from '../../../support/cypress-helper'; import { exist, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; describe('Vorgang Anhänge', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); + const attachmentContainer: AttachmentContainerE2EComponent = vorgangPage.getAttachmentContainer(); + const formularDatenContainer: VorgangFormularDatenE2EComponent = + vorgangPage.getFormularDatenContainer(); + + const xmlRepresentation: FileDataE2E = createXmlRepresentation(); + + const sonstigeAttachment = { + name: 'datei_sonstiges', + files: [createJpgAttachment(), createPdfAttachment()], + }; + const vorgangKeinAnhang: VorgangE2E = createVorgang(); + + const eingangWithAttachments: EingangE2E = { + ...createVorgang().eingangs[0], + numberOfRepresentations: 1, + representations: [xmlRepresentation], + numberOfAttachments: 2, + attachments: [sonstigeAttachment], + }; + const vorgangAnhangVorhanden: VorgangE2E = { + ...buildVorgang(objectIds[0], 'VorgangWithAnhang'), + eingangs: [eingangWithAttachments], + }; + + before(() => { + initGridFs([createXmlGridFsData(), createPdfGridFsData(), createJpgGridFsData()]); + initVorgaenge([vorgangKeinAnhang, vorgangAnhangVorhanden]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('Download Attachment', () => { + it('should open vorgang detail page on click on single vorgang', () => { + vorgangList.getListItem(vorgangAnhangVorhanden.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + }); + + it('should show attachment on click on tab', () => { + formularDatenContainer.getAttachmentTab().click(); + + notExist(vorgangPage.getSpinner()); + exist(attachmentContainer.getList().getRoot()); + }); + + it('should download jpg', () => { + const jpgAttachmentName: string = getJpgAttachment().name; + attachmentContainer.getList().getItem(jpgAttachmentName).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(readFileFromDownloads(buildDownloadFileName(jpgAttachmentName))); + }); + + it('should download pdf', () => { + const pdfAttachmentName: string = getPdfAttachment().name; + attachmentContainer + .getList() + .getItem(convertToDataTestId(pdfAttachmentName)) + .getRoot() + .click(); + waitForSpinnerToDisappear(); + + exist(readFileFromDownloads(buildDownloadFileName(pdfAttachmentName))); + }); + + it('should navigate to vorganglist on back button', () => { + subnavigation.getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + function getJpgAttachment(): FileDataE2E { + return sonstigeAttachment.files[1]; + } + + function getPdfAttachment(): FileDataE2E { + return sonstigeAttachment.files[0]; + } + }); + + describe('Download Representation', () => { + it('should open vorgang detail page on click on single vorgang', () => { + vorgangList.getListItem(vorgangAnhangVorhanden.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + }); + + it('should show attachment on click on tab', () => { + formularDatenContainer.getRepresentationTab().click(); + + notExist(vorgangPage.getSpinner()); + exist(attachmentContainer.getList().getRoot()); + }); + + it('should download representation', () => { + attachmentContainer.getList().getItem(xmlRepresentation.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(readFileFromDownloads(buildDownloadFileName(xmlRepresentation.name))); + }); + + it('should navigate to vorganglist on back button', () => { + subnavigation.getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + }); + + function buildDownloadFileName(fileName: string): string { + return `${getFileNamePrefix()}_${fileName}`; + } - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); - const subnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); - const attachmentContainer: AttachmentContainerE2EComponent = vorgangPage.getAttachmentContainer(); - const formularDatenContainer: VorgangFormularDatenE2EComponent = vorgangPage.getFormularDatenContainer(); - - const xmlRepresentation: FileDataE2E = createXmlRepresentation(); - - const sonstigeAttachment = { - name: 'datei_sonstiges', - files: [createJpgAttachment(), createPdfAttachment()] - } - const vorgangKeinAnhang: VorgangE2E = createVorgang(); - - const eingangWithAttachments: EingangE2E = { - ...createVorgang().eingangs[0], - numberOfRepresentations: 1, - representations: [xmlRepresentation], - numberOfAttachments: 2, - attachments: [sonstigeAttachment] - }; - const vorgangAnhangVorhanden: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangWithAnhang'), eingangs: [eingangWithAttachments] }; - - before(() => { - initGridFs([createXmlGridFsData(), createPdfGridFsData(), createJpgGridFsData()]); - initVorgaenge([vorgangKeinAnhang, vorgangAnhangVorhanden]); - - loginAsSabine(); - - waitForSpinnerToDisappear() - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('Download Attachment', () => { - - it('should open vorgang detail page on click on single vorgang', () => { - vorgangList.getListItem(vorgangAnhangVorhanden.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - }) - - it('should show attachment on click on tab', () => { - formularDatenContainer.getAttachmentTab().click(); - - notExist(vorgangPage.getSpinner()); - exist(attachmentContainer.getList().getRoot()); - }) - - it('should download jpg', () => { - const jpgAttachmentName: string = getJpgAttachment().name; - attachmentContainer.getList().getItem(jpgAttachmentName).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(buildDownloadFileName(jpgAttachmentName))); - }) - - it('should download pdf', () => { - const pdfAttachmentName: string = getPdfAttachment().name; - attachmentContainer.getList().getItem(convertToDataTestId(pdfAttachmentName)).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(buildDownloadFileName(pdfAttachmentName))); - }) - - it('should navigate to vorganglist on back button', () => { - subnavigation.getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - function getJpgAttachment(): FileDataE2E { - return sonstigeAttachment.files[1]; - } - - function getPdfAttachment(): FileDataE2E { - return sonstigeAttachment.files[0]; - } - }) - - describe('Download Representation', () => { - - it('should open vorgang detail page on click on single vorgang', () => { - vorgangList.getListItem(vorgangAnhangVorhanden.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - }) - - it('should show attachment on click on tab', () => { - formularDatenContainer.getRepresentationTab().click(); - - notExist(vorgangPage.getSpinner()); - exist(attachmentContainer.getList().getRoot()); - }) - - it('should download representation', () => { - attachmentContainer.getList().getItem(xmlRepresentation.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(buildDownloadFileName(xmlRepresentation.name))); - }) - - it('should navigate to vorganglist on back button', () => { - subnavigation.getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - }) - - function buildDownloadFileName(fileName: string): string{ - return `${getFileNamePrefix()}_${fileName}`; - } - - function getFileNamePrefix(): string { - return vorgangAnhangVorhanden.nummer; - } -}) \ No newline at end of file + function getFileNamePrefix(): string { + return vorgangAnhangVorhanden.nummer; + } +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts index 48251bf8b0182560c8376f7a1e8ac24da8fe64cf..7c24cf66f97dd2c37b98288fbe9bc481c5172aa9 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-abschliessen.cy.ts @@ -24,7 +24,12 @@ import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; @@ -33,121 +38,142 @@ import { loginAsSabine } from '../../../support/user-util'; import { buildVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; describe('Vorgang abschliessen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangAbschliessen: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoAbschliessen'), status: VorgangStatusE2E.BESCHIEDEN }; - const vorgangAbschliessenRevoke: VorgangE2E = { ...buildVorgang(objectIds[1], 'DoRevokeAbschliessen'), status: VorgangStatusE2E.BESCHIEDEN }; - - before(() => { - initVorgaenge([vorgangAbschliessen, vorgangAbschliessenRevoke]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('abschliessen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbschliessen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Beschieden', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbschliessen.status]); - }) - - it('should show snackBar message', () => { - vorgangFormularButtons.getAbschliessenButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN) - }) - - it('should close snackBar', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Abgeschlossen', () => { - haveText(vorgangList.getListItem(vorgangAbschliessen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - }) - }) - - describe('abschliessen und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbschliessenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Beschieden', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbschliessenRevoke.status]); - }) - - it('should show snackBar message', () => { - vorgangPage.getSubnavigation().getAbschliessenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Beschieden', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Beschieden', () => { - haveText(vorgangList.getListItem(vorgangAbschliessenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]) - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangAbschliessen: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoAbschliessen'), + status: VorgangStatusE2E.BESCHIEDEN, + }; + const vorgangAbschliessenRevoke: VorgangE2E = { + ...buildVorgang(objectIds[1], 'DoRevokeAbschliessen'), + status: VorgangStatusE2E.BESCHIEDEN, + }; + + before(() => { + initVorgaenge([vorgangAbschliessen, vorgangAbschliessenRevoke]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('abschliessen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbschliessen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Beschieden', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbschliessen.status], + ); + }); + + it('should show snackBar message', () => { + vorgangFormularButtons.getAbschliessenButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN); + }); + + it('should close snackBar', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Abgeschlossen', () => { + haveText( + vorgangList.getListItem(vorgangAbschliessen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + }); + }); + + describe('abschliessen und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbschliessenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Beschieden', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbschliessenRevoke.status], + ); + }); + + it('should show snackBar message', () => { + vorgangPage.getSubnavigation().getAbschliessenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ABGESCHLOSSEN); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Beschieden', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Beschieden', () => { + haveText( + vorgangList.getListItem(vorgangAbschliessenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-aktenzeichen-anlegen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-aktenzeichen-anlegen.cy.ts new file mode 100644 index 0000000000000000000000000000000000000000..aab04257a3a20171d6c4b99085521c89013f6ac1 --- /dev/null +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-aktenzeichen-anlegen.cy.ts @@ -0,0 +1,331 @@ +import { registerLocaleData } from '@angular/common'; +import localeDe from '@angular/common/locales/de'; +import localeDeExtra from '@angular/common/locales/extra/de'; +import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; +import { VorgangListItemE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-item.e2e.component'; +import { VorgangE2E, VorgangStatusE2E } from 'apps/alfa-e2e/src/model/vorgang'; +import 'cypress-real-events/support'; +import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; +import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; +import { VorgangPage } from '../../../page-objects/vorgang.po'; +import { dropCollections } from '../../../support/cypress-helper'; +import { contains, enterWith, exist, notExist } from '../../../support/cypress.util'; +import { + initUsermanagerUsers, + getUserManagerUserSabine, + getUserSabine, + loginAsSabine, +} from '../../../support/user-util'; +import { + buildVorgang, + initSearchIndex, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; +import { VorgangDetailHeaderE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-detail-header.e2e.component'; +import { VorgangAktenzeichenEditE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-aktenzeichen-edit.e2e.component'; +import { HeaderE2EComponent } from 'apps/alfa-e2e/src/page-objects/header.po'; +import { VorgangSearchE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component'; +import { + AktenzeichenHistorieItemE2EComponent, + VorgangFormularDatenHistorieItemE2EComponent, +} from 'apps/alfa-e2e/src/components/vorgang/vorgang.formular-daten.historie.e2e.component'; +import { VorgangFormularDatenE2EComponent } from '../../../components/vorgang/vorgang-formular.e2e.component'; +import { HistorieHeadlineE2E } from 'apps/alfa-e2e/src/model/historie'; + +registerLocaleData(localeDe, 'de', localeDeExtra); + +describe('Aktenzeichen anlegen', () => { + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const defaultAZ: string = 'default_AZ'; + const noAZ: string = 'kein Aktenzeichen'; + const newAZ: string = 'xyzäöüß!'; + const AZWithBlanks: string = ' aa bb cc '; + const trimmedAZ: string = 'aa bb cc'; + const longAZ: string = + 'iiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllll_iiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllll_iiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllll_iiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllll_iiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllll_iiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllll_iiiiiiiiiijjjjjjjjjjkkkkkkkkkkllllllllll_'; + const searchAZ: string = 'AZ Suche'; + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + const aktenzeichenEditor: VorgangAktenzeichenEditE2EComponent = + vorgangPage.getAktenzeichenEditor(); + const header: HeaderE2EComponent = mainPage.getHeader(); + const vorgangSearch: VorgangSearchE2EComponent = header.getVorgangSearch(); + + const aktenzeichenVorgang: VorgangE2E = { + ...buildVorgang(objectIds[0], 'Aktenzeichen Vorgang'), + status: VorgangStatusE2E.NEU, + }; + const aktenzeichenVorgangEdit: VorgangE2E = { + ...buildVorgang(objectIds[1], 'Aktenzeichen Vorgang Edit'), + status: VorgangStatusE2E.ANGENOMMEN, + aktenzeichen: defaultAZ, + }; + const aktenzeichenVorgangMissing: VorgangE2E = { + ...buildVorgang(objectIds[2], 'Missing Aktenzeichen Vorgang'), + status: VorgangStatusE2E.ANGENOMMEN, + aktenzeichen: '', + }; + const aktenzeichenVorgangHistory: VorgangE2E = { + ...buildVorgang(objectIds[3], 'Aktenzeichen Vorgang Historie'), + status: VorgangStatusE2E.ANGENOMMEN, + aktenzeichen: '', + }; + const aktenzeichenVorgangSearch: VorgangE2E = { + ...buildVorgang(objectIds[4], 'Aktenzeichen Vorgang Suche'), + status: VorgangStatusE2E.ANGENOMMEN, + aktenzeichen: searchAZ, + }; + + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + const vorgangDatenFormular: VorgangFormularDatenE2EComponent = + vorgangPage.getFormularDatenContainer(); + + const vorgangShowInSearch: VorgangListItemE2EComponent = vorgangList.getListItem( + aktenzeichenVorgangSearch.name, + ); + + before(() => { + initVorgaenge([ + aktenzeichenVorgang, + aktenzeichenVorgangEdit, + aktenzeichenVorgangMissing, + aktenzeichenVorgangHistory, + aktenzeichenVorgangSearch, + ]); + initSearchIndex([aktenzeichenVorgangSearch]); + initUsermanagerUsers([getUserManagerUserSabine()]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + function setNewAktenzeichen(aktenzeichen: string): void { + aktenzeichenEditor.getTextEditor().clear().type(aktenzeichen); + aktenzeichenEditor.getConfirmButton().click(); + } + + describe('check display of edit icon by Vorgang status', () => { + it('should not show icon on status Neu', () => { + vorgangList.getListItem(aktenzeichenVorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + notExist(vorgangHeader.getAktenzeichenEdit()); + }); + + it('should display icon on status Angenommen', () => { + vorgangFormularButtons.getAnnehmenButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getAktenzeichenEdit()); + }); + + it('should show icon on status In Bearbeitung', () => { + vorgangFormularButtons.getBearbeitenButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getAktenzeichenEdit()); + }); + + it('should not show icon on all following status', () => { + vorgangFormularButtons.getBescheidenButton().click(); + waitForSpinnerToDisappear(); + + notExist(vorgangHeader.getAktenzeichenEdit()); + + vorgangFormularButtons.getAbschliessenButton().click(); + waitForSpinnerToDisappear(); + + notExist(vorgangHeader.getAktenzeichenEdit()); + + vorgangFormularButtons.getLoeschenAnfordernButton().click(); + waitForSpinnerToDisappear(); + + notExist(vorgangHeader.getAktenzeichenEdit()); + + vorgangPage.getSubnavigation().getBackButton().click(); + }); + }); + + describe('check functionality of Aktenzeichen editing mask', () => { + it('should display editing mask on clicking edit icon', () => { + vorgangList.getListItem(aktenzeichenVorgangEdit.name).getRoot().click(); + waitForSpinnerToDisappear(); + + vorgangHeader.getAktenzeichenEditButton().click(); + + exist(aktenzeichenEditor.getTextEditor()); + }); + + it('should paste contents of clipboard', () => { + const clipboardText: string = 'clipboard'; + cy.window().its('navigator.clipboard').invoke('writeText', clipboardText); + aktenzeichenEditor.getClipboardButton().click(); + + aktenzeichenEditor.getTextEditor().invoke('val').should('equal', clipboardText); + }); + + it('should NOT use new content on cancel', () => { + aktenzeichenEditor.getCancelButton().click(); + + contains(vorgangHeader.getAktenzeichen(), defaultAZ); + }); + + it('should NOT use only blank spaces as Aktenzeichen', () => { + vorgangHeader.getAktenzeichenEditButton().click(); + setNewAktenzeichen(' '); + + contains(vorgangHeader.getAktenzeichen(), noAZ); + }); + + it('should adopt new valid Aktenzeichen on clicking confirm', () => { + vorgangHeader.getAktenzeichenEditButton().click(); + setNewAktenzeichen(newAZ); + + contains(vorgangHeader.getAktenzeichen(), newAZ); + }); + + it('should pre-set existing Aktenzeichen on opening mask', () => { + vorgangHeader.getAktenzeichenEditButton().click(); + + aktenzeichenEditor.getTextEditor().invoke('val').should('equal', newAZ); + }); + + it('should trim blank spaces at start and end of Aktenzeichen', () => { + setNewAktenzeichen(AZWithBlanks); + + contains(vorgangHeader.getAktenzeichen(), trimmedAZ); + }); + + it('should keep edit window open on confirm if Aktenzeichen is too long', () => { + vorgangHeader.getAktenzeichenEditButton().click(); + cy.window().its('navigator.clipboard').invoke('writeText', longAZ); + aktenzeichenEditor.getClipboardButton().click(); + aktenzeichenEditor.getConfirmButton().click(); + + exist(aktenzeichenEditor.getTextEditor()); + + aktenzeichenEditor.getCancelButton().click(); + }); + + it('should display placeholder text when Aktenzeichen is missing', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + vorgangList.getListItem(aktenzeichenVorgangMissing.name).getRoot().click(); + waitForSpinnerToDisappear(); + vorgangHeader.getAktenzeichenEditButton().click(); + + aktenzeichenEditor.getTextEditor().invoke('val').should('equal', ''); + }); + + it('should not show X button on empty Aktenzeichen', () => { + notExist(aktenzeichenEditor.getClearButton()); + }); + + it('should remove Aktenzeichen on clicking X button', () => { + aktenzeichenEditor.getTextEditor().clear().type(newAZ); + aktenzeichenEditor.getClearButton().click(); + + aktenzeichenEditor.getTextEditor().invoke('val').should('equal', ''); + + aktenzeichenEditor.getCancelButton().click(); + vorgangPage.getSubnavigation().getBackButton().click(); + }); + }); + + describe('check Aktenzeichen entries in Historie', () => { + const userName: string = `${getUserSabine().firstName} ${getUserSabine().lastName}`; + + it('should display history entry on setting new Aktenzeichen', () => { + vorgangList.getListItem(aktenzeichenVorgangHistory.name).getRoot().click(); + vorgangHeader.getAktenzeichenEditButton().click(); + aktenzeichenEditor.getTextEditor().clear().type(defaultAZ); + aktenzeichenEditor.getConfirmButton().click(); + vorgangDatenFormular.getHistorieTab().click(); + + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(0); + + exist(historieItem.getRoot()); + contains(historieItem.getHeadline(), HistorieHeadlineE2E.AKTENZEICHEN_GEAENDERT); + contains(historieItem.getUser(), userName); + exist(historieItem.getExpandButton()); + + historieItem.getExpandButton().click(); + }); + + it('should show new Aktenzeichen on opening dropdown', () => { + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(0); + const aktenzeichenItem: AktenzeichenHistorieItemE2EComponent = historieItem.getAktenzeichen(); + const azText: string = 'Aktenzeichen: ' + defaultAZ; + + contains(aktenzeichenItem.getText(), azText); + }); + + it('should show history entry after changing existing Aktenzeichen', () => { + vorgangHeader.getAktenzeichenEditButton().click(); + setNewAktenzeichen(newAZ); + vorgangDatenFormular.getAntragdatenTab().click(); + vorgangDatenFormular.getHistorieTab().click(); + + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(1); + const aktenzeichenItem: AktenzeichenHistorieItemE2EComponent = historieItem.getAktenzeichen(); + const azText: string = 'Aktenzeichen: ' + newAZ; + + historieItem.getExpandButton().click(); + + contains(aktenzeichenItem.getText(), azText); + }); + + it('should show history entry after deletion of Aktenzeichen', () => { + vorgangHeader.getAktenzeichenEditButton().click(); + aktenzeichenEditor.getTextEditor().clear(); + aktenzeichenEditor.getConfirmButton().click(); + vorgangDatenFormular.getAntragdatenTab().click(); + vorgangDatenFormular.getHistorieTab().click(); + + const historieItem: VorgangFormularDatenHistorieItemE2EComponent = vorgangDatenFormular + .getHistorieContainer() + .getListItemByIndex(2); + + contains(historieItem.getHeadline(), HistorieHeadlineE2E.AKTENZEICHEN_GELOESCHT); + + vorgangPage.getSubnavigation().getBackButton().click(); + }); + }); + + describe('search for Aktenzeichen', () => { + it('should find Vorgang with existing Aktenzeichen', () => { + vorgangList.getListItem(aktenzeichenVorgangSearch.name).getRoot().click(); + enterWith(vorgangSearch.getInput(), searchAZ); + //currently the first search only works if you manually send an Enter after a short delay + cy.wait(1000); + vorgangSearch.getInput().type('{enter}'); + + exist(vorgangShowInSearch.getRoot()); + }); + + it('should not find the same Vorgang after changing its Aktenzeichen', () => { + vorgangList.getListItem(aktenzeichenVorgangSearch.name).getRoot().click(); + vorgangHeader.getAktenzeichenEditButton().click(); + setNewAktenzeichen(newAZ); + enterWith(vorgangSearch.getInput(), searchAZ); + + notExist(vorgangShowInSearch.getRoot()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-annehmen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-annehmen.cy.ts index 68d6e27b4fc409aa1c0cb099c89757b3642212a7..00e6eda6a5a4032d88cdcd993afe5deb62f182eb 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-annehmen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-annehmen.cy.ts @@ -27,131 +27,156 @@ import localeDeExtra from '@angular/common/locales/extra/de'; import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Annehmen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangAnnehmen: VorgangE2E = { ...createVorgang(), name: 'DoAnnehmen' }; - const vorgangAnnehmenRevoke: VorgangE2E = buildVorgang(objectIds[0], 'DoRevokeAnnehmen'); - - before(() => { - initVorgaenge([vorgangAnnehmen, vorgangAnnehmenRevoke]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('annehmen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAnnehmen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Neu', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAnnehmen.status]); - }) - - it('should show snackBar message', () => { - vorgangFormularButtons.getAnnehmenButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ANGENOMMEN); - }) - - it('should close snackBar on close', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status Angenommen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Angenommen', () => { - haveText(vorgangList.getListItem(vorgangAnnehmen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]); - }) - }) - }) - - describe('annehmen und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAnnehmenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Neu', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAnnehmenRevoke.status]); - }) - - it('should show snackBar message', () => { - vorgangPage.getSubnavigation().getAnnehmenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ANGENOMMEN); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Neu', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Neu', () => { - haveText(vorgangList.getListItem(vorgangAnnehmenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]); - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangAnnehmen: VorgangE2E = { ...createVorgang(), name: 'DoAnnehmen' }; + const vorgangAnnehmenRevoke: VorgangE2E = buildVorgang(objectIds[0], 'DoRevokeAnnehmen'); + + before(() => { + initVorgaenge([vorgangAnnehmen, vorgangAnnehmenRevoke]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('annehmen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAnnehmen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Neu', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAnnehmen.status], + ); + }); + + it('should show snackBar message', () => { + vorgangFormularButtons.getAnnehmenButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ANGENOMMEN); + }); + + it('should close snackBar on close', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status Angenommen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Angenommen', () => { + haveText( + vorgangList.getListItem(vorgangAnnehmen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN], + ); + }); + }); + }); + + describe('annehmen und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAnnehmenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Neu', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAnnehmenRevoke.status], + ); + }); + + it('should show snackBar message', () => { + vorgangPage.getSubnavigation().getAnnehmenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ANGENOMMEN); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Neu', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.NEU], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Neu', () => { + haveText( + vorgangList.getListItem(vorgangAnnehmenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.NEU], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bearbeiten.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bearbeiten.cy.ts index 29a81633a918e4dc6c0b6a837684ccb4641818fb..c2bfc37f122500947544da460197c77a28ed4368 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bearbeiten.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bearbeiten.cy.ts @@ -24,130 +24,162 @@ import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; describe('Vorgang bearbeiten', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangBearbeiten: VorgangE2E = { ...createVorgang(), status: VorgangStatusE2E.ANGENOMMEN, name: 'DoBearbeiten' }; - const vorgangBearbeitenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeBearbeiten'), status: VorgangStatusE2E.ANGENOMMEN }; - - before(() => { - initVorgaenge([vorgangBearbeiten, vorgangBearbeitenRevoke]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('bearbeiten', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangBearbeiten.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Angenommen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangBearbeiten.status]); - }) - - it('should show snackBar', () => { - vorgangFormularButtons.getBearbeitenButton().click(); - waitForSpinnerToDisappear(); - - contains(snackBar.getMessage(), VorgangMessagesE2E.BEARBEITET); - exist(snackBar.getCloseButton()); - }) - - it('should close snackBar on close button', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status In Bearbeitung', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status In Bearbeitung', () => { - haveText(vorgangList.getListItem(vorgangBearbeiten.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]) - }) - }) - }) - - describe('bearbeiten und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangBearbeitenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Angenommen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangBearbeitenRevoke.status]); - }) - - it('should show snackBar', () => { - vorgangPage.getSubnavigation().getBearbeitenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.BEARBEITET); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Angenommen', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Angenommen', () => { - haveText(vorgangList.getListItem(vorgangBearbeitenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]) - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangBearbeiten: VorgangE2E = { + ...createVorgang(), + status: VorgangStatusE2E.ANGENOMMEN, + name: 'DoBearbeiten', + }; + const vorgangBearbeitenRevoke: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoRevokeBearbeiten'), + status: VorgangStatusE2E.ANGENOMMEN, + }; + + before(() => { + initVorgaenge([vorgangBearbeiten, vorgangBearbeitenRevoke]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('bearbeiten', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangBearbeiten.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Angenommen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangBearbeiten.status], + ); + }); + + it('should show snackBar', () => { + vorgangFormularButtons.getBearbeitenButton().click(); + waitForSpinnerToDisappear(); + + contains(snackBar.getMessage(), VorgangMessagesE2E.BEARBEITET); + exist(snackBar.getCloseButton()); + }); + + it('should close snackBar on close button', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status In Bearbeitung', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status In Bearbeitung', () => { + haveText( + vorgangList.getListItem(vorgangBearbeiten.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + }); + }); + + describe('bearbeiten und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangBearbeitenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Angenommen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangBearbeitenRevoke.status], + ); + }); + + it('should show snackBar', () => { + vorgangPage.getSubnavigation().getBearbeitenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.BEARBEITET); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Angenommen', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Angenommen', () => { + haveText( + vorgangList.getListItem(vorgangBearbeitenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bescheiden.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bescheiden.cy.ts index b4934a61f865d1a08fcf6fe5270ce99b3a4df3d0..9f96aa6b939d3fb8236b68697df8d48012151fd5 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bescheiden.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-bescheiden.cy.ts @@ -24,138 +24,170 @@ import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; describe('Vorgang bescheiden', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangBescheiden: VorgangE2E = { ...createVorgang(), name: 'DoBescheiden', status: VorgangStatusE2E.IN_BEARBEITUNG }; - const vorgangBescheidenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeBescheiden'), status: VorgangStatusE2E.IN_BEARBEITUNG }; - - before(() => { - initVorgaenge([vorgangBescheiden, vorgangBescheidenRevoke]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('bescheiden', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangBescheiden.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status In Bearbeitung', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangBescheiden.status]); - }) - - it('should show snackBar message', () => { - vorgangFormularButtons.getBescheidenButton().click(); - waitForSpinnerToDisappear(); - - contains(snackBar.getMessage(), VorgangMessagesE2E.BESCHIEDEN); - }) - - it('should show snackBar close button', () => { - exist(snackBar.getCloseButton()); - }) - - it('should close snackBar', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status Beschieden', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status In Bearbeitung', () => { - waitForSpinnerToDisappear(); - - haveText(vorgangList.getListItem(vorgangBescheiden.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]); - }) - }) - }) - - describe('bescheiden und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangBescheidenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status In Bearbeitung', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangBescheidenRevoke.status]); - }) - - it('should show snackBar message', () => { - vorgangPage.getSubnavigation().getBescheidenIconButton().click(); - waitForSpinnerToDisappear(); - - contains(snackBar.getMessage(), VorgangMessagesE2E.BESCHIEDEN); - }) - - it('should show snackBar close button', () => { - exist(snackBar.getCloseButton()); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Angenommen', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status In Bearbeitung', () => { - haveText(vorgangList.getListItem(vorgangBescheidenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangBescheiden: VorgangE2E = { + ...createVorgang(), + name: 'DoBescheiden', + status: VorgangStatusE2E.IN_BEARBEITUNG, + }; + const vorgangBescheidenRevoke: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoRevokeBescheiden'), + status: VorgangStatusE2E.IN_BEARBEITUNG, + }; + + before(() => { + initVorgaenge([vorgangBescheiden, vorgangBescheidenRevoke]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('bescheiden', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangBescheiden.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status In Bearbeitung', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangBescheiden.status], + ); + }); + + it('should show snackBar message', () => { + vorgangFormularButtons.getBescheidenButton().click(); + waitForSpinnerToDisappear(); + + contains(snackBar.getMessage(), VorgangMessagesE2E.BESCHIEDEN); + }); + + it('should show snackBar close button', () => { + exist(snackBar.getCloseButton()); + }); + + it('should close snackBar', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status Beschieden', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status In Bearbeitung', () => { + waitForSpinnerToDisappear(); + + haveText( + vorgangList.getListItem(vorgangBescheiden.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN], + ); + }); + }); + }); + + describe('bescheiden und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangBescheidenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status In Bearbeitung', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangBescheidenRevoke.status], + ); + }); + + it('should show snackBar message', () => { + vorgangPage.getSubnavigation().getBescheidenIconButton().click(); + waitForSpinnerToDisappear(); + + contains(snackBar.getMessage(), VorgangMessagesE2E.BESCHIEDEN); + }); + + it('should show snackBar close button', () => { + exist(snackBar.getCloseButton()); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Angenommen', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status In Bearbeitung', () => { + haveText( + vorgangList.getListItem(vorgangBescheidenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-by-role.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-by-role.cy.ts index 8c004c5d6ef46f38349f24af6eddb415a74df4c7..557ae27ecf94738b02e29b7206494c5fccdbc3bd 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-by-role.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-by-role.cy.ts @@ -33,7 +33,11 @@ import { AntragstellerE2EComponent } from '../../../components/vorgang/vorgang-a import { VorgangDetailHeaderE2EComponent } from '../../../components/vorgang/vorgang-detail-header.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { VorgangE2E } from '../../../model/vorgang'; -import { MainPage, waitForSpinnerToDisappear, waitforSpinnerToAppear } from '../../../page-objects/main.po'; +import { + MainPage, + waitForSpinnerToDisappear, + waitforSpinnerToAppear, +} from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { exist, notExist } from '../../../support/cypress.util'; @@ -43,239 +47,209 @@ import { createVorgang, initVorgang } from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Detailansicht by role', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); - const formularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const antragsteller: AntragstellerE2EComponent = vorgangPage.getAntragstellerContainer(); - const wiedervorlagenContainer: WiedervorlagenInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer(); - const vorgangSubnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); - const postfachMailContainer: PostfachMailE2EComponent = vorgangPage.getPostfachMailcontainer(); - const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); - - const vorgang: VorgangE2E = createVorgang(); - - describe('for user with role ' + UserRoleE2E.VERWALTUNG_USER, () => { - - before(() => { - initVorgang(vorgang); - - loginAsSabine(); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('click on vorgang in list', () => { - - it('should show vorgang header', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - }) - }) - - describe('Subnavigation actions buttons', () => { - - describe('for vorgang status', () => { - - describe('annehmen', () => { - - it('should be visible', () => { - exist(vorgangSubnavigation.getAnnehmenIconButton()); - }) - }) - - describe('verwerfen', () => { - - it('should be visible', () => { - exist(vorgangSubnavigation.getVerwerfenIconButton()); - }) - }) - }) - - describe('for postfach nachricht', () => { - - it('should be visible', () => { - exist(vorgangSubnavigation.getPostfachMailIconButton()); - }) - }) - - describe('for create wiedervorlage', () => { - - it('should be visible', () => { - exist(vorgangSubnavigation.getCreateWiedervorlageIconButton()); - }) - }) - }) - - describe('Antragsteller area', () => { - - it('should be visible', () => { - exist(antragsteller.getRoot()); - }) - }) - - describe('Formular button', () => { - - describe('annehmen', () => { - - it('should be visible', () => { - exist(formularButtons.getAnnehmenButton()); - }) - }) - - describe('verwerfen', () => { - - it('should be visible', () => { - exist(formularButtons.getVerwerfenButton()); - }) - }) - }) - - describe('Wiedervorlagen area', () => { - - it('should be visible', () => { - exist(wiedervorlagenContainer.getRoot()); - }) - }) - - describe('PostfachNachricht', () => { - - it('should be visible', () => { - exist(postfachMailContainer.getRoot()); - }) - }) - - describe('Kommentar area', () => { - - it('should be visible', () => { - exist(kommentarContainer.getRoot()); - }) - }) - }) - - describe('for user with role ' + UserRoleE2E.VERWALTUNG_POSTSTELLE, () => { - - before(() => { - initVorgang(vorgang); - - loginAsPeter(); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('click on vorgang in list', () => { - - it('should show vorgang header', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - }) - }) - - describe('Subnavigation actions buttons', () => { - - describe('for vorgang status', () => { - - describe('annehmen', () => { - - it('should NOT be visible', () => { - notExist(vorgangSubnavigation.getAnnehmenIconButton()); - }) - }) - - describe('verwerfen', () => { - - it('should NOT be visible', () => { - notExist(vorgangSubnavigation.getVerwerfenIconButton()); - }) - }) - }) - - describe('for postfach nachricht', () => { - - it('should be visible', () => { - exist(vorgangSubnavigation.getPostfachMailIconButton()); - }) - }) - - describe('for create wiedervorlage', () => { - - it('should NOT be visible', () => { - notExist(vorgangSubnavigation.getCreateWiedervorlageIconButton()); - }) - }) - - describe('for assign user', () => { - - it('should be visible', () => { - exist(vorgangSubnavigation.getAssignUserProfileIconButton()); - }) - }) - }) - - describe('Antragsteller area', () => { - - it('should be visible', () => { - exist(antragsteller.getRoot()); - }) - }) - - describe('Formular button', () => { - - describe('annehmen', () => { - - it('should NOT be visible', () => { - notExist(formularButtons.getAnnehmenButton()); - }) - }) - - describe('verwerfen', () => { - - it('should NOT be visible', () => { - notExist(formularButtons.getVerwerfenButton()); - }) - }) - }) - - describe('Wiedervorlagen area', () => { - - it('should NOT be visible', () => { - notExist(wiedervorlagenContainer.getRoot()); - }) - }) - - describe('PostfachNachricht', () => { - - it('should be visible', () => { - exist(postfachMailContainer.getRoot()); - }) - }) - - describe('Kommentar area', () => { - - it('should be visible', () => { - exist(kommentarContainer.getRoot()); - }) - }) - }) -}); \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + const formularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); + + const antragsteller: AntragstellerE2EComponent = vorgangPage.getAntragstellerContainer(); + const wiedervorlagenContainer: WiedervorlagenInVorgangE2EComponent = + vorgangPage.getWiedervorlagenContainer(); + const vorgangSubnavigation: VorgangSubnavigationE2EComponent = vorgangPage.getSubnavigation(); + const postfachMailContainer: PostfachMailE2EComponent = vorgangPage.getPostfachMailcontainer(); + const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); + + const vorgang: VorgangE2E = createVorgang(); + + describe('for user with role ' + UserRoleE2E.VERWALTUNG_USER, () => { + before(() => { + initVorgang(vorgang); + + loginAsSabine(); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('click on vorgang in list', () => { + it('should show vorgang header', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + }); + }); + + describe('Subnavigation actions buttons', () => { + describe('for vorgang status', () => { + describe('annehmen', () => { + it('should be visible', () => { + exist(vorgangSubnavigation.getAnnehmenIconButton()); + }); + }); + + describe('verwerfen', () => { + it('should be visible', () => { + exist(vorgangSubnavigation.getVerwerfenIconButton()); + }); + }); + }); + + describe('for postfach nachricht', () => { + it('should be visible', () => { + exist(vorgangSubnavigation.getPostfachMailIconButton()); + }); + }); + + describe('for create wiedervorlage', () => { + it('should be visible', () => { + exist(vorgangSubnavigation.getCreateWiedervorlageIconButton()); + }); + }); + }); + + describe('Antragsteller area', () => { + it('should be visible', () => { + exist(antragsteller.getRoot()); + }); + }); + + describe('Formular button', () => { + describe('annehmen', () => { + it('should be visible', () => { + exist(formularButtons.getAnnehmenButton()); + }); + }); + + describe('verwerfen', () => { + it('should be visible', () => { + exist(formularButtons.getVerwerfenButton()); + }); + }); + }); + + describe('Wiedervorlagen area', () => { + it('should be visible', () => { + exist(wiedervorlagenContainer.getRoot()); + }); + }); + + describe('PostfachNachricht', () => { + it('should be visible', () => { + exist(postfachMailContainer.getRoot()); + }); + }); + + describe('Kommentar area', () => { + it('should be visible', () => { + exist(kommentarContainer.getRoot()); + }); + }); + }); + + describe('for user with role ' + UserRoleE2E.VERWALTUNG_POSTSTELLE, () => { + before(() => { + initVorgang(vorgang); + + loginAsPeter(); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('click on vorgang in list', () => { + it('should show vorgang header', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + }); + }); + + describe('Subnavigation actions buttons', () => { + describe('for vorgang status', () => { + describe('annehmen', () => { + it('should NOT be visible', () => { + notExist(vorgangSubnavigation.getAnnehmenIconButton()); + }); + }); + + describe('verwerfen', () => { + it('should NOT be visible', () => { + notExist(vorgangSubnavigation.getVerwerfenIconButton()); + }); + }); + }); + + describe('for postfach nachricht', () => { + it('should be visible', () => { + exist(vorgangSubnavigation.getPostfachMailIconButton()); + }); + }); + + describe('for create wiedervorlage', () => { + it('should NOT be visible', () => { + notExist(vorgangSubnavigation.getCreateWiedervorlageIconButton()); + }); + }); + + describe('for assign user', () => { + it('should be visible', () => { + exist(vorgangSubnavigation.getAssignUserProfileIconButton()); + }); + }); + }); + + describe('Antragsteller area', () => { + it('should be visible', () => { + exist(antragsteller.getRoot()); + }); + }); + + describe('Formular button', () => { + describe('annehmen', () => { + it('should NOT be visible', () => { + notExist(formularButtons.getAnnehmenButton()); + }); + }); + + describe('verwerfen', () => { + it('should NOT be visible', () => { + notExist(formularButtons.getVerwerfenButton()); + }); + }); + }); + + describe('Wiedervorlagen area', () => { + it('should NOT be visible', () => { + notExist(wiedervorlagenContainer.getRoot()); + }); + }); + + describe('PostfachNachricht', () => { + it('should be visible', () => { + exist(postfachMailContainer.getRoot()); + }); + }); + + describe('Kommentar area', () => { + it('should be visible', () => { + exist(kommentarContainer.getRoot()); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-formdata.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-formdata.cy.ts index a08bf4884204bc076c2c24057614e0f263e7bed1..f89eece987188c4fe3ac2ab6bec9362a9ec371ab 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-formdata.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht-formdata.cy.ts @@ -33,183 +33,180 @@ import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main. import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Detailansicht with formData', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangDatenFormular: VorgangFormularDatenE2EComponent = vorgangPage.getFormularDatenContainer(); - - const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); - - const ort: string = 'Ort'; - const sh_strasse: string = 'Strasse'; - const sh_hausnummer: string = 'Hausnummer'; - const emailadresse: string = 'E-Mail Adresse'; - const postleitzahl: string = 'PLZ'; - - const vorgang: VorgangE2E = { ...createVorgang(), name: 'TestVorgang' }; - const vorgangWithLabels: VorgangE2E = createVorgangWithLabels(); - - before(() => { - initVorgaenge([vorgang, vorgangWithLabels]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - function createVorgangWithLabels(): VorgangE2E{ - const vorgang = buildVorgang(objectIds[0], 'TestVorgangWithLabels'); - return { - ...vorgang, - eingangs: [{ - ...vorgang.eingangs[0], - formData: createFormDataWithLabels() - }] - } - } - - function createFormDataWithLabels(): FormData { - return { - ...vorgang.eingangs[0].formData, - _kopControlData: { - metaData: true, - labels: { ort, sh_strasse, sh_hausnummer } - }, - empfangendestelle: createEmpfangendestelleWithLabels() - } - } - - function createEmpfangendestelleWithLabels(): any { - return { - ...vorgang.eingangs[0].formData.empfangendestelle, - _kopControlData: { - labels: { - emailadresse, - postleitzahl - } - } - } - } - - after(() => { - dropCollections(); - }) - - describe('navigate to vorgang detail (without labels)', () => { - - describe('click on vorgang in list', () => { - - it('should show header', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - }) - }) - - describe('click on "Antragsdaten" tab', () => { - - it('should show on click on tab', () => { - vorgangDatenFormular.getAntragdatenTab().click(); - - exist(vorgangDatenFormular.getAntragdaten()); - }) - - it('should show "sh_hausnummer"', () => { - contains(vorgangDatenFormular.getRoot(), 'sh_hausnummer'); - }) - - it('should show "sh_strasse"', () => { - contains(vorgangDatenFormular.getRoot(), 'sh_strasse'); - }) - - }) - - // SKIP: Metadaten sind aktuell aus - describe('click on "Metadaten" tab', () => { - - it.skip('should show on click on tab', () => { - vorgangDatenFormular.getMetadatenTab().click(); - - exist(vorgangDatenFormular.getMetadaten()); - }) - - it.skip('should show "emailadresse"', () => { - contains(vorgangDatenFormular.getRoot(), 'emailadresse'); - }) - - it.skip('should show "postleitzahl"', () => { - contains(vorgangDatenFormular.getRoot(), 'postleitzahl'); - }) - - it('should navigate back to Vorgang List', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - }) - }) - }) - - describe('navigate to vorgang detail (with labels)', () => { - - describe('click on vorgang in list', () => { - - it('should show header', () => { - vorgangList.getListItem(vorgangWithLabels.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - }) - }) - - describe('click on "Antragsdaten" tab', () => { - - it('should show on click on tab', () => { - vorgangDatenFormular.getAntragdatenTab().click(); - - exist(vorgangDatenFormular.getAntragdaten()); - }) - - it('should not show "_kopControlData', () => { - notContains(vorgangDatenFormular.getRoot(), '_kopControlData'); - }) - - it('should show "Hausnummer"', () => { - contains(vorgangDatenFormular.getRoot(), sh_hausnummer); - }) - - it('should show "Strasse"', () => { - contains(vorgangDatenFormular.getRoot(), sh_strasse); - }) - - it('should show "Ort"', () => { - contains(vorgangDatenFormular.getRoot(), ort); - }) - - }) - - describe.skip('click on "Metadaten" tab', () => { - - it('should show on click on tab', () => { - vorgangDatenFormular.getMetadatenTab().click(); - - exist(vorgangDatenFormular.getMetadaten()); - }) - - it('should show "E-Mail Adresse"', () => { - contains(vorgangDatenFormular.getRoot(), emailadresse); - }) - - it('should show "PLZ"', () => { - contains(vorgangDatenFormular.getRoot(), postleitzahl); - }) - - }) - }) -}); \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangDatenFormular: VorgangFormularDatenE2EComponent = + vorgangPage.getFormularDatenContainer(); + + const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + + const ort: string = 'Ort'; + const sh_strasse: string = 'Strasse'; + const sh_hausnummer: string = 'Hausnummer'; + const emailadresse: string = 'E-Mail Adresse'; + const postleitzahl: string = 'PLZ'; + + const vorgang: VorgangE2E = { ...createVorgang(), name: 'TestVorgang' }; + const vorgangWithLabels: VorgangE2E = createVorgangWithLabels(); + + before(() => { + initVorgaenge([vorgang, vorgangWithLabels]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + function createVorgangWithLabels(): VorgangE2E { + const vorgang = buildVorgang(objectIds[0], 'TestVorgangWithLabels'); + return { + ...vorgang, + eingangs: [ + { + ...vorgang.eingangs[0], + formData: createFormDataWithLabels(), + }, + ], + }; + } + + function createFormDataWithLabels(): FormData { + return { + ...vorgang.eingangs[0].formData, + _kopControlData: { + metaData: true, + labels: { ort, sh_strasse, sh_hausnummer }, + }, + empfangendestelle: createEmpfangendestelleWithLabels(), + }; + } + + function createEmpfangendestelleWithLabels(): any { + return { + ...vorgang.eingangs[0].formData.empfangendestelle, + _kopControlData: { + labels: { + emailadresse, + postleitzahl, + }, + }, + }; + } + + after(() => { + dropCollections(); + }); + + describe('navigate to vorgang detail (without labels)', () => { + describe('click on vorgang in list', () => { + it('should show header', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + }); + }); + + describe('click on "Antragsdaten" tab', () => { + it('should show on click on tab', () => { + vorgangDatenFormular.getAntragdatenTab().click(); + + exist(vorgangDatenFormular.getAntragdaten()); + }); + + it('should show "sh_hausnummer"', () => { + contains(vorgangDatenFormular.getRoot(), 'sh_hausnummer'); + }); + + it('should show "sh_strasse"', () => { + contains(vorgangDatenFormular.getRoot(), 'sh_strasse'); + }); + }); + + // SKIP: Metadaten sind aktuell aus + describe('click on "Metadaten" tab', () => { + it.skip('should show on click on tab', () => { + vorgangDatenFormular.getMetadatenTab().click(); + + exist(vorgangDatenFormular.getMetadaten()); + }); + + it.skip('should show "emailadresse"', () => { + contains(vorgangDatenFormular.getRoot(), 'emailadresse'); + }); + + it.skip('should show "postleitzahl"', () => { + contains(vorgangDatenFormular.getRoot(), 'postleitzahl'); + }); + + it('should navigate back to Vorgang List', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + }); + }); + }); + + describe('navigate to vorgang detail (with labels)', () => { + describe('click on vorgang in list', () => { + it('should show header', () => { + vorgangList.getListItem(vorgangWithLabels.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + }); + }); + + describe('click on "Antragsdaten" tab', () => { + it('should show on click on tab', () => { + vorgangDatenFormular.getAntragdatenTab().click(); + + exist(vorgangDatenFormular.getAntragdaten()); + }); + + it('should not show "_kopControlData', () => { + notContains(vorgangDatenFormular.getRoot(), '_kopControlData'); + }); + + it('should show "Hausnummer"', () => { + contains(vorgangDatenFormular.getRoot(), sh_hausnummer); + }); + + it('should show "Strasse"', () => { + contains(vorgangDatenFormular.getRoot(), sh_strasse); + }); + + it('should show "Ort"', () => { + contains(vorgangDatenFormular.getRoot(), ort); + }); + }); + + describe.skip('click on "Metadaten" tab', () => { + it('should show on click on tab', () => { + vorgangDatenFormular.getMetadatenTab().click(); + + exist(vorgangDatenFormular.getMetadaten()); + }); + + it('should show "E-Mail Adresse"', () => { + contains(vorgangDatenFormular.getRoot(), emailadresse); + }); + + it('should show "PLZ"', () => { + contains(vorgangDatenFormular.getRoot(), postleitzahl); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.authorize-by-role.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.authorize-by-role.cy.ts index 2fd4051fdb7479cfcf651a2a856e7f12cbb292c8..798edc157930b0637c36e66e32171f010055770c 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.authorize-by-role.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.authorize-by-role.cy.ts @@ -24,95 +24,121 @@ import { SnackBarE2EComponent } from 'apps/alfa-e2e/src/components/ui/snackbar.e2e.component'; import { VorgangDetailHeaderE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-detail-header.e2e.component'; import { VorgangE2E, VorgangStatusE2E } from 'apps/alfa-e2e/src/model/vorgang'; -import { MainPage, waitForSpinnerToDisappear, waitforSpinnerToAppear } from 'apps/alfa-e2e/src/page-objects/main.po'; +import { + MainPage, + waitForSpinnerToDisappear, + waitforSpinnerToAppear, +} from 'apps/alfa-e2e/src/page-objects/main.po'; import { contains, exist, notExist } from 'apps/alfa-e2e/src/support/cypress.util'; import { MessagesE2E } from 'apps/alfa-e2e/src/support/messages'; import { UserRoleE2E, loginAsPeter } from 'apps/alfa-e2e/src/support/user-util'; -import { buildVorgang, createVorgangUriById, initVorgaenge } from 'apps/alfa-e2e/src/support/vorgang-util'; +import { + buildVorgang, + createVorgangUriById, + initVorgaenge, +} from 'apps/alfa-e2e/src/support/vorgang-util'; import { dropCollections, visitUrl } from '../../../support/cypress-helper'; describe('Vorgang Detailansicht should be authorized by role', () => { - - const mainPage: MainPage = new MainPage(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangHeader: VorgangDetailHeaderE2EComponent = new VorgangDetailHeaderE2EComponent(); - - describe(`for user Peter with role ${UserRoleE2E.VERWALTUNG_POSTSTELLE}`, () => { - - const vorgangInStatusNeuId: string = '601bc78eabc134051570aab8'; - const vorgangInStatusNeuUrl: string = createVorgangUriById(vorgangInStatusNeuId); - const vorgangInStatusNeu: VorgangE2E = { ...buildVorgang(vorgangInStatusNeuId, 'VorgangInStatusNeu'), status: VorgangStatusE2E.NEU }; - - const vorgangInStatusInBearbeitungId = '60250b9d383c182943f6ba79'; - const vorgangInStatusInBearbeitungUrl: string = createVorgangUriById(vorgangInStatusInBearbeitungId); - const vorgangInStatusInBearbeitung: VorgangE2E = { ...buildVorgang(vorgangInStatusInBearbeitungId, 'vorgangInStatusInBearbeitung'), status: VorgangStatusE2E.IN_BEARBEITUNG }; - - const vorgangInStatusAbgeschlossenId: string = '602566a807bb665df9a86e87'; - const vorgangInStatusAbgeschlossenUrl: string = createVorgangUriById(vorgangInStatusAbgeschlossenId); - const vorgangInStatusAbgeschlossen: VorgangE2E = { ...buildVorgang(vorgangInStatusAbgeschlossenId, 'vorgangInStatusAbgeschlossen'), status: VorgangStatusE2E.ABGESCHLOSSEN }; - - const vorgangInStatusBeschiedenId: string = '602566a207bb665df9a86e86'; - const vorgangInStatusBeschiedenUrl: string = createVorgangUriById(vorgangInStatusBeschiedenId); - const vorgangInStatusBeschieden: VorgangE2E = { ...buildVorgang(vorgangInStatusBeschiedenId, 'vorgangInStatusBeschieden'), status: VorgangStatusE2E.BESCHIEDEN }; - - before(() => { - initVorgaenge([vorgangInStatusNeu, vorgangInStatusInBearbeitung, vorgangInStatusAbgeschlossen, vorgangInStatusBeschieden]); - - loginAsPeter(); - }) - - after(() => { - dropCollections(); - }) - - it('should show vorgangList after login', () => { - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - exist(mainPage.getVorgangList().getRoot()); - }) - - it(`should show vorgang in Stauts ${VorgangStatusE2E.NEU}`, () => { - visitUrl(vorgangInStatusNeuUrl); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - }) - - describe('should hide vorgang in status', () => { - - it(`${VorgangStatusE2E.IN_BEARBEITUNG}`, () => { - visitUrl(vorgangInStatusInBearbeitungUrl); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - notExist(vorgangHeader.getRoot()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - - it(`${VorgangStatusE2E.ABGESCHLOSSEN}`, () => { - visitUrl(vorgangInStatusAbgeschlossenUrl); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - notExist(vorgangHeader.getRoot()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - - it(`${VorgangStatusE2E.BESCHIEDEN}`, () => { - visitUrl(vorgangInStatusBeschiedenUrl); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - notExist(vorgangHeader.getRoot()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - }) - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangHeader: VorgangDetailHeaderE2EComponent = new VorgangDetailHeaderE2EComponent(); + + describe(`for user Peter with role ${UserRoleE2E.VERWALTUNG_POSTSTELLE}`, () => { + const vorgangInStatusNeuId: string = '601bc78eabc134051570aab8'; + const vorgangInStatusNeuUrl: string = createVorgangUriById(vorgangInStatusNeuId); + const vorgangInStatusNeu: VorgangE2E = { + ...buildVorgang(vorgangInStatusNeuId, 'VorgangInStatusNeu'), + status: VorgangStatusE2E.NEU, + }; + + const vorgangInStatusInBearbeitungId = '60250b9d383c182943f6ba79'; + const vorgangInStatusInBearbeitungUrl: string = createVorgangUriById( + vorgangInStatusInBearbeitungId, + ); + const vorgangInStatusInBearbeitung: VorgangE2E = { + ...buildVorgang(vorgangInStatusInBearbeitungId, 'vorgangInStatusInBearbeitung'), + status: VorgangStatusE2E.IN_BEARBEITUNG, + }; + + const vorgangInStatusAbgeschlossenId: string = '602566a807bb665df9a86e87'; + const vorgangInStatusAbgeschlossenUrl: string = createVorgangUriById( + vorgangInStatusAbgeschlossenId, + ); + const vorgangInStatusAbgeschlossen: VorgangE2E = { + ...buildVorgang(vorgangInStatusAbgeschlossenId, 'vorgangInStatusAbgeschlossen'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + + const vorgangInStatusBeschiedenId: string = '602566a207bb665df9a86e86'; + const vorgangInStatusBeschiedenUrl: string = createVorgangUriById(vorgangInStatusBeschiedenId); + const vorgangInStatusBeschieden: VorgangE2E = { + ...buildVorgang(vorgangInStatusBeschiedenId, 'vorgangInStatusBeschieden'), + status: VorgangStatusE2E.BESCHIEDEN, + }; + + before(() => { + initVorgaenge([ + vorgangInStatusNeu, + vorgangInStatusInBearbeitung, + vorgangInStatusAbgeschlossen, + vorgangInStatusBeschieden, + ]); + + loginAsPeter(); + }); + + after(() => { + dropCollections(); + }); + + it('should show vorgangList after login', () => { + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + exist(mainPage.getVorgangList().getRoot()); + }); + + it(`should show vorgang in Stauts ${VorgangStatusE2E.NEU}`, () => { + visitUrl(vorgangInStatusNeuUrl); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + }); + + describe('should hide vorgang in status', () => { + it(`${VorgangStatusE2E.IN_BEARBEITUNG}`, () => { + visitUrl(vorgangInStatusInBearbeitungUrl); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + notExist(vorgangHeader.getRoot()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + + it(`${VorgangStatusE2E.ABGESCHLOSSEN}`, () => { + visitUrl(vorgangInStatusAbgeschlossenUrl); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + notExist(vorgangHeader.getRoot()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + + it(`${VorgangStatusE2E.BESCHIEDEN}`, () => { + visitUrl(vorgangInStatusBeschiedenUrl); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + notExist(vorgangHeader.getRoot()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.cy.ts index 79981f16fff506a270cbd3d75966eb206654e7b3..314e090a98b6e3042e7fff02a3e72d1df5828664 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.cy.ts @@ -33,188 +33,220 @@ import { NO_AKTENZEICHEN, VorgangE2E, vorgangStatusLabelE2E } from '../../../mod import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections, reload } from '../../../support/cypress-helper'; -import { contains, exist, haveText, shouldFirstContains, shouldHaveAttributeBeGreaterThan, shouldHaveAttributeBeLowerThan } from '../../../support/cypress.util'; +import { + contains, + exist, + haveText, + shouldFirstContains, + shouldHaveAttributeBeGreaterThan, + shouldHaveAttributeBeLowerThan, +} from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { AntragstellerE2ETestData, buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + AntragstellerE2ETestData, + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Detailansicht', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangDatenFormular: VorgangFormularDatenE2EComponent = vorgangPage.getFormularDatenContainer(); - - const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); - const expansionPanelContainer: ExpansionPanelE2Eomponent = vorgangPage.getFormularDatenContainer().getExpansionPanelContainer(); - const antragsteller: AntragstellerE2EComponent = vorgangPage.getAntragstellerContainer(); - - const vorgang: VorgangE2E = { ...createVorgang(), name: 'TestVorgang' }; - const vorgangTwo: VorgangE2E = buildVorgang(objectIds[0], 'TestVorgangWithAntragstellerNull'); - const vorgangWithAntragstellerNull: VorgangE2E = { - ...vorgangTwo, - eingangs: [{ ...vorgangTwo.eingangs[0], antragsteller: null }] - }; - - before(() => { - initVorgaenge([vorgang, vorgangWithAntragstellerNull]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('navigate to vorgang detail', () => { - - describe('click on vorgang in list', () => { - - it('should show header', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - }) - - it('should have header data', () => { - haveText(vorgangHeader.getStatus(), vorgangStatusLabelE2E[vorgang.status]); - haveText(vorgangHeader.getAktenzeichen(), vorgang.aktenzeichen ? vorgang.aktenzeichen : NO_AKTENZEICHEN); - haveText(vorgangHeader.getVorgangNummer(), vorgang.nummer); - haveText(vorgangHeader.getName(), vorgang.name); - haveText(vorgangHeader.getCreatedAt(), formatDate(vorgang.createdAt.$date, 'EEEE, dd. MMMM y, HH:mm', 'de')); - }) - - it('should have header data after reload', () => { - reload(); - - exist(vorgangHeader.getRoot()); - haveText(vorgangHeader.getStatus(), vorgangStatusLabelE2E[vorgang.status]); - haveText(vorgangHeader.getAktenzeichen(), vorgang.aktenzeichen ? vorgang.aktenzeichen : NO_AKTENZEICHEN); - haveText(vorgangHeader.getVorgangNummer(), vorgang.nummer); - haveText(vorgangHeader.getName(), vorgang.name); - haveText(vorgangHeader.getCreatedAt(), formatDate(vorgang.createdAt.$date, 'EEEE, dd. MMMM y, HH:mm', 'de')); - }) - }) - - // SKIP: Metada sind aktuell disabled - describe.skip('metadaten in tab', () => { - - it('should show on click on tab', () => { - vorgangDatenFormular.getMetadatenTab().click(); - - exist(vorgangDatenFormular.getMetadaten()); - }) - - it('should show "empfangendestelle"', () => { - contains(vorgangDatenFormular.getRoot(), vorgang.eingangs[0].formData.empfangendestelle.emailadresse); - }) - }) - - describe('antragdaten in tab', () => { - - it('should show on click on tab', () => { - vorgangDatenFormular.getAntragdatenTab().click(); - - exist(vorgangDatenFormular.getAntragdaten()); - }) - - it('should show "bez flurstueck"', () => { - contains(vorgangDatenFormular.getRoot(), vorgang.eingangs[0].formData.bezFlurstuek[0]); - contains(vorgangDatenFormular.getRoot(), vorgang.eingangs[0].formData.bezFlurstuek[1]); - }) - }) - - describe('historie in tab', () => { - - it('should show on click on tab', () => { - vorgangDatenFormular.getHistorieTab().click(); - - exist(vorgangDatenFormular.getHistorieContainer().getRoot()); - }) - - it('should show vorgang created at', () => { - exist(vorgangDatenFormular.getHistorieContainer().getCreatedAt()); - }) - }) - - describe('expansion panel', () => { - - it('should contains Formulardaten panel', () => { - shouldFirstContains(expansionPanelContainer.getExpansionPanelTitle(), 'Formulardaten'); - }) - - it('should have Formulardaten panel open initial', () => { - shouldHaveAttributeBeGreaterThan(expansionPanelContainer.getExpansionPanel(), 'outerHeight', 50); - }) - - it('should close the panel', () => { - expansionPanelContainer.getExpansionPanelTitle().first().click(); - - shouldHaveAttributeBeLowerThan(expansionPanelContainer.getExpansionPanel(), 'outerHeight', 50); - }) - }) - }) - - describe('Antragsdaten', () => { - - it('should contains Antragsteller area', () => { - exist(antragsteller.getRoot()); - }) - - it('should contains name', () => { - exist(antragsteller.getName()); - contains(antragsteller.getName(), AntragstellerE2ETestData.anrede); - contains(antragsteller.getName(), AntragstellerE2ETestData.vorname); - contains(antragsteller.getName(), AntragstellerE2ETestData.nachname); - }) - - it('should contains email', () => { - exist(antragsteller.getEmail()); - contains(antragsteller.getEmail(), AntragstellerE2ETestData.email); - }) - - it('should contains telefon', () => { - exist(antragsteller.getTelefon()); - contains(antragsteller.getTelefon(), AntragstellerE2ETestData.telefon); - }) - - it('should contains adresse', () => { - exist(antragsteller.getStrasseHausnummer()); - contains(antragsteller.getStrasseHausnummer(), AntragstellerE2ETestData.strasse); - contains(antragsteller.getStrasseHausnummer(), AntragstellerE2ETestData.hausnummer); - - exist(antragsteller.getPlzOrt()); - contains(antragsteller.getPlzOrt(), AntragstellerE2ETestData.plz); - contains(antragsteller.getPlzOrt(), AntragstellerE2ETestData.ort); - }) - - it('should contains birth data', () => { - exist(antragsteller.getBirthData()); - contains(antragsteller.getBirthData(), AntragstellerE2ETestData.geburtsort); - }) - - it('should show vorgang header', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - }) - }) - - describe('Antragsdaten null', () => { - it('should show vorgang header', () => { - vorgangList.getListItem(vorgangWithAntragstellerNull.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - }) - - it('should show noAntragsteller', () => { - exist(antragsteller.getNoAntragsteller()); - contains(antragsteller.getNoAntragsteller(), 'Nicht vorhanden.'); - }) - }) -}); \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangDatenFormular: VorgangFormularDatenE2EComponent = + vorgangPage.getFormularDatenContainer(); + + const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + const expansionPanelContainer: ExpansionPanelE2Eomponent = vorgangPage + .getFormularDatenContainer() + .getExpansionPanelContainer(); + const antragsteller: AntragstellerE2EComponent = vorgangPage.getAntragstellerContainer(); + + const vorgang: VorgangE2E = { ...createVorgang(), name: 'TestVorgang' }; + const vorgangTwo: VorgangE2E = buildVorgang(objectIds[0], 'TestVorgangWithAntragstellerNull'); + const vorgangWithAntragstellerNull: VorgangE2E = { + ...vorgangTwo, + eingangs: [{ ...vorgangTwo.eingangs[0], antragsteller: null }], + }; + + before(() => { + initVorgaenge([vorgang, vorgangWithAntragstellerNull]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('navigate to vorgang detail', () => { + describe('click on vorgang in list', () => { + it('should show header', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + }); + + it('should have header data', () => { + haveText(vorgangHeader.getStatus(), vorgangStatusLabelE2E[vorgang.status]); + haveText( + vorgangHeader.getAktenzeichen(), + vorgang.aktenzeichen ? vorgang.aktenzeichen : NO_AKTENZEICHEN, + ); + haveText(vorgangHeader.getVorgangNummer(), vorgang.nummer); + haveText(vorgangHeader.getName(), vorgang.name); + haveText( + vorgangHeader.getCreatedAt(), + formatDate(vorgang.createdAt.$date, 'EEEE, dd. MMMM y, HH:mm', 'de'), + ); + }); + + it('should have header data after reload', () => { + reload(); + + exist(vorgangHeader.getRoot()); + haveText(vorgangHeader.getStatus(), vorgangStatusLabelE2E[vorgang.status]); + haveText( + vorgangHeader.getAktenzeichen(), + vorgang.aktenzeichen ? vorgang.aktenzeichen : NO_AKTENZEICHEN, + ); + haveText(vorgangHeader.getVorgangNummer(), vorgang.nummer); + haveText(vorgangHeader.getName(), vorgang.name); + haveText( + vorgangHeader.getCreatedAt(), + formatDate(vorgang.createdAt.$date, 'EEEE, dd. MMMM y, HH:mm', 'de'), + ); + }); + }); + + // SKIP: Metada sind aktuell disabled + describe.skip('metadaten in tab', () => { + it('should show on click on tab', () => { + vorgangDatenFormular.getMetadatenTab().click(); + + exist(vorgangDatenFormular.getMetadaten()); + }); + + it('should show "empfangendestelle"', () => { + contains( + vorgangDatenFormular.getRoot(), + vorgang.eingangs[0].formData.empfangendestelle.emailadresse, + ); + }); + }); + + describe('antragdaten in tab', () => { + it('should show on click on tab', () => { + vorgangDatenFormular.getAntragdatenTab().click(); + + exist(vorgangDatenFormular.getAntragdaten()); + }); + + it('should show "bez flurstueck"', () => { + contains(vorgangDatenFormular.getRoot(), vorgang.eingangs[0].formData.bezFlurstuek[0]); + contains(vorgangDatenFormular.getRoot(), vorgang.eingangs[0].formData.bezFlurstuek[1]); + }); + }); + + describe('historie in tab', () => { + it('should show on click on tab', () => { + vorgangDatenFormular.getHistorieTab().click(); + + exist(vorgangDatenFormular.getHistorieContainer().getRoot()); + }); + + it('should show vorgang created at', () => { + exist(vorgangDatenFormular.getHistorieContainer().getCreatedAt()); + }); + }); + + describe('expansion panel', () => { + it('should contains Formulardaten panel', () => { + shouldFirstContains(expansionPanelContainer.getExpansionPanelTitle(), 'Formulardaten'); + }); + + it('should have Formulardaten panel open initial', () => { + shouldHaveAttributeBeGreaterThan( + expansionPanelContainer.getExpansionPanel(), + 'outerHeight', + 50, + ); + }); + + it('should close the panel', () => { + expansionPanelContainer.getExpansionPanelTitle().first().click(); + + shouldHaveAttributeBeLowerThan( + expansionPanelContainer.getExpansionPanel(), + 'outerHeight', + 50, + ); + }); + }); + }); + + describe('Antragsdaten', () => { + it('should contains Antragsteller area', () => { + exist(antragsteller.getRoot()); + }); + + it('should contains name', () => { + exist(antragsteller.getName()); + contains(antragsteller.getName(), AntragstellerE2ETestData.anrede); + contains(antragsteller.getName(), AntragstellerE2ETestData.vorname); + contains(antragsteller.getName(), AntragstellerE2ETestData.nachname); + }); + + it('should contains email', () => { + exist(antragsteller.getEmail()); + contains(antragsteller.getEmail(), AntragstellerE2ETestData.email); + }); + + it('should contains telefon', () => { + exist(antragsteller.getTelefon()); + contains(antragsteller.getTelefon(), AntragstellerE2ETestData.telefon); + }); + + it('should contains adresse', () => { + exist(antragsteller.getStrasseHausnummer()); + contains(antragsteller.getStrasseHausnummer(), AntragstellerE2ETestData.strasse); + contains(antragsteller.getStrasseHausnummer(), AntragstellerE2ETestData.hausnummer); + + exist(antragsteller.getPlzOrt()); + contains(antragsteller.getPlzOrt(), AntragstellerE2ETestData.plz); + contains(antragsteller.getPlzOrt(), AntragstellerE2ETestData.ort); + }); + + it('should contains birth data', () => { + exist(antragsteller.getBirthData()); + contains(antragsteller.getBirthData(), AntragstellerE2ETestData.geburtsort); + }); + + it('should show vorgang header', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + }); + }); + + describe('Antragsdaten null', () => { + it('should show vorgang header', () => { + vorgangList.getListItem(vorgangWithAntragstellerNull.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + }); + + it('should show noAntragsteller', () => { + exist(antragsteller.getNoAntragsteller()); + contains(antragsteller.getNoAntragsteller(), 'Nicht vorhanden.'); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.cy.ts index a92cb1664127afe5f80fb417cc6965e51d866c28..81e46b08d7ed612e8d33b114581951e1ddd3b7d6 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.cy.ts @@ -25,167 +25,190 @@ import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.compon import { VorgangDetailHeaderE2EComponent } from '../../../components/vorgang/vorgang-detail-header.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { EingangE2E, VorgangE2E } from '../../../model/vorgang'; -import { MainPage, waitForSpinnerToDisappear, waitforSpinnerToAppear } from '../../../page-objects/main.po'; +import { + MainPage, + waitForSpinnerToDisappear, + waitforSpinnerToAppear, +} from '../../../page-objects/main.po'; import { dropCollections, visitUrl } from '../../../support/cypress-helper'; import { contains, exist, notExist } from '../../../support/cypress.util'; -import { ORGANISATIONSEINHEITEN_ID_FOR_KFINDER, ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } from '../../../support/data.util'; +import { + ORGANISATIONSEINHEITEN_ID_FOR_KFINDER, + ORGANISATIONSEINHEITEN_ID_FOR_KORDNER, +} from '../../../support/data.util'; import { MessagesE2E } from '../../../support/messages'; import { loginAsKfinder, loginAsKordner, loginAsZonk } from '../../../support/user-util'; -import { buildVorgang, createVorgang, createVorgangUriById, initVorgaenge } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + createVorgangUriById, + initVorgaenge, +} from '../../../support/vorgang-util'; const defaultCommandTimeout: number = 30000; describe('Vorgang-detailansicht filtered by organisationseinheit', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const detailPage: VorgangDetailHeaderE2EComponent = new VorgangDetailHeaderE2EComponent(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const detailPage: VorgangDetailHeaderE2EComponent = new VorgangDetailHeaderE2EComponent(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangIdForKFinder: string = '601bc78eabc134051570aab8'; + const vorgangUrlVisibleToKFinder: string = createVorgangUriById(vorgangIdForKFinder); + + const eingangForKFinder: EingangE2E = { + ...createVorgang().eingangs[0], + zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KFINDER }, + }; + const vorgangForKFinder: VorgangE2E = { + ...buildVorgang(vorgangIdForKFinder, 'VorgangVisibleToKFinder'), + eingangs: [eingangForKFinder], + }; + + const vorgangIdForKOrdner: string = '60250b9d383c182943f6ba79'; + const vorgangUrlVisibleToKOrdner: string = createVorgangUriById(vorgangIdForKOrdner); + + const eingangForKOrdner: EingangE2E = { + ...createVorgang().eingangs[0], + zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KORDNER }, + }; + const vorgangForKOrdner: VorgangE2E = { + ...buildVorgang(vorgangIdForKOrdner, 'VorgangVisibleToKOrdner'), + eingangs: [eingangForKOrdner], + }; + + before(() => { + initVorgaenge([vorgangForKFinder, vorgangForKOrdner]); + }); + + after(() => { + dropCollections(); + }); + + describe('on user kfinder', () => { + const authorizedUrl: string = vorgangUrlVisibleToKFinder; + const forbiddenUrl: string = vorgangUrlVisibleToKOrdner; + + before(() => { + loginAsKfinder(); + }); + + it('should show vorgangList after login', () => { + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - const vorgangIdForKFinder: string = '601bc78eabc134051570aab8'; - const vorgangUrlVisibleToKFinder: string = createVorgangUriById(vorgangIdForKFinder); + it('should open detailpage', { defaultCommandTimeout }, () => { + visitUrl(authorizedUrl); - const eingangForKFinder: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KFINDER } }; - const vorgangForKFinder: VorgangE2E = { ...buildVorgang(vorgangIdForKFinder, 'VorgangVisibleToKFinder'), eingangs: [eingangForKFinder] }; + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); - const vorgangIdForKOrdner: string = '60250b9d383c182943f6ba79'; - const vorgangUrlVisibleToKOrdner: string = createVorgangUriById(vorgangIdForKOrdner); + exist(detailPage.getRoot()); + }); + + it('should not open detailpage', { defaultCommandTimeout }, () => { + visitUrl(forbiddenUrl); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + notExist(detailPage.getRoot()); + }); + + it('should show snackbar', () => { + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + }); + + describe('on user kordner', () => { + const authorizedUrl: string = vorgangUrlVisibleToKOrdner; + const forbiddenUrl: string = vorgangUrlVisibleToKFinder; + + before(() => { + loginAsKordner(); + }); + + it('should show vorgangList after login', () => { + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + it('should open detailpage', { defaultCommandTimeout }, () => { + visitUrl(authorizedUrl); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + exist(detailPage.getRoot()); + }); + + it('should not open detailpage', { defaultCommandTimeout }, () => { + visitUrl(forbiddenUrl); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + notExist(detailPage.getRoot()); + }); + + it('should show snackbar', () => { + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + }); + + describe('on user zonk', () => { + const authorizedUrl: string = vorgangUrlVisibleToKOrdner; + const forbiddenUrl: string = vorgangUrlVisibleToKFinder; - const eingangForKOrdner: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } }; - const vorgangForKOrdner: VorgangE2E = { ...buildVorgang(vorgangIdForKOrdner, 'VorgangVisibleToKOrdner'), eingangs: [eingangForKOrdner] }; + before(() => { + loginAsZonk(); - before(() => { - initVorgaenge([vorgangForKFinder, vorgangForKOrdner]); - }) + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - after(() => { - dropCollections(); - }) + describe('for vorgang with assigned organisationseinheitenId', () => { + it('should not open detailpage (for kordner)', () => { + visitUrl(authorizedUrl); - describe('on user kfinder', () => { - const authorizedUrl: string = vorgangUrlVisibleToKFinder; - const forbiddenUrl: string = vorgangUrlVisibleToKOrdner; + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); - before(() => { - loginAsKfinder(); - }) + notExist(detailPage.getRoot()); + }); - it('should show vorgangList after login', () => { - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + it('should show snackbar', () => { + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); - it('should open detailpage', { defaultCommandTimeout }, () => { - visitUrl(authorizedUrl); + it('should close snackbar on close button', () => { + //FIXME Workaround, somewhere and somehow here are appearing multiple instances of snackbar(or the button) + snackbar.getCloseButton().click({ multiple: true }); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); + notExist(snackbar.getCloseButton()); + notExist(snackbar.getMessage()); + }); - exist(detailPage.getRoot()); - }) + it('should not open detailpage (for kfinder)', () => { + visitUrl(forbiddenUrl); - it('should not open detailpage', { defaultCommandTimeout }, () => { - visitUrl(forbiddenUrl); + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); + notExist(detailPage.getRoot()); + }); - notExist(detailPage.getRoot()); - }) - - it('should show snackbar', () => { - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - }) - - describe('on user kordner', () => { - const authorizedUrl: string = vorgangUrlVisibleToKOrdner; - const forbiddenUrl: string = vorgangUrlVisibleToKFinder; - - before(() => { - loginAsKordner(); - }) - - it('should show vorgangList after login', () => { - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - it('should open detailpage', { defaultCommandTimeout }, () => { - visitUrl(authorizedUrl); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - exist(detailPage.getRoot()); - }) - - it('should not open detailpage', { defaultCommandTimeout }, () => { - visitUrl(forbiddenUrl); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - notExist(detailPage.getRoot()); - }) - - it('should show snackbar', () => { - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - }) - - describe('on user zonk', () => { - const authorizedUrl: string = vorgangUrlVisibleToKOrdner; - const forbiddenUrl: string = vorgangUrlVisibleToKFinder; - - before(() => { - loginAsZonk(); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - describe('for vorgang with assigned organisationseinheitenId', () => { - - it('should not open detailpage (for kordner)', () => { - visitUrl(authorizedUrl); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - notExist(detailPage.getRoot()); - }) - - it('should show snackbar', () => { - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - - it('should close snackbar on close button', () => { - //FIXME Workaround, somewhere and somehow here are appearing multiple instances of snackbar(or the button) - snackbar.getCloseButton().click({ multiple: true }); - - notExist(snackbar.getCloseButton()); - notExist(snackbar.getMessage()); - }) - - it('should not open detailpage (for kfinder)', () => { - visitUrl(forbiddenUrl); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - notExist(detailPage.getRoot()); - }) - - it('should show snackbar', () => { - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - }) - }) -}); \ No newline at end of file + it('should show snackbar', () => { + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts index a44900080e54cc8fb2d00a1f6d835be689bf34ec..bba552f9720e61065793c38a2edc709e2ea9bbfa 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-exportieren.cy.ts @@ -24,12 +24,19 @@ import { registerLocaleData } from '@angular/common'; import localeDe from '@angular/common/locales/de'; import localeDeExtra from '@angular/common/locales/extra/de'; -import { VorgangMoreMenuE2EComponent, VorgangMoreMenuExportierenItemE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-more-menu.e2e.components'; +import { + VorgangMoreMenuE2EComponent, + VorgangMoreMenuExportierenItemE2EComponent, +} from 'apps/alfa-e2e/src/components/vorgang/vorgang-more-menu.e2e.components'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; -import { countDownloadFiles, deleteDownloadFolder, dropCollections } from '../../../support/cypress-helper'; +import { + countDownloadFiles, + deleteDownloadFolder, + dropCollections, +} from '../../../support/cypress-helper'; import { exist, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgaenge } from '../../../support/vorgang-util'; @@ -37,64 +44,64 @@ import { createVorgang, initVorgaenge } from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang exportieren', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangMoreMenu: VorgangMoreMenuE2EComponent = vorgangPage.getMoreMenu(); + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangMoreMenu: VorgangMoreMenuE2EComponent = vorgangPage.getMoreMenu(); - const vorgangExportieren: VorgangE2E = { ...createVorgang(), name: 'DoExportieren' }; + const vorgangExportieren: VorgangE2E = { ...createVorgang(), name: 'DoExportieren' }; - before(() => { - initVorgaenge([vorgangExportieren]); + before(() => { + initVorgaenge([vorgangExportieren]); - loginAsSabine(); + loginAsSabine(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('exportieren', () => { + describe('exportieren', () => { + const menuItem: VorgangMoreMenuExportierenItemE2EComponent = + vorgangMoreMenu.getExportierenItem(); - const menuItem: VorgangMoreMenuExportierenItemE2EComponent = vorgangMoreMenu.getExportierenItem(); + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangExportieren.name).getRoot().click(); + waitForSpinnerToDisappear(); - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangExportieren.name).getRoot().click(); - waitForSpinnerToDisappear(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) + it('open "more menu"', () => { + vorgangMoreMenu.getButton().click(); - it('open "more menu"', () => { - vorgangMoreMenu.getButton().click(); + exist(vorgangMoreMenu.getRoot()); + }); - exist(vorgangMoreMenu.getRoot()); - }) + it('should show item', () => { + exist(menuItem.getRoot()); + }); - it('should show item', () => { - exist(menuItem.getRoot()); - }) + it('should show "Herunterladen" button', () => { + exist(menuItem.getButton()); + }); - it('should show "Herunterladen" button', () => { - exist(menuItem.getButton()); - }) + it('should have 1 file in download folder after download', () => { + deleteDownloadFolder(); + menuItem.getButton().click(); - it('should have 1 file in download folder after download', () => { - deleteDownloadFolder(); - menuItem.getButton().click(); + waitForSpinnerToDisappear(); + countDownloadFiles().then((count) => { + expect(count).to.eq(1); + }); + }); - waitForSpinnerToDisappear(); - countDownloadFiles().then((count) => { - expect(count).to.eq(1); - }); - }) - - it('should close menu after download', () => { - notExist(menuItem.getRoot()); - }) - }) + it('should close menu after download', () => { + notExist(menuItem.getRoot()); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-verwerfen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-verwerfen.cy.ts index e9ccf001527cbfe24c3d4f0d2ea1b546443a4d63..08eb091172c0888911b99f3f0d82e77e5bb4c627 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-verwerfen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-verwerfen.cy.ts @@ -27,142 +27,167 @@ import localeDeExtra from '@angular/common/locales/extra/de'; import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Verwerfen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangVerwerfen: VorgangE2E = { ...createVorgang(), name: 'DoVerwerfen' }; - const vorgangVerwerfenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeVerwerfen') }; - - before(() => { - initVorgaenge([vorgangVerwerfen, vorgangVerwerfenRevoke]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('verwerfen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangVerwerfen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Neu', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangVerwerfen.status]); - }) - - it('should show snackBar', () => { - vorgangFormularButtons.getVerwerfenButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN); - }) - - it('should close snackBar on close button', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getMessage()); - }) - - it('should have status Verworfen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]); - }) - - it('should have button zurückholen', () => { - exist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); - exist(vorgangFormularButtons.getZurueckholenButton()); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Verworfen', () => { - haveText(vorgangList.getListItem(vorgangVerwerfen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]); - }) - }) - }) - - describe('verwerfen und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangVerwerfenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Neu', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangVerwerfenRevoke.status]); - }) - - it('should show snackBar', () => { - vorgangPage.getSubnavigation().getVerwerfenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN); - }) - - it('should close snackbar on revoke', () => { - snackbar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackbar.getMessage()); - }) - - it('should show status Neu', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]); - }) - - it('should not have button zurückholen', () => { - notExist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); - notExist(vorgangFormularButtons.getZurueckholenButton()); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Neu', () => { - haveText(vorgangList.getListItem(vorgangVerwerfenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]); - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangVerwerfen: VorgangE2E = { ...createVorgang(), name: 'DoVerwerfen' }; + const vorgangVerwerfenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeVerwerfen') }; + + before(() => { + initVorgaenge([vorgangVerwerfen, vorgangVerwerfenRevoke]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('verwerfen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangVerwerfen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Neu', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangVerwerfen.status], + ); + }); + + it('should show snackBar', () => { + vorgangFormularButtons.getVerwerfenButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN); + }); + + it('should close snackBar on close button', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getMessage()); + }); + + it('should have status Verworfen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + + it('should have button zurückholen', () => { + exist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); + exist(vorgangFormularButtons.getZurueckholenButton()); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Verworfen', () => { + haveText( + vorgangList.getListItem(vorgangVerwerfen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + }); + }); + + describe('verwerfen und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangVerwerfenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Neu', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangVerwerfenRevoke.status], + ); + }); + + it('should show snackBar', () => { + vorgangPage.getSubnavigation().getVerwerfenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), VorgangMessagesE2E.VERWORFEN); + }); + + it('should close snackbar on revoke', () => { + snackbar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackbar.getMessage()); + }); + + it('should show status Neu', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.NEU], + ); + }); + + it('should not have button zurückholen', () => { + notExist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); + notExist(vorgangFormularButtons.getZurueckholenButton()); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Neu', () => { + haveText( + vorgangList.getListItem(vorgangVerwerfenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.NEU], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-vorpruefen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-vorpruefen.cy.ts index 3a2279a0ba453e1af9eee2dc1037c04430a4a71d..6777cbb5059f9cab9786424aa7a475bcd01fb45f 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-vorpruefen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-vorpruefen.cy.ts @@ -24,8 +24,16 @@ import { registerLocaleData } from '@angular/common'; import localeDe from '@angular/common/locales/de'; import localeDeExtra from '@angular/common/locales/extra/de'; -import { VorgangMoreMenuE2EComponent, VorgangMoreMenuVorpruefenItemE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-more-menu.e2e.components'; -import { EingangE2E, EingangHeaderE2E, VorgangE2E, VorgangStatusE2E } from 'apps/alfa-e2e/src/model/vorgang'; +import { + VorgangMoreMenuE2EComponent, + VorgangMoreMenuVorpruefenItemE2EComponent, +} from 'apps/alfa-e2e/src/components/vorgang/vorgang-more-menu.e2e.components'; +import { + EingangE2E, + EingangHeaderE2E, + VorgangE2E, + VorgangStatusE2E, +} from 'apps/alfa-e2e/src/model/vorgang'; import 'cypress-real-events/support'; import { KommentareInVorgangE2EComponent } from '../../../components/kommentar/kommentar-list.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; @@ -34,153 +42,169 @@ import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { exist, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe.skip('Vorgang vorprüfen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangMoreMenu: VorgangMoreMenuE2EComponent = vorgangPage.getMoreMenu(); + const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); + + const vorgangOhnePruefung: VorgangE2E = { + ...buildVorgang(objectIds[0], 'NichtZuPruefen'), + status: VorgangStatusE2E.NEU, + }; + + const formIdP: string = 'Erstattung_ERFOLG'; + const formEngineName: string = 'AFM'; + const eingangHeader: EingangHeaderE2E = { ...createVorgang().eingangs[0].header }; + + const eingangP: EingangE2E = { + ...createVorgang().eingangs[0], + header: { ...eingangHeader, formId: formIdP, formEngineName }, + }; + const vorgangVorpruefenPositive: VorgangE2E = { + ...createVorgang(), + name: 'ZuPruefenPositive', + eingangs: [eingangP], + }; + + const formIdN: string = 'Erstattung_FAIL'; + const eingangN: EingangE2E = { + ...createVorgang().eingangs[0], + header: { ...eingangHeader, formId: formIdN, formEngineName }, + }; + const vorgangVorpruefenNegative: VorgangE2E = { + ...buildVorgang(objectIds[1], 'ZuPruefenNegative'), + eingangs: [eingangN], + }; + + before(() => { + initVorgaenge([vorgangOhnePruefung, vorgangVorpruefenPositive, vorgangVorpruefenNegative]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('do vorprüfen...', () => { + describe('...vorpruefen with positive answer from Prozessor', () => { + const menuItem: VorgangMoreMenuVorpruefenItemE2EComponent = + vorgangMoreMenu.getVorpruefenItem(); + const kommentarText = 'Positive text, tbd'; + + it('should open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangVorpruefenPositive.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should open "more menu"', () => { + //nur testweise + //kommentarContainer.getHinzufuegenButton().click(); + //kommentarContainer.getTextInput().clear().type(kommentarText); + //kommentarContainer.getFormularSpeichernButton().click(); + waitForSpinnerToDisappear(); + // + + vorgangMoreMenu.getButton().click(); + + exist(vorgangMoreMenu.getRoot()); + }); + + it('should show Prüfung item', () => { + //exist(menuItem.getRoot());? + }); + + it('should show "Vorgang vorpüfen" button', () => { + exist(menuItem.getButton()); + }); + + it('should have a positive comment after Prüfung', () => { + menuItem.getButton().click(); + //waitForSpinnerToDisappear(); + + exist(kommentarContainer.getKommentar(kommentarText).getRoot()); + //check for positive comment + }); + + it('should close menu after Prüfung', () => { + //am Ende entfernen + vorgangMoreMenu.getButton().click(); + + //notExist(menuItem.getRoot()); + + vorgangPage.getSubnavigation().getBackButton().click(); + }); + }); + + describe('...vorpruefen with negative answer from Prozessor', () => { + const menuItem: VorgangMoreMenuVorpruefenItemE2EComponent = + vorgangMoreMenu.getVorpruefenItem(); + const kommentarText = 'Negative text, tbd'; + + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangVorpruefenNegative.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should have a negative comment after Prüfung', () => { + vorgangMoreMenu.getButton().click(); + + menuItem.getButton().click(); + + //nur testweise + //kommentarContainer.getHinzufuegenButton().click(); + //kommentarContainer.getTextInput().clear().type(kommentarText); + //kommentarContainer.getFormularSpeichernButton().click(); + waitForSpinnerToDisappear(); + // - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangMoreMenu: VorgangMoreMenuE2EComponent = vorgangPage.getMoreMenu(); - const kommentarContainer: KommentareInVorgangE2EComponent = vorgangPage.getKommentarContainer(); + waitForSpinnerToDisappear(); + + exist(kommentarContainer.getKommentar(kommentarText).getRoot()); + //check for negative comment + }); - const vorgangOhnePruefung: VorgangE2E = { ...buildVorgang(objectIds[0], 'NichtZuPruefen'), status: VorgangStatusE2E.NEU}; + it('should close menu after Prüfung', () => { + notExist(menuItem.getRoot()); - const formIdP: string = 'Erstattung_ERFOLG'; - const formEngineName: string = 'AFM'; - const eingangHeader: EingangHeaderE2E = { ...createVorgang().eingangs[0].header }; + vorgangPage.getSubnavigation().getBackButton().click(); + }); + }); - const eingangP: EingangE2E = { ...createVorgang().eingangs[0], header: { ...eingangHeader, formId: formIdP, formEngineName } } - const vorgangVorpruefenPositive: VorgangE2E = { ...createVorgang(), name: 'ZuPruefenPositive', eingangs: [eingangP] }; + describe('button not available on other Vorgänge', () => { + const menuItem: VorgangMoreMenuVorpruefenItemE2EComponent = + vorgangMoreMenu.getVorpruefenItem(); - const formIdN: string = 'Erstattung_FAIL'; - const eingangN: EingangE2E = { ...createVorgang().eingangs[0], header: { ...eingangHeader, formId: formIdN, formEngineName } } - const vorgangVorpruefenNegative: VorgangE2E = { ...buildVorgang(objectIds[1], 'ZuPruefenNegative'), eingangs: [eingangN] }; - - before(() => { - initVorgaenge([vorgangOhnePruefung, vorgangVorpruefenPositive, vorgangVorpruefenNegative]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('do vorprüfen...', () => { - - describe('...vorpruefen with positive answer from Prozessor', () => { - - const menuItem: VorgangMoreMenuVorpruefenItemE2EComponent = vorgangMoreMenu.getVorpruefenItem(); - const kommentarText = 'Positive text, tbd'; - - it('should open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangVorpruefenPositive.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should open "more menu"', () => { - - //nur testweise - //kommentarContainer.getHinzufuegenButton().click(); - //kommentarContainer.getTextInput().clear().type(kommentarText); - //kommentarContainer.getFormularSpeichernButton().click(); - waitForSpinnerToDisappear(); - // - - vorgangMoreMenu.getButton().click(); - - exist(vorgangMoreMenu.getRoot()); - }) - - it('should show Prüfung item', () => { - //exist(menuItem.getRoot());? - }) - - it('should show "Vorgang vorpüfen" button', () => { - exist(menuItem.getButton()); - }) - - it('should have a positive comment after Prüfung', () => { - menuItem.getButton().click(); - //waitForSpinnerToDisappear(); - - exist(kommentarContainer.getKommentar(kommentarText).getRoot()); - //check for positive comment - }) - - it('should close menu after Prüfung', () => { - //am Ende entfernen - vorgangMoreMenu.getButton().click(); - - //notExist(menuItem.getRoot()); - - vorgangPage.getSubnavigation().getBackButton().click(); - }) - }) - - describe('...vorpruefen with negative answer from Prozessor', () => { - - const menuItem: VorgangMoreMenuVorpruefenItemE2EComponent = vorgangMoreMenu.getVorpruefenItem(); - const kommentarText = 'Negative text, tbd'; - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangVorpruefenNegative.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should have a negative comment after Prüfung', () => { - vorgangMoreMenu.getButton().click(); - - menuItem.getButton().click(); - - //nur testweise - //kommentarContainer.getHinzufuegenButton().click(); - //kommentarContainer.getTextInput().clear().type(kommentarText); - //kommentarContainer.getFormularSpeichernButton().click(); - waitForSpinnerToDisappear(); - // - - waitForSpinnerToDisappear(); - - exist(kommentarContainer.getKommentar(kommentarText).getRoot()); - //check for negative comment - }) - - it('should close menu after Prüfung', () => { - notExist(menuItem.getRoot()); - - vorgangPage.getSubnavigation().getBackButton().click(); - }) - }) - - describe('button not available on other Vorgänge', () => { - - const menuItem: VorgangMoreMenuVorpruefenItemE2EComponent = vorgangMoreMenu.getVorpruefenItem(); - - it('should open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangOhnePruefung.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('more menu should not contain Vorprüfen button', () => { - vorgangMoreMenu.getButton().click(); - notExist(menuItem.getRoot()); - }) - - }) - }) + it('should open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangOhnePruefung.name).getRoot().click(); + waitForSpinnerToDisappear(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + it('more menu should not contain Vorprüfen button', () => { + vorgangMoreMenu.getButton().click(); + notExist(menuItem.getRoot()); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts index 5ab50dc75f0a4d4fabf581b2c143ab7ad79f6ea1..28abf1fb5c756fbcf486db5546760d3f46950f6d 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedereroeffnen.cy.ts @@ -24,230 +24,287 @@ import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; describe('Vorgang wiedereroeffnen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangBeschiedenWiedereroeffnen: VorgangE2E = { ...createVorgang(), name: 'DoWiedereroeffnenOnBeschieden', status: VorgangStatusE2E.BESCHIEDEN }; - const vorgangBeschiedenWiedereroeffnenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeWiedereroeffnenOnBeschieden'), status: VorgangStatusE2E.BESCHIEDEN }; - const vorgangAbgeschlossenWiedereroeffnen: VorgangE2E = { ...buildVorgang(objectIds[1], 'DoWiedereroeffnenOnAbgeschlossen'), status: VorgangStatusE2E.ABGESCHLOSSEN };; - const vorgangAbgeschlossenWiedereroeffnenRevoke: VorgangE2E = { ...buildVorgang(objectIds[2], 'DoRevokeWiedereroeffnenOnAbgeschlossen'), status: VorgangStatusE2E.ABGESCHLOSSEN };; - - before(() => { - initVorgaenge([vorgangBeschiedenWiedereroeffnen, vorgangBeschiedenWiedereroeffnenRevoke, vorgangAbgeschlossenWiedereroeffnen, vorgangAbgeschlossenWiedereroeffnenRevoke]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('vorgang in status beschieden', () => { - - describe('wiedereroeffnen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangBeschiedenWiedereroeffnen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Beschieden', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangBeschiedenWiedereroeffnen.status]); - }) - - it('should show snackBar message', () => { - vorgangFormularButtons.getWiedereroeffnenButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); - }) - - it('should close snackBar on close', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getMessage()); - }) - - it('should have status In Bearbeitung', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status In Bearbeitung', () => { - haveText(vorgangList.getListItem(vorgangBeschiedenWiedereroeffnen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - }) - }) - - describe('wiedereroeffnen und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangBeschiedenWiedereroeffnenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - it('should have status Beschieden', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangBeschiedenWiedereroeffnenRevoke.status]); - }) - - it('should show snackBar message', () => { - vorgangPage.getSubnavigation().getWiedereroeffnenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); - }) - - it('should close snackbar on revoke', () => { - snackbar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackbar.getMessage()); - }) - - it('should show status Beschieden', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Beschieden', () => { - haveText(vorgangList.getListItem(vorgangBeschiedenWiedereroeffnenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN]); - }) - }) - }) - }) - - describe('vorgang in status abgeschlossen', () => { - - describe('wiedereroeffnen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbgeschlossenWiedereroeffnen.status]); - }) - - it('should show snackBar', () => { - vorgangFormularButtons.getWiedereroeffnenButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); - }) - - it('should close snackBar on close', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getMessage()); - }) - - it('should have status In Bearbeitung', () => { - vorgangPage.getVorgangDetailHeader().getStatus().should('exist').should('have.text', vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status In Bearbeitung', () => { - haveText(vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - }) - }) - - describe('wiedereroeffnen und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Abgeschlossen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangAbgeschlossenWiedereroeffnenRevoke.status]); - }) - - it('should show snackBar', () => { - vorgangPage.getSubnavigation().getWiedereroeffnenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getCloseButton()); - contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); - }) - - it('should close snackbar on revoke', () => { - snackbar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackbar.getMessage()); - }) - - it('should show status Abgeschlossen', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Abgeschlossen', () => { - haveText(vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN]); - }) - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangBeschiedenWiedereroeffnen: VorgangE2E = { + ...createVorgang(), + name: 'DoWiedereroeffnenOnBeschieden', + status: VorgangStatusE2E.BESCHIEDEN, + }; + const vorgangBeschiedenWiedereroeffnenRevoke: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoRevokeWiedereroeffnenOnBeschieden'), + status: VorgangStatusE2E.BESCHIEDEN, + }; + const vorgangAbgeschlossenWiedereroeffnen: VorgangE2E = { + ...buildVorgang(objectIds[1], 'DoWiedereroeffnenOnAbgeschlossen'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + const vorgangAbgeschlossenWiedereroeffnenRevoke: VorgangE2E = { + ...buildVorgang(objectIds[2], 'DoRevokeWiedereroeffnenOnAbgeschlossen'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + + before(() => { + initVorgaenge([ + vorgangBeschiedenWiedereroeffnen, + vorgangBeschiedenWiedereroeffnenRevoke, + vorgangAbgeschlossenWiedereroeffnen, + vorgangAbgeschlossenWiedereroeffnenRevoke, + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('vorgang in status beschieden', () => { + describe('wiedereroeffnen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangBeschiedenWiedereroeffnen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Beschieden', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangBeschiedenWiedereroeffnen.status], + ); + }); + + it('should show snackBar message', () => { + vorgangFormularButtons.getWiedereroeffnenButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); + }); + + it('should close snackBar on close', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getMessage()); + }); + + it('should have status In Bearbeitung', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status In Bearbeitung', () => { + haveText( + vorgangList.getListItem(vorgangBeschiedenWiedereroeffnen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + }); + }); + + describe('wiedereroeffnen und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangBeschiedenWiedereroeffnenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Beschieden', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangBeschiedenWiedereroeffnenRevoke.status], + ); + }); + + it('should show snackBar message', () => { + vorgangPage.getSubnavigation().getWiedereroeffnenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); + }); + + it('should close snackbar on revoke', () => { + snackbar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackbar.getMessage()); + }); + + it('should show status Beschieden', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Beschieden', () => { + haveText( + vorgangList.getListItem(vorgangBeschiedenWiedereroeffnenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.BESCHIEDEN], + ); + }); + }); + }); + }); + + describe('vorgang in status abgeschlossen', () => { + describe('wiedereroeffnen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbgeschlossenWiedereroeffnen.status], + ); + }); + + it('should show snackBar', () => { + vorgangFormularButtons.getWiedereroeffnenButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); + }); + + it('should close snackBar on close', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getMessage()); + }); + + it('should have status In Bearbeitung', () => { + vorgangPage + .getVorgangDetailHeader() + .getStatus() + .should('exist') + .should('have.text', vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status In Bearbeitung', () => { + haveText( + vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + }); + }); + + describe('wiedereroeffnen und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Abgeschlossen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangAbgeschlossenWiedereroeffnenRevoke.status], + ); + }); + + it('should show snackBar', () => { + vorgangPage.getSubnavigation().getWiedereroeffnenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getCloseButton()); + contains(snackbar.getMessage(), VorgangMessagesE2E.WIEDEREROEFFNET); + }); + + it('should close snackbar on revoke', () => { + snackbar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackbar.getMessage()); + }); + + it('should show status Abgeschlossen', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Abgeschlossen', () => { + haveText( + vorgangList.getListItem(vorgangAbgeschlossenWiedereroeffnenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ABGESCHLOSSEN], + ); + }); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedervorlage-loading.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedervorlage-loading.cy.ts index d9c6a2709786399b5fada7f5271771a60e071277..7695f8ebda8dc062b3076c1eaef52236a02bee80 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedervorlage-loading.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-wiedervorlage-loading.cy.ts @@ -1,135 +1,160 @@ -import { VorgangListE2EComponent } from "apps/alfa-e2e/src/components/vorgang/vorgang-list.e2e.component"; -import { WiedervorlageInVorgangE2EComponent } from "apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-in-vorgang.e2e.component"; -import { WiedervorlagenInVorgangE2EComponent } from "apps/alfa-e2e/src/components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component"; -import { VorgangE2E } from "apps/alfa-e2e/src/model/vorgang"; -import { VorgangAttachedItemE2E } from "apps/alfa-e2e/src/model/vorgang-attached-item"; -import { WiedervorlageE2E } from "apps/alfa-e2e/src/model/wiedervorlage"; -import { MainPage, waitForSpinnerToDisappear } from "apps/alfa-e2e/src/page-objects/main.po"; -import { VorgangPage } from "apps/alfa-e2e/src/page-objects/vorgang.po"; -import { WiedervorlagePage } from "apps/alfa-e2e/src/page-objects/wiedervorlage.po"; -import { dropCollections } from "apps/alfa-e2e/src/support/cypress-helper"; -import { exist, haveText } from "apps/alfa-e2e/src/support/cypress.util"; -import { loginAsSabine } from "apps/alfa-e2e/src/support/user-util"; -import { initVorgangAttachedItem } from "apps/alfa-e2e/src/support/vorgang-attached-item-util"; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from "apps/alfa-e2e/src/support/vorgang-util"; -import { createWiedervorlageAttachedItem, createWiedervorlageItem } from "apps/alfa-e2e/src/support/wiedervorlage-util"; +import { VorgangListE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-list.e2e.component'; +import { WiedervorlageInVorgangE2EComponent } from 'apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-in-vorgang.e2e.component'; +import { WiedervorlagenInVorgangE2EComponent } from 'apps/alfa-e2e/src/components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component'; +import { VorgangE2E } from 'apps/alfa-e2e/src/model/vorgang'; +import { VorgangAttachedItemE2E } from 'apps/alfa-e2e/src/model/vorgang-attached-item'; +import { WiedervorlageE2E } from 'apps/alfa-e2e/src/model/wiedervorlage'; +import { MainPage, waitForSpinnerToDisappear } from 'apps/alfa-e2e/src/page-objects/main.po'; +import { VorgangPage } from 'apps/alfa-e2e/src/page-objects/vorgang.po'; +import { WiedervorlagePage } from 'apps/alfa-e2e/src/page-objects/wiedervorlage.po'; +import { dropCollections } from 'apps/alfa-e2e/src/support/cypress-helper'; +import { exist, haveText } from 'apps/alfa-e2e/src/support/cypress.util'; +import { loginAsSabine } from 'apps/alfa-e2e/src/support/user-util'; +import { initVorgangAttachedItem } from 'apps/alfa-e2e/src/support/vorgang-attached-item-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from 'apps/alfa-e2e/src/support/vorgang-util'; +import { + createWiedervorlageAttachedItem, + createWiedervorlageItem, +} from 'apps/alfa-e2e/src/support/wiedervorlage-util'; describe('Vorgang wiedervorlage loading', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const vorgangPage: VorgangPage = new VorgangPage(); - const wiedervorlagContainer: WiedervorlagenInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer(); + const vorgangPage: VorgangPage = new VorgangPage(); + const wiedervorlagContainer: WiedervorlagenInVorgangE2EComponent = + vorgangPage.getWiedervorlagenContainer(); - const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); + const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); - const vorgangWithWiedervorlagen: VorgangE2E = { ...createVorgang(), name: 'VorgangWithWiedervorlagen' }; - const wiedervorlage: WiedervorlageE2E = createWiedervorlageItem('EineWiedervorlage'); - const wiedervorlageAttachedItem: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[0], vorgangWithWiedervorlagen._id.$oid), item: wiedervorlage }; + const vorgangWithWiedervorlagen: VorgangE2E = { + ...createVorgang(), + name: 'VorgangWithWiedervorlagen', + }; + const wiedervorlage: WiedervorlageE2E = createWiedervorlageItem('EineWiedervorlage'); + const wiedervorlageAttachedItem: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[0], vorgangWithWiedervorlagen._id.$oid), + item: wiedervorlage, + }; - const vorgangWithOtherWiedervorlagen: VorgangE2E = buildVorgang(objectIds[0], 'VorgangWithOtherWiedervorlagen'); - const otherWiedervorlage: WiedervorlageE2E = createWiedervorlageItem('EineAndereWiedervorlage'); - const otherWiedervorlageAttachedItem: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[1], vorgangWithOtherWiedervorlagen._id.$oid), item: otherWiedervorlage }; + const vorgangWithOtherWiedervorlagen: VorgangE2E = buildVorgang( + objectIds[0], + 'VorgangWithOtherWiedervorlagen', + ); + const otherWiedervorlage: WiedervorlageE2E = createWiedervorlageItem('EineAndereWiedervorlage'); + const otherWiedervorlageAttachedItem: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[1], vorgangWithOtherWiedervorlagen._id.$oid), + item: otherWiedervorlage, + }; - before(() => { - initVorgaenge([vorgangWithWiedervorlagen, vorgangWithOtherWiedervorlagen]); - initVorgangAttachedItem([wiedervorlageAttachedItem, otherWiedervorlageAttachedItem]); + before(() => { + initVorgaenge([vorgangWithWiedervorlagen, vorgangWithOtherWiedervorlagen]); + initVorgangAttachedItem([wiedervorlageAttachedItem, otherWiedervorlageAttachedItem]); - loginAsSabine(); + loginAsSabine(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('Vorgang with wiedervorlagen', () => { + describe('Vorgang with wiedervorlagen', () => { + it('should show vorgang detail by click on vorgang in list', () => { + vorgangList.getListItem(vorgangWithWiedervorlagen.name).getRoot().click(); + waitForSpinnerToDisappear(); - it('should show vorgang detail by click on vorgang in list', () => { - vorgangList.getListItem(vorgangWithWiedervorlagen.name).getRoot().click(); - waitForSpinnerToDisappear(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) + it('should show wiedervorlage on vorgang page', () => { + const singleWiedervorlage = wiedervorlagContainer.getWiedervorlage(wiedervorlage.betreff); - it('should show wiedervorlage on vorgang page', () => { - const singleWiedervorlage = wiedervorlagContainer.getWiedervorlage(wiedervorlage.betreff); + exist(singleWiedervorlage.getRoot()); - exist(singleWiedervorlage.getRoot()); + haveText(singleWiedervorlage.getBetreff(), wiedervorlage.betreff); + }); - haveText(singleWiedervorlage.getBetreff(), wiedervorlage.betreff); - }) + it('should open Wiedervorlage-Page by click on wiedervorlage ', () => { + const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = + wiedervorlagContainer.getWiedervorlage(wiedervorlage.betreff); - it('should open Wiedervorlage-Page by click on wiedervorlage ', () => { - const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = wiedervorlagContainer.getWiedervorlage(wiedervorlage.betreff); + wiedervorlageInVorgang.getLink().click(); + waitForSpinnerToDisappear(); - wiedervorlageInVorgang.getLink().click(); - waitForSpinnerToDisappear(); + exist(wiedervorlagePage.getSubnavigation().getRoot()); + }); - exist(wiedervorlagePage.getSubnavigation().getRoot()); - }) + it('should show wiedervorlage on vorgang page on navigate back', () => { + wiedervorlagePage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); - it('should show wiedervorlage on vorgang page on navigate back', () => { - wiedervorlagePage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); + const singleWiedervorlage = wiedervorlagContainer.getWiedervorlage(wiedervorlage.betreff); + exist(singleWiedervorlage.getRoot()); + }); - const singleWiedervorlage = wiedervorlagContainer.getWiedervorlage(wiedervorlage.betreff); - exist(singleWiedervorlage.getRoot()); - }) + it('should show vorganglist on navigate back', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); - it('should show vorganglist on navigate back', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + }); - exist(vorgangList.getRoot()); - }) - }) + describe.skip('Vorgang without wiedervorlagen', () => { + it('should show vorgang detail by click on vorgang in list', () => { + vorgangList.getListItem(vorgangWithOtherWiedervorlagen.name).getRoot().click(); + waitForSpinnerToDisappear(); - describe.skip('Vorgang without wiedervorlagen', () => { + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); - it('should show vorgang detail by click on vorgang in list', () => { - vorgangList.getListItem(vorgangWithOtherWiedervorlagen.name).getRoot().click(); - waitForSpinnerToDisappear(); + it('should show other wiedervorlage on vorgang page', () => { + const singleWiedervorlage = wiedervorlagContainer.getWiedervorlage( + otherWiedervorlage.betreff, + ); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) + exist(singleWiedervorlage.getRoot()); - it('should show other wiedervorlage on vorgang page', () => { - const singleWiedervorlage = wiedervorlagContainer.getWiedervorlage(otherWiedervorlage.betreff); + haveText(singleWiedervorlage.getBetreff(), otherWiedervorlage.betreff); + }); - exist(singleWiedervorlage.getRoot()); + it('should open Wiedervorlage-Page by click on wiedervorlage ', () => { + const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = + wiedervorlagContainer.getWiedervorlage(otherWiedervorlage.betreff); - haveText(singleWiedervorlage.getBetreff(), otherWiedervorlage.betreff); - }) + wiedervorlageInVorgang.getLink().click(); + waitForSpinnerToDisappear(); - it('should open Wiedervorlage-Page by click on wiedervorlage ', () => { - const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = wiedervorlagContainer.getWiedervorlage(otherWiedervorlage.betreff); + exist(wiedervorlagePage.getSubnavigation().getRoot()); + }); - wiedervorlageInVorgang.getLink().click(); - waitForSpinnerToDisappear(); + it('should keep empty wiedervorlagen on vorgang page on navigate back', () => { + wiedervorlagePage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); - exist(wiedervorlagePage.getSubnavigation().getRoot()); - }) + exist(vorgangPage.getVorgangDetailHeader().getRoot()); - it('should keep empty wiedervorlagen on vorgang page on navigate back', () => { - wiedervorlagePage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); + const singleWiedervorlage = wiedervorlagContainer.getWiedervorlage( + otherWiedervorlage.betreff, + ); + exist(singleWiedervorlage.getRoot()); + }); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); + it('should show vorganglist on navigate back', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); - const singleWiedervorlage = wiedervorlagContainer.getWiedervorlage(otherWiedervorlage.betreff); - exist(singleWiedervorlage.getRoot()); - }) - - it('should show vorganglist on navigate back', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - }) -}) \ No newline at end of file + exist(vorgangList.getRoot()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckholen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckholen.cy.ts index 5ada1f9a39df97c545fafcedcf665095244435b0..4c9784b5deb9e801dce14ff83721694e60e0f942 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckholen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckholen.cy.ts @@ -27,141 +27,173 @@ import localeDeExtra from '@angular/common/locales/extra/de'; import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-formular-buttons.e2e.components'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Zurueckholen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangZurueckholen: VorgangE2E = { ...createVorgang(), name: 'DoZurueckholen', status: VorgangStatusE2E.VERWORFEN }; - const vorgangZurueckholenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeZurueckholen'), status: VorgangStatusE2E.VERWORFEN }; - - before(() => { - initVorgaenge([vorgangZurueckholen, vorgangZurueckholenRevoke]) - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('Zurueckholen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangZurueckholen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status Verworfen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZurueckholen.status]); - }) - - it('should show snackBar message', () => { - vorgangFormularButtons.getZurueckholenButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT); - }) - - it('should close snackBar on close button', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status Neu', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]); - }) - - it('should have button annehmen und verwerfen', () => { - exist(vorgangFormularButtons.getVerwerfenButton()); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Neu', () => { - haveText(vorgangList.getListItem(vorgangZurueckholen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.NEU]); - }) - }) - }) - - describe('Zurueckholen und rueckgaengig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangZurueckholenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status Neu', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZurueckholenRevoke.status]); - }) - - it('should show snackBar', () => { - vorgangPage.getSubnavigation().getZurueckholenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status Abgeschlossen', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]); - }) - - it('should have button zurueckholen', () => { - exist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); - exist(vorgangFormularButtons.getZurueckholenButton()); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Verworfen', () => { - haveText(vorgangList.getListItem(vorgangZurueckholenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN]); - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangZurueckholen: VorgangE2E = { + ...createVorgang(), + name: 'DoZurueckholen', + status: VorgangStatusE2E.VERWORFEN, + }; + const vorgangZurueckholenRevoke: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoRevokeZurueckholen'), + status: VorgangStatusE2E.VERWORFEN, + }; + + before(() => { + initVorgaenge([vorgangZurueckholen, vorgangZurueckholenRevoke]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('Zurueckholen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangZurueckholen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status Verworfen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangZurueckholen.status], + ); + }); + + it('should show snackBar message', () => { + vorgangFormularButtons.getZurueckholenButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT); + }); + + it('should close snackBar on close button', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status Neu', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.NEU], + ); + }); + + it('should have button annehmen und verwerfen', () => { + exist(vorgangFormularButtons.getVerwerfenButton()); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Neu', () => { + haveText( + vorgangList.getListItem(vorgangZurueckholen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.NEU], + ); + }); + }); + }); + + describe('Zurueckholen und rueckgaengig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangZurueckholenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status Neu', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangZurueckholenRevoke.status], + ); + }); + + it('should show snackBar', () => { + vorgangPage.getSubnavigation().getZurueckholenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGEHOLT); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status Abgeschlossen', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + + it('should have button zurueckholen', () => { + exist(vorgangPage.getSubnavigation().getZurueckholenIconButton()); + exist(vorgangFormularButtons.getZurueckholenButton()); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Verworfen', () => { + haveText( + vorgangList.getListItem(vorgangZurueckholenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.VERWORFEN], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.cy.ts index 047f3d25ffd65fe372f7fc0f7142abab5ed0ee21..b441e5a4118c0c8456ed46523e90144f7ac83495 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-detailansicht/vorgang-zurueckstellen.cy.ts @@ -28,139 +28,185 @@ import { VorgangFormularButtonsE2EComponent } from 'apps/alfa-e2e/src/components import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { UserProfileE2EComponent } from '../../../components/user-profile/user-profile.component.e2e'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; -import { VorgangE2E, VorgangMessagesE2E, VorgangStatusE2E, vorgangStatusLabelE2E } from '../../../model/vorgang'; +import { + VorgangE2E, + VorgangMessagesE2E, + VorgangStatusE2E, + vorgangStatusLabelE2E, +} from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { dropCollections } from '../../../support/cypress-helper'; import { contains, exist, haveText, notExist } from '../../../support/cypress.util'; -import { getUserManagerUserEmil, getUserManagerUserPeter, getUserManagerUserSabine, getUserSabineInternalId, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + getUserManagerUserEmil, + getUserManagerUserPeter, + getUserManagerUserSabine, + getUserSabineInternalId, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Zurueckstellen', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const userContainer: UserProfileE2EComponent = vorgangPage.getVorgangDetailHeader().getUserContainer(); - const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = vorgangPage.getFormularButtons(); - - const vorgangZurueckstellen: VorgangE2E = { ...createVorgang(), name: 'DoBescheiden', status: VorgangStatusE2E.IN_BEARBEITUNG, assignedTo: getUserSabineInternalId() }; - const vorgangZurueckstellenRevoke: VorgangE2E = { ...buildVorgang(objectIds[0], 'DoRevokeBescheiden'), status: VorgangStatusE2E.IN_BEARBEITUNG }; - - before(() => { - initVorgaenge([vorgangZurueckstellen, vorgangZurueckstellenRevoke]); - initUsermanagerUsers([getUserManagerUserSabine(), getUserManagerUserPeter(), getUserManagerUserEmil()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('zurueckstellen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangZurueckstellen.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by button', () => { - - it('should have status In Bearbeitung', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZurueckstellen.status]); - }) - - it('should have assigned user(Bearbeiter)', () => { - exist(userContainer.getRoot()); - exist(userContainer.getIconContainer().getAssignedIcon()); - }) - - it('should show snackBar message', () => { - vorgangFormularButtons.getZurueckstellenButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGESTELLT); - }) - - it('should close snackBar', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should have status Angenommen', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status Zurückgestellt', () => { - haveText(vorgangList.getListItem(vorgangZurueckstellen.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN]); - }) - }) - }) - - describe('zurückstellen und rückgängig machen', () => { - - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgangZurueckstellenRevoke.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('by icon-button', () => { - - it('should have status In Bearbeitung', () => { - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[vorgangZurueckstellenRevoke.status]); - }) - - it('should show snackBar message', () => { - vorgangPage.getSubnavigation().getZurueckstellenIconButton().click(); - waitForSpinnerToDisappear(); - - exist(snackBar.getCloseButton()); - contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGESTELLT); - }) - - it('should close snackbar on revoke', () => { - snackBar.getRevokeButton().click(); - waitForSpinnerToDisappear(); - - notExist(snackBar.getMessage()); - }) - - it('should show status In Bearbeitung', () => { - notExist(vorgangPage.getProgressBar()); - - haveText(vorgangPage.getVorgangDetailHeader().getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should have status In Bearbeitung', () => { - haveText(vorgangList.getListItem(vorgangZurueckstellenRevoke.name).getStatus(), vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG]); - }) - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const userContainer: UserProfileE2EComponent = vorgangPage + .getVorgangDetailHeader() + .getUserContainer(); + const vorgangFormularButtons: VorgangFormularButtonsE2EComponent = + vorgangPage.getFormularButtons(); + + const vorgangZurueckstellen: VorgangE2E = { + ...createVorgang(), + name: 'DoBescheiden', + status: VorgangStatusE2E.IN_BEARBEITUNG, + assignedTo: getUserSabineInternalId(), + }; + const vorgangZurueckstellenRevoke: VorgangE2E = { + ...buildVorgang(objectIds[0], 'DoRevokeBescheiden'), + status: VorgangStatusE2E.IN_BEARBEITUNG, + }; + + before(() => { + initVorgaenge([vorgangZurueckstellen, vorgangZurueckstellenRevoke]); + initUsermanagerUsers([ + getUserManagerUserSabine(), + getUserManagerUserPeter(), + getUserManagerUserEmil(), + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('zurueckstellen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangZurueckstellen.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by button', () => { + it('should have status In Bearbeitung', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangZurueckstellen.status], + ); + }); + + it('should have assigned user(Bearbeiter)', () => { + exist(userContainer.getRoot()); + exist(userContainer.getIconContainer().getAssignedIcon()); + }); + + it('should show snackBar message', () => { + vorgangFormularButtons.getZurueckstellenButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGESTELLT); + }); + + it('should close snackBar', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should have status Angenommen', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status Zurückgestellt', () => { + haveText( + vorgangList.getListItem(vorgangZurueckstellen.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.ANGENOMMEN], + ); + }); + }); + }); + + describe('zurückstellen und rückgängig machen', () => { + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgangZurueckstellenRevoke.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('by icon-button', () => { + it('should have status In Bearbeitung', () => { + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[vorgangZurueckstellenRevoke.status], + ); + }); + + it('should show snackBar message', () => { + vorgangPage.getSubnavigation().getZurueckstellenIconButton().click(); + waitForSpinnerToDisappear(); + + exist(snackBar.getCloseButton()); + contains(snackBar.getMessage(), VorgangMessagesE2E.ZURUECKGESTELLT); + }); + + it('should close snackbar on revoke', () => { + snackBar.getRevokeButton().click(); + waitForSpinnerToDisappear(); + + notExist(snackBar.getMessage()); + }); + + it('should show status In Bearbeitung', () => { + notExist(vorgangPage.getProgressBar()); + + haveText( + vorgangPage.getVorgangDetailHeader().getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should have status In Bearbeitung', () => { + haveText( + vorgangList.getListItem(vorgangZurueckstellenRevoke.name).getStatus(), + vorgangStatusLabelE2E[VorgangStatusE2E.IN_BEARBEITUNG], + ); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list-wiedervorlage/vorgang-list-wiedervorlagen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list-wiedervorlage/vorgang-list-wiedervorlagen.cy.ts index 83ee455a4eb20372ccbf4735de1bcc75a238f07b..f74517b847dbf07ae728d5bfc4aa4526f69d7802 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list-wiedervorlage/vorgang-list-wiedervorlagen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list-wiedervorlage/vorgang-list-wiedervorlagen.cy.ts @@ -25,92 +25,139 @@ import { registerLocaleData } from '@angular/common'; import localeDe from '@angular/common/locales/de'; import localeDeExtra from '@angular/common/locales/extra/de'; import { VorgangAttachedItemE2E } from 'apps/alfa-e2e/src/model/vorgang-attached-item'; -import { createDateInTheFuture, createDateInThePast, createDateToday } from 'apps/alfa-e2e/src/support/tech.util'; +import { + createDateInTheFuture, + createDateInThePast, + createDateToday, +} from 'apps/alfa-e2e/src/support/tech.util'; import { initVorgangAttachedItem } from 'apps/alfa-e2e/src/support/vorgang-attached-item-util'; -import { createWiedervorlageAttachedItem, createWiedervorlageItem } from 'apps/alfa-e2e/src/support/wiedervorlage-util'; +import { + createWiedervorlageAttachedItem, + createWiedervorlageItem, +} from 'apps/alfa-e2e/src/support/wiedervorlage-util'; import { VorgangListItemE2EComponent } from '../../../components/vorgang/vorgang-item.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { ClientAttributeNameE2E, VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { dropCollections } from '../../../support/cypress-helper'; -import { containClass, exist, mouseEnter, notContainClass, notExist } from '../../../support/cypress.util'; +import { + containClass, + exist, + mouseEnter, + notContainClass, + notExist, +} from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; -import { buildVorgang, createAlfaClientAttributes, createNextWiedervorlageFristClientAttribute, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + buildVorgang, + createAlfaClientAttributes, + createNextWiedervorlageFristClientAttribute, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('VorgangList Wiedervorlagen Next Frist', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangWithNoWiedervorlagen: VorgangE2E = { ...createVorgang(), name: 'NoWiedervorlagen' }; - - const vorgangWithWiedervorlageFristToday: VorgangE2E = { - ...buildVorgang(objectIds[0], 'FristToday'), - clientAttributes: createAlfaClientAttributes(ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, createNextWiedervorlageFristClientAttribute(createDateToday())) - }; - const wiedervorlageFristToday: VorgangAttachedItemE2E = { - ...createWiedervorlageAttachedItem(objectIds[1], vorgangWithWiedervorlageFristToday._id.$oid), - item: { ...createWiedervorlageItem('WiedervorlageFristToday'), frist: createDateToday() } - }; - - const vorgangWithWiedervorlageInThePast: VorgangE2E = { - ...buildVorgang(objectIds[2], 'FristInThePast'), - clientAttributes: createAlfaClientAttributes(ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, createNextWiedervorlageFristClientAttribute(createDateInThePast())) - }; - const wiedervorlageFristInThePast: VorgangAttachedItemE2E = { - ...createWiedervorlageAttachedItem(objectIds[3], vorgangWithWiedervorlageInThePast._id.$oid), - item: { ...createWiedervorlageItem('WiedervorlageFristInThePast'), frist: createDateInThePast() } - }; - - - const vorgangWithWiedervorlageInFuture: VorgangE2E = { - ...buildVorgang(objectIds[4], 'FristInTheFuture'), - clientAttributes: createAlfaClientAttributes(ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, createNextWiedervorlageFristClientAttribute(createDateInTheFuture())) - }; - const wiedervorlageFristInTheFuture: VorgangAttachedItemE2E = { - ...createWiedervorlageAttachedItem(objectIds[5], vorgangWithWiedervorlageInFuture._id.$oid), - item: { ...createWiedervorlageItem('WiedervorlageFristInTheFuture'), frist: createDateInTheFuture() } - }; - - before(() => { - initVorgaenge([vorgangWithNoWiedervorlagen, vorgangWithWiedervorlageFristToday, vorgangWithWiedervorlageInThePast, vorgangWithWiedervorlageInFuture]); - - initVorgangAttachedItem([wiedervorlageFristToday, wiedervorlageFristInThePast, wiedervorlageFristInTheFuture]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('on vorgang with no wiedervorlagen', () => { - - it('should not show next frist icon', () => { - const item: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangWithNoWiedervorlagen.name); - - notExist(item.getWiedervorlageNextFrist()); - }) - }) - - describe('on vorgang with existing wiedervorlagen', () => { - - it('should show next frist in future and list', () => { - const vorgang: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangWithWiedervorlageInFuture.name); - - notContainClass(vorgang.getWiedervorlageNextFrist(), 'red'); - exist(vorgang.getWiedervorlageNextFrist()); - }) - - it('should show next frist in the past and list', () => { - const vorgang: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangWithWiedervorlageInThePast.name); - - containClass(vorgang.getWiedervorlageNextFrist(), 'red'); - exist(vorgang.getWiedervorlageNextFrist()); - }) - }) + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangWithNoWiedervorlagen: VorgangE2E = { ...createVorgang(), name: 'NoWiedervorlagen' }; + + const vorgangWithWiedervorlageFristToday: VorgangE2E = { + ...buildVorgang(objectIds[0], 'FristToday'), + clientAttributes: createAlfaClientAttributes( + ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, + createNextWiedervorlageFristClientAttribute(createDateToday()), + ), + }; + const wiedervorlageFristToday: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[1], vorgangWithWiedervorlageFristToday._id.$oid), + item: { ...createWiedervorlageItem('WiedervorlageFristToday'), frist: createDateToday() }, + }; + + const vorgangWithWiedervorlageInThePast: VorgangE2E = { + ...buildVorgang(objectIds[2], 'FristInThePast'), + clientAttributes: createAlfaClientAttributes( + ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, + createNextWiedervorlageFristClientAttribute(createDateInThePast()), + ), + }; + const wiedervorlageFristInThePast: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[3], vorgangWithWiedervorlageInThePast._id.$oid), + item: { + ...createWiedervorlageItem('WiedervorlageFristInThePast'), + frist: createDateInThePast(), + }, + }; + + const vorgangWithWiedervorlageInFuture: VorgangE2E = { + ...buildVorgang(objectIds[4], 'FristInTheFuture'), + clientAttributes: createAlfaClientAttributes( + ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, + createNextWiedervorlageFristClientAttribute(createDateInTheFuture()), + ), + }; + const wiedervorlageFristInTheFuture: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[5], vorgangWithWiedervorlageInFuture._id.$oid), + item: { + ...createWiedervorlageItem('WiedervorlageFristInTheFuture'), + frist: createDateInTheFuture(), + }, + }; + + before(() => { + initVorgaenge([ + vorgangWithNoWiedervorlagen, + vorgangWithWiedervorlageFristToday, + vorgangWithWiedervorlageInThePast, + vorgangWithWiedervorlageInFuture, + ]); + + initVorgangAttachedItem([ + wiedervorlageFristToday, + wiedervorlageFristInThePast, + wiedervorlageFristInTheFuture, + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('on vorgang with no wiedervorlagen', () => { + it('should not show next frist icon', () => { + const item: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangWithNoWiedervorlagen.name, + ); + + notExist(item.getWiedervorlageNextFrist()); + }); + }); + + describe('on vorgang with existing wiedervorlagen', () => { + it('should show next frist in future and list', () => { + const vorgang: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangWithWiedervorlageInFuture.name, + ); + + notContainClass(vorgang.getWiedervorlageNextFrist(), 'red'); + exist(vorgang.getWiedervorlageNextFrist()); + }); + + it('should show next frist in the past and list', () => { + const vorgang: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangWithWiedervorlageInThePast.name, + ); + + containClass(vorgang.getWiedervorlageNextFrist(), 'red'); + exist(vorgang.getWiedervorlageNextFrist()); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-pages.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-pages.cy.ts index d01a77c315ba196c6c5392b93016066211ff9808..e8af185fe27ffa1762708e4ba5205bc47746b5f0 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-pages.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-pages.cy.ts @@ -26,180 +26,226 @@ import { MainPage, waitForSpinnerToDisappear } from 'apps/alfa-e2e/src/page-obje import { Interception } from 'cypress/types/net-stubbing'; import { HttpMethodE2E } from '../../../model/util'; import { VorgangE2E, VorgangStatusE2E } from '../../../model/vorgang'; -import { dropCollections, intercept, scrollToWindowBottom, waitOfInterceptor } from '../../../support/cypress-helper'; +import { + dropCollections, + intercept, + scrollToWindowBottom, + waitOfInterceptor, +} from '../../../support/cypress-helper'; import { generateIds } from '../../../support/tech.util'; -import { getUserManagerUserSabine, getUserSabineInternalId, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; +import { + getUserManagerUserSabine, + getUserSabineInternalId, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; import { buildVorgang, initVorgaenge } from '../../../support/vorgang-util'; describe('VorgangList Pages', () => { - const mainPage: MainPage = new MainPage(); - - const navigation: NavigationE2EComponent = mainPage.getNavigation(); - - const PAGE_SIZE: number = 100; - const assignedTo: string = getUserSabineInternalId(); - - before(() => { - const vorgaenge: VorgangE2E[] = - createVorgaengeWithStatus(VorgangStatusE2E.NEU).concat( - createVorgaengeWithStatusAndAssignedTo(VorgangStatusE2E.NEU), - createVorgaengeWithStatus(VorgangStatusE2E.ANGENOMMEN), - createVorgaengeWithStatusAndAssignedTo(VorgangStatusE2E.ANGENOMMEN) - ); - initVorgaenge(vorgaenge); - initUsermanagerUsers([getUserManagerUserSabine()]); - - loginAsSabine(); - }) - - after(() => { - dropCollections(); - }) - - describe('VorgangList', () => { - - describe('with Alle Filter', () => { - - describe('1 page (NEU)', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangPageLink(1)).as(loadPageInterceptor); - }) - - it('should show 1 page with 100 vorgaenge NEU', () => { - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name === 'VorgangNEU_1'); - assert(interception.response.body._embedded.vorgangHeaderList[99].name === 'VorgangNEU_' + PAGE_SIZE); - }) - }) - }) - - describe('2 page (NEU, ASSIGNED)', () => { - const loadNextPageInterceptor: string = 'loadNextPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangPageLink(2)).as(loadNextPageInterceptor); - }) - - it('should show 2 page with 100 vorgaenge NEU ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadNextPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name === 'VorgangNEUAssigned_1'); - assert(interception.response.body._embedded.vorgangHeaderList[99].name === 'VorgangNEUAssigned_' + PAGE_SIZE); - }) - waitForSpinnerToDisappear(); - }) - }) - - describe('3 page (ANGENOMMEN)', () => { - const loadNextPageInterceptor: string = 'loadNextPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangPageLink(3)).as(loadNextPageInterceptor); - }) - - it('should show 2 page with 100 vorgaenge ANGENOMMEN on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadNextPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name === 'VorgangANGENOMMEN_1'); - assert(interception.response.body._embedded.vorgangHeaderList[99].name === 'VorgangANGENOMMEN_' + PAGE_SIZE); - }) - waitForSpinnerToDisappear(); - }) - }) - - describe('4 page (ANGENOMMEN, ASSIGNED)', () => { - const loadNextPageInterceptor: string = 'loadNextPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangPageLink(4)).as(loadNextPageInterceptor); - }) - - it('should show 3 page with 100 vorgaenge ANGENOMMEN ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadNextPageInterceptor).then((interception: Interception) => { - scrollToWindowBottom(); - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name === 'VorgangANGENOMMENAssigned_1'); - assert(interception.response.body._embedded.vorgangHeaderList[99].name === 'VorgangANGENOMMENAssigned_' + PAGE_SIZE); - }) - }) - }) - - function buildVorgangPageLink(page: number): string { - return `*/vorgangs?page=${page - 1}&limit=${PAGE_SIZE}`; - } - }) - - describe('with MeineVorgaenge Filter', () => { - - describe('1 page (NEU ASSIGNED)', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangPageLink(1)).as(loadPageInterceptor); - }) - - it('should show 1 page with 100 vorgaenge NEU ASSIGNED', () => { - navigation.getMeineVorgaengeFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name === 'VorgangNEUAssigned_1'); - assert(interception.response.body._embedded.vorgangHeaderList[99].name === 'VorgangNEUAssigned_' + PAGE_SIZE); - }) - }) - }) - - describe('2 page (ANGENOMMEN, ASSIGNED)', () => { - const loadNextPageInterceptor: string = 'loadNextPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangPageLink(2)).as(loadNextPageInterceptor); - }) - - it('should show 2 page with 100 vorgaenge ANGENOMMEN ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadNextPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name === 'VorgangANGENOMMENAssigned_1'); - assert(interception.response.body._embedded.vorgangHeaderList[99].name === 'VorgangANGENOMMENAssigned_' + PAGE_SIZE); - }) - waitForSpinnerToDisappear(); - }) - }) - - function buildVorgangPageLink(page: number): string { - return `*/vorgangs?page=${page - 1}&limit=${PAGE_SIZE}&assignedTo=${assignedTo}`; - } - }) - }) - - function createVorgaengeWithStatus(status: VorgangStatusE2E): VorgangE2E[] { - let count = 1; - return generateIds(100).map(randomId => { - const vorgang: VorgangE2E = {...buildVorgang(randomId, 'Vorgang' + status + '_' + count), status }; - count++; - return vorgang; - }) - } - - function createVorgaengeWithStatusAndAssignedTo(status: VorgangStatusE2E): VorgangE2E[] { - let count = 1; - return generateIds(100).map(randomId => { - const vorgang: VorgangE2E = { ...buildVorgang(randomId, 'Vorgang' + status + 'Assigned_' + count), status, assignedTo }; - count++; - return vorgang; - }) - } -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + + const navigation: NavigationE2EComponent = mainPage.getNavigation(); + + const PAGE_SIZE: number = 100; + const assignedTo: string = getUserSabineInternalId(); + + before(() => { + const vorgaenge: VorgangE2E[] = createVorgaengeWithStatus(VorgangStatusE2E.NEU).concat( + createVorgaengeWithStatusAndAssignedTo(VorgangStatusE2E.NEU), + createVorgaengeWithStatus(VorgangStatusE2E.ANGENOMMEN), + createVorgaengeWithStatusAndAssignedTo(VorgangStatusE2E.ANGENOMMEN), + ); + initVorgaenge(vorgaenge); + initUsermanagerUsers([getUserManagerUserSabine()]); + + loginAsSabine(); + }); + + after(() => { + dropCollections(); + }); + + describe('VorgangList', () => { + describe('with Alle Filter', () => { + describe('1 page (NEU)', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangPageLink(1)).as(loadPageInterceptor); + }); + + it('should show 1 page with 100 vorgaenge NEU', () => { + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name === 'VorgangNEU_1', + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name === + 'VorgangNEU_' + PAGE_SIZE, + ); + }); + }); + }); + + describe('2 page (NEU, ASSIGNED)', () => { + const loadNextPageInterceptor: string = 'loadNextPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangPageLink(2)).as(loadNextPageInterceptor); + }); + + it('should show 2 page with 100 vorgaenge NEU ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadNextPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name === + 'VorgangNEUAssigned_1', + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name === + 'VorgangNEUAssigned_' + PAGE_SIZE, + ); + }); + waitForSpinnerToDisappear(); + }); + }); + + describe('3 page (ANGENOMMEN)', () => { + const loadNextPageInterceptor: string = 'loadNextPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangPageLink(3)).as(loadNextPageInterceptor); + }); + + it('should show 2 page with 100 vorgaenge ANGENOMMEN on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadNextPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name === + 'VorgangANGENOMMEN_1', + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name === + 'VorgangANGENOMMEN_' + PAGE_SIZE, + ); + }); + waitForSpinnerToDisappear(); + }); + }); + + describe('4 page (ANGENOMMEN, ASSIGNED)', () => { + const loadNextPageInterceptor: string = 'loadNextPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangPageLink(4)).as(loadNextPageInterceptor); + }); + + it('should show 3 page with 100 vorgaenge ANGENOMMEN ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadNextPageInterceptor).then((interception: Interception) => { + scrollToWindowBottom(); + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name === + 'VorgangANGENOMMENAssigned_1', + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name === + 'VorgangANGENOMMENAssigned_' + PAGE_SIZE, + ); + }); + }); + }); + + function buildVorgangPageLink(page: number): string { + return `*/vorgangs?page=${page - 1}&limit=${PAGE_SIZE}`; + } + }); + + describe('with MeineVorgaenge Filter', () => { + describe('1 page (NEU ASSIGNED)', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangPageLink(1)).as(loadPageInterceptor); + }); + + it('should show 1 page with 100 vorgaenge NEU ASSIGNED', () => { + navigation.getMeineVorgaengeFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name === + 'VorgangNEUAssigned_1', + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name === + 'VorgangNEUAssigned_' + PAGE_SIZE, + ); + }); + }); + }); + + describe('2 page (ANGENOMMEN, ASSIGNED)', () => { + const loadNextPageInterceptor: string = 'loadNextPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangPageLink(2)).as(loadNextPageInterceptor); + }); + + it('should show 2 page with 100 vorgaenge ANGENOMMEN ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadNextPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name === + 'VorgangANGENOMMENAssigned_1', + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name === + 'VorgangANGENOMMENAssigned_' + PAGE_SIZE, + ); + }); + waitForSpinnerToDisappear(); + }); + }); + + function buildVorgangPageLink(page: number): string { + return `*/vorgangs?page=${page - 1}&limit=${PAGE_SIZE}&assignedTo=${assignedTo}`; + } + }); + }); + + function createVorgaengeWithStatus(status: VorgangStatusE2E): VorgangE2E[] { + let count = 1; + return generateIds(100).map((randomId) => { + const vorgang: VorgangE2E = { + ...buildVorgang(randomId, 'Vorgang' + status + '_' + count), + status, + }; + count++; + return vorgang; + }); + } + + function createVorgaengeWithStatusAndAssignedTo(status: VorgangStatusE2E): VorgangE2E[] { + let count = 1; + return generateIds(100).map((randomId) => { + const vorgang: VorgangE2E = { + ...buildVorgang(randomId, 'Vorgang' + status + 'Assigned_' + count), + status, + assignedTo, + }; + count++; + return vorgang; + }); + } +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-pagination.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-pagination.cy.ts index c31333b4febeb81b0ff70a83e923ef13f2301213..06eaa38b8f9546aa5bffe78fff9351cb03b68002 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-pagination.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-pagination.cy.ts @@ -25,72 +25,79 @@ import { VorgangE2E } from 'apps/alfa-e2e/src/model/vorgang'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { HttpMethodE2E } from '../../../model/util'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; -import { dropCollections, dropSearchIndex, intercept, scrollToWindowBottom, waitOfInterceptor } from '../../../support/cypress-helper'; +import { + dropCollections, + dropSearchIndex, + intercept, + scrollToWindowBottom, + waitOfInterceptor, +} from '../../../support/cypress-helper'; import { enterWith, exist } from '../../../support/cypress.util'; import { generateIds } from '../../../support/tech.util'; import { loginAsSabine } from '../../../support/user-util'; import { buildVorgang, initSearchIndex, initVorgaenge } from '../../../support/vorgang-util'; describe.skip('VorgangList: search and pagination', () => { + const mainPage: MainPage = new MainPage(); - const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const NUMBER_OF_VORGAENGE: number = 250; + const PAGE_SIZE: number = 100; + const vorgaenge: VorgangE2E[] = generateIds(NUMBER_OF_VORGAENGE).map((id: string, i: number) => ({ + ...buildVorgang(id, `Vorgang_${i + 1}`), + nummer: `Vorgang_${i + 1}`, + })); - const NUMBER_OF_VORGAENGE: number = 250; - const PAGE_SIZE: number = 100; - const vorgaenge: VorgangE2E[] = generateIds(NUMBER_OF_VORGAENGE).map((id: string, i: number) => ({ ...buildVorgang(id, `Vorgang_${i + 1}`), nummer: `Vorgang_${i + 1}`})); + before(() => { + initVorgaenge(vorgaenge); + initSearchIndex(vorgaenge); - before(() => { - initVorgaenge(vorgaenge); - initSearchIndex(vorgaenge); + loginAsSabine(); + }); - loginAsSabine(); - }); + after(() => { + dropCollections(); + dropSearchIndex(); + }); - after(() => { - dropCollections(); - dropSearchIndex(); - }) + describe('open Vorgang list', () => { + const SEARCH_BY: string = 'Vorgang'; - describe('open Vorgang list', () => { + it('should open Vorgang list', () => { + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - const SEARCH_BY: string = 'Vorgang'; + it('should search for Vorgänge', () => { + enterWith(mainPage.getHeader().getVorgangSearch().getInput(), SEARCH_BY); + waitForSpinnerToDisappear(); + }); - it('should open Vorgang list', () => { - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }); + it('should load Vorgang from second page', () => { + const loadSecondPageIterceptor: string = 'loadSecondPage'; + intercept(HttpMethodE2E.GET, buildVorgangPageLink(2, SEARCH_BY)).as(loadSecondPageIterceptor); - it('should search for Vorgänge', () => { - enterWith(mainPage.getHeader().getVorgangSearch().getInput(), SEARCH_BY); - waitForSpinnerToDisappear(); - }); + scrollToWindowBottom(); - it('should load Vorgang from second page', () => { - const loadSecondPageIterceptor: string = 'loadSecondPage'; - intercept(HttpMethodE2E.GET, buildVorgangPageLink(2, SEARCH_BY)).as(loadSecondPageIterceptor); + waitOfInterceptor(loadSecondPageIterceptor).then(() => { + exist(vorgangList.getListItem('Vorgang_110').getRoot()); + }); + }); - scrollToWindowBottom(); + it('should load Vorgang from third page', () => { + const loadThirdPageIterceptor: string = 'loadThirdPage'; + intercept(HttpMethodE2E.GET, buildVorgangPageLink(3, SEARCH_BY)).as(loadThirdPageIterceptor); - waitOfInterceptor(loadSecondPageIterceptor).then(() => { - exist(vorgangList.getListItem('Vorgang_110').getRoot()); - }); - }) + scrollToWindowBottom(); - it('should load Vorgang from third page', () => { - const loadThirdPageIterceptor: string = 'loadThirdPage'; - intercept(HttpMethodE2E.GET, buildVorgangPageLink(3, SEARCH_BY)).as(loadThirdPageIterceptor); + waitOfInterceptor(loadThirdPageIterceptor).then(() => { + exist(vorgangList.getListItem('Vorgang_250').getRoot()); + }); + }); + }); - scrollToWindowBottom(); - - waitOfInterceptor(loadThirdPageIterceptor).then(() => { - exist(vorgangList.getListItem('Vorgang_250').getRoot()); - }); - }); - }); - - function buildVorgangPageLink(page: number, searchBy: string): string { - return `*/vorgangs?page=${page - 1}&limit=${PAGE_SIZE}&searchBy=${searchBy}`; - } -}) \ No newline at end of file + function buildVorgangPageLink(page: number, searchBy: string): string { + return `*/vorgangs?page=${page - 1}&limit=${PAGE_SIZE}&searchBy=${searchBy}`; + } +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-views-pages.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-views-pages.cy.ts index ca9ed1364d607869f97ce1b916547aed1c99069a..2ac1cd3a5d4c12275f3efba49096b8b09640a885 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-views-pages.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list-views-pages.cy.ts @@ -29,1038 +29,1293 @@ import { exist } from 'apps/alfa-e2e/src/support/cypress.util'; import { Interception } from 'cypress/types/net-stubbing'; import { HttpMethodE2E } from '../../../model/util'; import { VorgangE2E, VorgangStatusE2E } from '../../../model/vorgang'; -import { dropCollections, intercept, scrollToWindowBottom, waitOfInterceptor } from '../../../support/cypress-helper'; +import { + dropCollections, + intercept, + scrollToWindowBottom, + waitOfInterceptor, +} from '../../../support/cypress-helper'; import { generateIds } from '../../../support/tech.util'; -import { getUserManagerUserSabine, getUserSabineInternalId, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; +import { + getUserManagerUserSabine, + getUserSabineInternalId, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; import { buildVorgang, initVorgaenge } from '../../../support/vorgang-util'; describe('VorgangList View Pages', () => { - const mainPage: MainPage = new MainPage(); - - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const navigation: NavigationE2EComponent = mainPage.getNavigation(); - - const views: VorgangViewsE2EComponent = mainPage.getViews(); - - const PAGE_SIZE: number = 100; - const assignedTo: string = getUserSabineInternalId(); - - before(() => { - const vorgaenge: VorgangE2E[] = - createVorgaengeWithStatus(VorgangStatusE2E.NEU).concat( - createAssignedVorgaengeWithStatus(VorgangStatusE2E.NEU), - createVorgaengeWithStatus(VorgangStatusE2E.ANGENOMMEN), - createAssignedVorgaengeWithStatus(VorgangStatusE2E.ANGENOMMEN), - createVorgaengeWithStatus(VorgangStatusE2E.IN_BEARBEITUNG), - createAssignedVorgaengeWithStatus(VorgangStatusE2E.IN_BEARBEITUNG), - createVorgaengeWithStatus(VorgangStatusE2E.BESCHIEDEN), - createAssignedVorgaengeWithStatus(VorgangStatusE2E.BESCHIEDEN), - createVorgaengeWithStatus(VorgangStatusE2E.ABGESCHLOSSEN), - createAssignedVorgaengeWithStatus(VorgangStatusE2E.ABGESCHLOSSEN), - createVorgaengeWithStatus(VorgangStatusE2E.VERWORFEN), - createAssignedVorgaengeWithStatus(VorgangStatusE2E.VERWORFEN)); - initVorgaenge(vorgaenge); - initUsermanagerUsers([getUserManagerUserSabine()]); - - loginAsSabine(); - exist(vorgangList.getRoot()); - waitForSpinnerToDisappear(); - }) - - after(() => { - dropCollections(); - }) - - describe('Neu', () => { - - const ALLE_NAME_PREFIX: string = 'VorgangNEU_'; - const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangNEUAssigned_'; - - describe('Alle filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangNeuPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge NEU', () => { - views.getNeu().getRoot().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangNeuPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge NEU and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 3', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangNeuPageLink(3)).as(loadPageInterceptor); - }) - - it('should show page 3 with 10 vorgaenge NEU ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 20); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 80); - assert(interception.response.body._embedded.vorgangHeaderList[19].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - function buildVorgangNeuPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&status=NEU`; - } - }) - - describe('Meine Vorgänge filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangNeuAssignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge NEU', () => { - navigation.getMeineVorgaengeFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangNeuAssignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge NEU and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, MEINE_VORGAENGE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangNeuAssignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=NEU`; - } - }) - - describe('Nicht zugewiesen filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangUnassignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge NEU', () => { - navigation.getNichtZugewiesenFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangUnassignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, ALLE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangUnassignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=&status=NEU`; - } - }) - }) - - describe('Angenommen', () => { - - const ALLE_NAME_PREFIX: string = 'VorgangANGENOMMEN_'; - const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangANGENOMMENAssigned_'; - - describe('Alle filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - navigation.getAlleFilter().click(); - waitForSpinnerToDisappear(); - intercept(HttpMethodE2E.GET, buildVorgangAngenommenPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge ANGENOMMEN', () => { - views.getAngenommen().getRoot().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangAngenommenPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge ANGENOMMEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 3', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangAngenommenPageLink(3)).as(loadPageInterceptor); - }) - - it('should show page 3 with 10 vorgaenge ANGENOMMEN ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 20); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 80); - assert(interception.response.body._embedded.vorgangHeaderList[19].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - function buildVorgangAngenommenPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&status=ANGENOMMEN`; - } - }) - - describe('Meine Vorgänge filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangAngenommenAssignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge ANGENOMMEN', () => { - navigation.getMeineVorgaengeFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangAngenommenAssignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge ANGENOMMEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, MEINE_VORGAENGE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangAngenommenAssignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=ANGENOMMEN`; - } - }) - - describe('Nicht zugewiesen filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangAngenommenUnassignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge ANGENOMMEN', () => { - navigation.getNichtZugewiesenFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangAngenommenUnassignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, ALLE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangAngenommenUnassignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=&status=ANGENOMMEN`; - } - }) - }) - - describe('In Bearbeitung', () => { - - const ALLE_NAME_PREFIX: string = 'VorgangIN_BEARBEITUNG_'; - const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangIN_BEARBEITUNGAssigned_'; - - describe('Alle filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - navigation.getAlleFilter().click(); - waitForSpinnerToDisappear(); - intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge IN_BEARBEITUNG', () => { - views.getInBearbeitung().getRoot().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge IN_BEARBEITUNG and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 3', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungPageLink(3)).as(loadPageInterceptor); - }) - - it('should show page 3 with 10 vorgaenge IN_BEARBEITUNG ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 20); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 80); - assert(interception.response.body._embedded.vorgangHeaderList[19].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - function buildVorgangInBearbeitungPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&status=IN_BEARBEITUNG`; - } - }) - - describe('Meine Vorgänge filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungAssignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge IN_BEARBEITUNG', () => { - navigation.getMeineVorgaengeFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungAssignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge IN_BEARBEITUNG and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, MEINE_VORGAENGE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangInBearbeitungAssignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=IN_BEARBEITUNG`; - } - }) - - describe('Nicht zugewiesen filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungUnassignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge IN_BEARBEITUNG', () => { - navigation.getNichtZugewiesenFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungUnassignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, ALLE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangInBearbeitungUnassignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=&status=IN_BEARBEITUNG`; - } - }) - }) - - describe('Beschieden', () => { - - const ALLE_NAME_PREFIX: string = 'VorgangBESCHIEDEN_'; - const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangBESCHIEDENAssigned_'; - - describe('Alle filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - navigation.getAlleFilter().click(); - waitForSpinnerToDisappear(); - intercept(HttpMethodE2E.GET, buildVorgangBeschiedenPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge BESCHIEDEN', () => { - views.getBeschieden().getRoot().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangBeschiedenPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge BESCHIEDEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 3', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangBeschiedenPageLink(3)).as(loadPageInterceptor); - }) - - it('should show page 3 with 10 vorgaenge BESCHIEDEN ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 20); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 80); - assert(interception.response.body._embedded.vorgangHeaderList[19].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - function buildVorgangBeschiedenPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&status=BESCHIEDEN`; - } - }) - - describe('Meine Vorgänge filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInBescheidenAssignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge BESCHIEDEN', () => { - navigation.getMeineVorgaengeFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInBescheidenAssignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge BESCHIEDEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, MEINE_VORGAENGE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangInBescheidenAssignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=BESCHIEDEN`; - } - }) - - describe('Nicht zugewiesen filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInBescheidenUnassignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge BESCHIEDEN', () => { - navigation.getNichtZugewiesenFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInBescheidenUnassignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, ALLE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangInBescheidenUnassignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=&status=BESCHIEDEN`; - } - }) - }) - - describe('Abgeschlossen', () => { - - const ALLE_NAME_PREFIX: string = 'VorgangABGESCHLOSSEN_'; - const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangABGESCHLOSSENAssigned_'; - - describe('Alle filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - navigation.getAlleFilter().click(); - waitForSpinnerToDisappear(); - intercept(HttpMethodE2E.GET, buildVorgangAbgeschlossenPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge ABGESCHLOSSEN', () => { - views.getAbgeschlossen().getRoot().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangAbgeschlossenPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge ABGESCHLOSSEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 3', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangAbgeschlossenPageLink(3)).as(loadPageInterceptor); - }) - - it('should show page 3 with 10 vorgaenge ABGESCHLOSSEN ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 20); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 80); - assert(interception.response.body._embedded.vorgangHeaderList[19].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - function buildVorgangAbgeschlossenPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&status=ABGESCHLOSSEN`; - } - }) - - describe('Meine Vorgänge filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInAbgeschlossenAssignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge ABGESCHLOSSEN', () => { - navigation.getMeineVorgaengeFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInAbgeschlossenAssignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge ABGESCHLOSSEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, MEINE_VORGAENGE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangInAbgeschlossenAssignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=ABGESCHLOSSEN`; - } - }) - - describe('Nicht zugewiesen filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInAbgeschlossenUnassignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge ABGESCHLOSSEN', () => { - navigation.getNichtZugewiesenFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInAbgeschlossenUnassignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, MEINE_VORGAENGE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangInAbgeschlossenUnassignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=&status=ABGESCHLOSSEN`; - } - }) - }) - - describe('Verworfen', () => { - - const ALLE_NAME_PREFIX: string = 'VorgangVERWORFEN_'; - const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangVERWORFENAssigned_'; - - describe('Alle filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - navigation.getAlleFilter().click(); - waitForSpinnerToDisappear(); - intercept(HttpMethodE2E.GET, buildVorgangVerworfenPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge VERWORFEN', () => { - views.getVerworfen().getRoot().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangVerworfenPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge VERWORFEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 3', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangVerworfenPageLink(3)).as(loadPageInterceptor); - }) - - it('should show page 3 with 10 vorgaenge VERWORFEN ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 20); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 80); - assert(interception.response.body._embedded.vorgangHeaderList[19].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - function buildVorgangVerworfenPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&status=VERWORFEN`; - } - }) - - describe('Meine Vorgänge filter', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInVerworfenAssignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge VERWORFEN', () => { - navigation.getMeineVorgaengeFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInVerworfenAssignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge VERWORFEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, MEINE_VORGAENGE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangInVerworfenAssignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=VERWORFEN`; - } - }) - - describe('Nicht zugewiesen', () => { - - describe('page 1', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInVerworfenUnassignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show page 1 with 100 vorgaenge VERWORFEN', () => { - navigation.getNichtZugewiesenFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME_PREFIX + PAGE_SIZE); - }) - }) - }) - - describe('page 2', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangInVerworfenUnassignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME_PREFIX + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, ALLE_NAME_PREFIX + 110); - }) - }) - }) - - function buildVorgangInVerworfenUnassignedPageLink(page: number): string { - return `${buildVorgangPageLink(page)}&assignedTo=&status=VERWORFEN`; - } - }) - }) - - function createVorgaengeWithStatus(status: VorgangStatusE2E): VorgangE2E[] { - let count = 1; - return generateIds(110).map(randomId => { - const vorgang: VorgangE2E = { ...buildVorgang(randomId, 'Vorgang' + status + '_' + count), status }; - count++; - return vorgang; - }) - } - - function createAssignedVorgaengeWithStatus(status: VorgangStatusE2E): VorgangE2E[] { - let count = 1; - return generateIds(110).map(randomId => { - const vorgang: VorgangE2E = { ...buildVorgang(randomId, 'Vorgang' + status + 'Assigned_' + count), status, assignedTo }; - count++; - return vorgang; - }) - } - - function buildVorgangPageLink(page: number): string { - return `vorgangs?page=${page - 1}&limit=100`; - } -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const navigation: NavigationE2EComponent = mainPage.getNavigation(); + + const views: VorgangViewsE2EComponent = mainPage.getViews(); + + const PAGE_SIZE: number = 100; + const assignedTo: string = getUserSabineInternalId(); + + before(() => { + const vorgaenge: VorgangE2E[] = createVorgaengeWithStatus(VorgangStatusE2E.NEU).concat( + createAssignedVorgaengeWithStatus(VorgangStatusE2E.NEU), + createVorgaengeWithStatus(VorgangStatusE2E.ANGENOMMEN), + createAssignedVorgaengeWithStatus(VorgangStatusE2E.ANGENOMMEN), + createVorgaengeWithStatus(VorgangStatusE2E.IN_BEARBEITUNG), + createAssignedVorgaengeWithStatus(VorgangStatusE2E.IN_BEARBEITUNG), + createVorgaengeWithStatus(VorgangStatusE2E.BESCHIEDEN), + createAssignedVorgaengeWithStatus(VorgangStatusE2E.BESCHIEDEN), + createVorgaengeWithStatus(VorgangStatusE2E.ABGESCHLOSSEN), + createAssignedVorgaengeWithStatus(VorgangStatusE2E.ABGESCHLOSSEN), + createVorgaengeWithStatus(VorgangStatusE2E.VERWORFEN), + createAssignedVorgaengeWithStatus(VorgangStatusE2E.VERWORFEN), + ); + initVorgaenge(vorgaenge); + initUsermanagerUsers([getUserManagerUserSabine()]); + + loginAsSabine(); + exist(vorgangList.getRoot()); + waitForSpinnerToDisappear(); + }); + + after(() => { + dropCollections(); + }); + + describe('Neu', () => { + const ALLE_NAME_PREFIX: string = 'VorgangNEU_'; + const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangNEUAssigned_'; + + describe('Alle filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangNeuPageLink(1)).as(loadPageInterceptor); + }); + + it('should show page 1 with 100 vorgaenge NEU', () => { + views.getNeu().getRoot().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangNeuPageLink(2)).as(loadPageInterceptor); + }); + + it('should show page 2 with 10 vorgaenge NEU and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 3', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangNeuPageLink(3)).as(loadPageInterceptor); + }); + + it('should show page 3 with 10 vorgaenge NEU ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 20); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 80, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[19].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + function buildVorgangNeuPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&status=NEU`; + } + }); + + describe('Meine Vorgänge filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangNeuAssignedPageLink(1)).as(loadPageInterceptor); + }); + + it('should show page 1 with 100 vorgaenge NEU', () => { + navigation.getMeineVorgaengeFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangNeuAssignedPageLink(2)).as(loadPageInterceptor); + }); + + it('should show page 2 with 10 vorgaenge NEU and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + MEINE_VORGAENGE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangNeuAssignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=NEU`; + } + }); + + describe('Nicht zugewiesen filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangUnassignedPageLink(1)).as(loadPageInterceptor); + }); + + it('should show page 1 with 100 vorgaenge NEU', () => { + navigation.getNichtZugewiesenFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangUnassignedPageLink(2)).as(loadPageInterceptor); + }); + + it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + ALLE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangUnassignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=&status=NEU`; + } + }); + }); + + describe('Angenommen', () => { + const ALLE_NAME_PREFIX: string = 'VorgangANGENOMMEN_'; + const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangANGENOMMENAssigned_'; + + describe('Alle filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + navigation.getAlleFilter().click(); + waitForSpinnerToDisappear(); + intercept(HttpMethodE2E.GET, buildVorgangAngenommenPageLink(1)).as(loadPageInterceptor); + }); + + it('should show page 1 with 100 vorgaenge ANGENOMMEN', () => { + views.getAngenommen().getRoot().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangAngenommenPageLink(2)).as(loadPageInterceptor); + }); + + it('should show page 2 with 10 vorgaenge ANGENOMMEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 3', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangAngenommenPageLink(3)).as(loadPageInterceptor); + }); + + it('should show page 3 with 10 vorgaenge ANGENOMMEN ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 20); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 80, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[19].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + function buildVorgangAngenommenPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&status=ANGENOMMEN`; + } + }); + + describe('Meine Vorgänge filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangAngenommenAssignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge ANGENOMMEN', () => { + navigation.getMeineVorgaengeFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangAngenommenAssignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge ANGENOMMEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + MEINE_VORGAENGE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangAngenommenAssignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=ANGENOMMEN`; + } + }); + + describe('Nicht zugewiesen filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangAngenommenUnassignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge ANGENOMMEN', () => { + navigation.getNichtZugewiesenFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangAngenommenUnassignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + ALLE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangAngenommenUnassignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=&status=ANGENOMMEN`; + } + }); + }); + + describe('In Bearbeitung', () => { + const ALLE_NAME_PREFIX: string = 'VorgangIN_BEARBEITUNG_'; + const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangIN_BEARBEITUNGAssigned_'; + + describe('Alle filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + navigation.getAlleFilter().click(); + waitForSpinnerToDisappear(); + intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge IN_BEARBEITUNG', () => { + views.getInBearbeitung().getRoot().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge IN_BEARBEITUNG and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 3', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungPageLink(3)).as( + loadPageInterceptor, + ); + }); + + it('should show page 3 with 10 vorgaenge IN_BEARBEITUNG ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 20); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 80, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[19].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + function buildVorgangInBearbeitungPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&status=IN_BEARBEITUNG`; + } + }); + + describe('Meine Vorgänge filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungAssignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge IN_BEARBEITUNG', () => { + navigation.getMeineVorgaengeFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungAssignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge IN_BEARBEITUNG and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + MEINE_VORGAENGE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangInBearbeitungAssignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=IN_BEARBEITUNG`; + } + }); + + describe('Nicht zugewiesen filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungUnassignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge IN_BEARBEITUNG', () => { + navigation.getNichtZugewiesenFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInBearbeitungUnassignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + ALLE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangInBearbeitungUnassignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=&status=IN_BEARBEITUNG`; + } + }); + }); + + describe('Beschieden', () => { + const ALLE_NAME_PREFIX: string = 'VorgangBESCHIEDEN_'; + const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangBESCHIEDENAssigned_'; + + describe('Alle filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + navigation.getAlleFilter().click(); + waitForSpinnerToDisappear(); + intercept(HttpMethodE2E.GET, buildVorgangBeschiedenPageLink(1)).as(loadPageInterceptor); + }); + + it('should show page 1 with 100 vorgaenge BESCHIEDEN', () => { + views.getBeschieden().getRoot().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangBeschiedenPageLink(2)).as(loadPageInterceptor); + }); + + it('should show page 2 with 10 vorgaenge BESCHIEDEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 3', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangBeschiedenPageLink(3)).as(loadPageInterceptor); + }); + + it('should show page 3 with 10 vorgaenge BESCHIEDEN ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 20); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 80, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[19].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + function buildVorgangBeschiedenPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&status=BESCHIEDEN`; + } + }); + + describe('Meine Vorgänge filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInBescheidenAssignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge BESCHIEDEN', () => { + navigation.getMeineVorgaengeFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInBescheidenAssignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge BESCHIEDEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + MEINE_VORGAENGE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangInBescheidenAssignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=BESCHIEDEN`; + } + }); + + describe('Nicht zugewiesen filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInBescheidenUnassignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge BESCHIEDEN', () => { + navigation.getNichtZugewiesenFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInBescheidenUnassignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + ALLE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangInBescheidenUnassignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=&status=BESCHIEDEN`; + } + }); + }); + + describe('Abgeschlossen', () => { + const ALLE_NAME_PREFIX: string = 'VorgangABGESCHLOSSEN_'; + const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangABGESCHLOSSENAssigned_'; + + describe('Alle filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + navigation.getAlleFilter().click(); + waitForSpinnerToDisappear(); + intercept(HttpMethodE2E.GET, buildVorgangAbgeschlossenPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge ABGESCHLOSSEN', () => { + views.getAbgeschlossen().getRoot().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangAbgeschlossenPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge ABGESCHLOSSEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 3', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangAbgeschlossenPageLink(3)).as( + loadPageInterceptor, + ); + }); + + it('should show page 3 with 10 vorgaenge ABGESCHLOSSEN ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 20); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 80, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[19].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + function buildVorgangAbgeschlossenPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&status=ABGESCHLOSSEN`; + } + }); + + describe('Meine Vorgänge filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInAbgeschlossenAssignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge ABGESCHLOSSEN', () => { + navigation.getMeineVorgaengeFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInAbgeschlossenAssignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge ABGESCHLOSSEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + MEINE_VORGAENGE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangInAbgeschlossenAssignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=ABGESCHLOSSEN`; + } + }); + + describe('Nicht zugewiesen filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInAbgeschlossenUnassignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge ABGESCHLOSSEN', () => { + navigation.getNichtZugewiesenFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInAbgeschlossenUnassignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + MEINE_VORGAENGE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangInAbgeschlossenUnassignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=&status=ABGESCHLOSSEN`; + } + }); + }); + + describe('Verworfen', () => { + const ALLE_NAME_PREFIX: string = 'VorgangVERWORFEN_'; + const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangVERWORFENAssigned_'; + + describe('Alle filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + navigation.getAlleFilter().click(); + waitForSpinnerToDisappear(); + intercept(HttpMethodE2E.GET, buildVorgangVerworfenPageLink(1)).as(loadPageInterceptor); + }); + + it('should show page 1 with 100 vorgaenge VERWORFEN', () => { + views.getVerworfen().getRoot().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangVerworfenPageLink(2)).as(loadPageInterceptor); + }); + + it('should show page 2 with 10 vorgaenge VERWORFEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 3', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangVerworfenPageLink(3)).as(loadPageInterceptor); + }); + + it('should show page 3 with 10 vorgaenge VERWORFEN ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 20); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 80, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[19].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + function buildVorgangVerworfenPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&status=VERWORFEN`; + } + }); + + describe('Meine Vorgänge filter', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInVerworfenAssignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge VERWORFEN', () => { + navigation.getMeineVorgaengeFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInVerworfenAssignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge VERWORFEN and 90 vorgaenge ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + MEINE_VORGAENGE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangInVerworfenAssignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=${assignedTo}&status=VERWORFEN`; + } + }); + + describe('Nicht zugewiesen', () => { + describe('page 1', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInVerworfenUnassignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show page 1 with 100 vorgaenge VERWORFEN', () => { + navigation.getNichtZugewiesenFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === PAGE_SIZE); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME_PREFIX + PAGE_SIZE, + ); + }); + }); + }); + + describe('page 2', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangInVerworfenUnassignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show page 2 with 10 vorgaenge on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + ALLE_NAME_PREFIX + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + ALLE_NAME_PREFIX + 110, + ); + }); + }); + }); + + function buildVorgangInVerworfenUnassignedPageLink(page: number): string { + return `${buildVorgangPageLink(page)}&assignedTo=&status=VERWORFEN`; + } + }); + }); + + function createVorgaengeWithStatus(status: VorgangStatusE2E): VorgangE2E[] { + let count = 1; + return generateIds(110).map((randomId) => { + const vorgang: VorgangE2E = { + ...buildVorgang(randomId, 'Vorgang' + status + '_' + count), + status, + }; + count++; + return vorgang; + }); + } + + function createAssignedVorgaengeWithStatus(status: VorgangStatusE2E): VorgangE2E[] { + let count = 1; + return generateIds(110).map((randomId) => { + const vorgang: VorgangE2E = { + ...buildVorgang(randomId, 'Vorgang' + status + 'Assigned_' + count), + status, + assignedTo, + }; + count++; + return vorgang; + }); + } + + function buildVorgangPageLink(page: number): string { + return `vorgangs?page=${page - 1}&limit=100`; + } +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.cy.ts index 9a8dc836b7940c4134c9426d906265025b3c9a8d..9045209a3166d3b2f6e2169862d744c0c4baee4e 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.cy.ts @@ -26,90 +26,110 @@ import { EingangE2E, VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { dropCollections } from '../../../support/cypress-helper'; import { exist, notExist } from '../../../support/cypress.util'; -import { ORGANISATIONSEINHEITEN_ID_FOR_KFINDER, ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } from '../../../support/data.util'; -import { loginAsKfinder, loginAsKordner, loginAsRichard, loginAsZonk } from '../../../support/user-util'; -import { buildVorgang, createVorgang, initVorgaenge, objectIds } from '../../../support/vorgang-util'; +import { + ORGANISATIONSEINHEITEN_ID_FOR_KFINDER, + ORGANISATIONSEINHEITEN_ID_FOR_KORDNER, +} from '../../../support/data.util'; +import { + loginAsKfinder, + loginAsKordner, + loginAsRichard, + loginAsZonk, +} from '../../../support/user-util'; +import { + buildVorgang, + createVorgang, + initVorgaenge, + objectIds, +} from '../../../support/vorgang-util'; describe('VorgangList', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const eingangForKFinder: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KFINDER } }; - const vorgangForKFinder: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangVisibleToKFinder'), eingangs: [eingangForKFinder] }; - - const eingangForKOrdner: EingangE2E = { ...createVorgang().eingangs[0], zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KORDNER } }; - const vorgangForKOrdner: VorgangE2E = { ...buildVorgang(objectIds[1], 'VorgangVisibleToKOrdner'), eingangs: [eingangForKOrdner] }; - - before(() => { - initVorgaenge([vorgangForKFinder, vorgangForKOrdner]); - }) - - after(() => { - dropCollections(); - }) - - describe('filtered/authorized', () => { - - describe('by user kfinder', () => { - - before(() => { - loginAsKfinder(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - it('should show authorized vorgaenge', () => { - exist(vorgangList.getListItem(vorgangForKFinder.name).getRoot()); - notExist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot()); - }) - }) - - describe('by user kordner', () => { - - before(() => { - loginAsKordner(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - it('should show authorized vorgaenge', () => { - exist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot()); - notExist(vorgangList.getListItem(vorgangForKFinder.name).getRoot()); - }) - }) - - describe('by user zonk', () => { - - const vorgang: VorgangE2E = createVorgang(); - - before(() => { - loginAsZonk(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - it('should show authorized empty vorgaenge', () => { - notExist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot()); - notExist(vorgangList.getListItem(vorgangForKFinder.name).getRoot()); - notExist(vorgangList.getListItem(vorgang.name).getRoot()); - }) - }) - - describe('by user richard', () => { - - before(() => { - loginAsRichard(); - - waitForSpinnerToDisappear(); - }) - - it('should show hint message while have no roles', () => { - notExist(vorgangList.getRoot()); - exist(vorgangList.getNoRoleMessage()); - }) - }) - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const eingangForKFinder: EingangE2E = { + ...createVorgang().eingangs[0], + zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KFINDER }, + }; + const vorgangForKFinder: VorgangE2E = { + ...buildVorgang(objectIds[0], 'VorgangVisibleToKFinder'), + eingangs: [eingangForKFinder], + }; + + const eingangForKOrdner: EingangE2E = { + ...createVorgang().eingangs[0], + zustaendigeStelle: { organisationseinheitenId: ORGANISATIONSEINHEITEN_ID_FOR_KORDNER }, + }; + const vorgangForKOrdner: VorgangE2E = { + ...buildVorgang(objectIds[1], 'VorgangVisibleToKOrdner'), + eingangs: [eingangForKOrdner], + }; + + before(() => { + initVorgaenge([vorgangForKFinder, vorgangForKOrdner]); + }); + + after(() => { + dropCollections(); + }); + + describe('filtered/authorized', () => { + describe('by user kfinder', () => { + before(() => { + loginAsKfinder(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + it('should show authorized vorgaenge', () => { + exist(vorgangList.getListItem(vorgangForKFinder.name).getRoot()); + notExist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot()); + }); + }); + + describe('by user kordner', () => { + before(() => { + loginAsKordner(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + it('should show authorized vorgaenge', () => { + exist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot()); + notExist(vorgangList.getListItem(vorgangForKFinder.name).getRoot()); + }); + }); + + describe('by user zonk', () => { + const vorgang: VorgangE2E = createVorgang(); + + before(() => { + loginAsZonk(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + it('should show authorized empty vorgaenge', () => { + notExist(vorgangList.getListItem(vorgangForKOrdner.name).getRoot()); + notExist(vorgangList.getListItem(vorgangForKFinder.name).getRoot()); + notExist(vorgangList.getListItem(vorgang.name).getRoot()); + }); + }); + + describe('by user richard', () => { + before(() => { + loginAsRichard(); + + waitForSpinnerToDisappear(); + }); + + it('should show hint message while have no roles', () => { + notExist(vorgangList.getRoot()); + exist(vorgangList.getNoRoleMessage()); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts index cde003f7648db8acb2ab860b0ca2d45029d7e433..04dfb66723a6281ccc3480a077fd97eaf9a43a58 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-list.search.cy.ts @@ -25,552 +25,692 @@ import { faker } from '@faker-js/faker'; import { VorgangDetailHeaderE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-detail-header.e2e.component'; import { VorgangListItemE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-item.e2e.component'; import { VorgangListE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-list.e2e.component'; -import { VorgangSearchE2EComponent, VorgangSearchPreviewListItemE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component'; +import { + VorgangSearchE2EComponent, + VorgangSearchPreviewListItemE2EComponent, +} from 'apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component'; import { UserE2E } from 'apps/alfa-e2e/src/model/user'; import { EingangE2E, VorgangE2E, VorgangStatusE2E } from 'apps/alfa-e2e/src/model/vorgang'; import { HeaderE2EComponent } from 'apps/alfa-e2e/src/page-objects/header.po'; import { VorgangPage } from 'apps/alfa-e2e/src/page-objects/vorgang.po'; import { dropCollections, dropSearchIndex } from 'apps/alfa-e2e/src/support/cypress-helper'; -import { AntragstellerE2ETestData, EingangE2ETestData, EingangHeaderE2ETestData, buildVorgang, createVorgang, initSearchIndex, initVorgaenge, objectIds } from 'apps/alfa-e2e/src/support/vorgang-util'; +import { + AntragstellerE2ETestData, + EingangE2ETestData, + EingangHeaderE2ETestData, + buildVorgang, + createVorgang, + initSearchIndex, + initVorgaenge, + objectIds, +} from 'apps/alfa-e2e/src/support/vorgang-util'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; -import { backspaceOn, enterWith, exist, haveText, haveValue, notExist } from '../../../support/cypress.util'; -import { UserRoleE2E, getUserManagerUserSabine, getUserSabine, getUserSabineInternalId, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; -import { DirectionE2E, PostfachMailItemE2E, PostfachNachrichtMessageCodeE2E, VorgangAttachedItemE2E } from 'apps/alfa-e2e/src/model/vorgang-attached-item'; +import { + backspaceOn, + enterWith, + exist, + haveText, + haveValue, + notExist, +} from '../../../support/cypress.util'; +import { + UserRoleE2E, + getUserManagerUserSabine, + getUserSabine, + getUserSabineInternalId, + initUsermanagerUsers, + loginAsSabine, +} from '../../../support/user-util'; +import { + DirectionE2E, + PostfachMailItemE2E, + PostfachNachrichtMessageCodeE2E, + VorgangAttachedItemE2E, +} from 'apps/alfa-e2e/src/model/vorgang-attached-item'; import { WiedervorlageE2E } from 'apps/alfa-e2e/src/model/wiedervorlage'; -import { createPostfachNachrichtAttachedItem, createPostfachNachrichtReplyItem, initVorgangAttachedItem } from 'apps/alfa-e2e/src/support/vorgang-attached-item-util'; -import { createWiedervorlageItem, createWiedervorlageAttachedItem } from 'apps/alfa-e2e/src/support/wiedervorlage-util'; +import { + createPostfachNachrichtAttachedItem, + createPostfachNachrichtReplyItem, + initVorgangAttachedItem, +} from 'apps/alfa-e2e/src/support/vorgang-attached-item-util'; +import { + createWiedervorlageItem, + createWiedervorlageAttachedItem, +} from 'apps/alfa-e2e/src/support/wiedervorlage-util'; import { KommentarE2E } from 'apps/alfa-e2e/src/model/kommentar'; -import { createKommentar, createKommentarAttachedItem } from 'apps/alfa-e2e/src/support/kommentar.util'; +import { + createKommentar, + createKommentarAttachedItem, +} from 'apps/alfa-e2e/src/support/kommentar.util'; import { WiedervorlageInVorgangE2EComponent } from 'apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-in-vorgang.e2e.component'; -import { KommentarInVorgangE2E, KommentareInVorgangE2EComponent } from 'apps/alfa-e2e/src/components/kommentar/kommentar-list.e2e.component'; +import { + KommentarInVorgangE2E, + KommentareInVorgangE2EComponent, +} from 'apps/alfa-e2e/src/components/kommentar/kommentar-list.e2e.component'; import { PostfachMailListItem } from 'apps/alfa-e2e/src/components/postfach/postfach-mail.e2e.component'; describe('VorgangList Suche', () => { - const mainPage: MainPage = new MainPage(); - - const header: HeaderE2EComponent = mainPage.getHeader(); - const vorgangSearch: VorgangSearchE2EComponent = header.getVorgangSearch(); - - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); - - describe.skip(`on user with role ${UserRoleE2E.VERWALTUNG_USER} by requestId/Eingangskennzeichen`, () => { - - const requestId: string = faker.datatype.uuid(); - const eingang: EingangE2E = { ...EingangE2ETestData, header: { ...EingangHeaderE2ETestData, requestId } } - const vorgangToStay: VorgangE2E = { ...createVorgang(), name: 'VorgangToStay', eingangs: [eingang], assignedTo: getUserSabineInternalId() }; - - const vorgangToDisappear: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangToDisappear'), status: VorgangStatusE2E.NEU }; - const vorgangHyphen: VorgangE2E = { ...buildVorgang(objectIds[1], 'Vorgang-mit-Bindestrich'), status: VorgangStatusE2E.NEU }; - const vorgangWOHyphen: VorgangE2E = { ...buildVorgang(objectIds[2], 'Vorgang mit Leerzeichen'), status: VorgangStatusE2E.NEU }; - - const vorgangStayInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangToStay.name); - const vorgangDisappearInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangToDisappear.name); - const vorgangHyphenInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangHyphen.name); - const vorgangWOHyphenInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangWOHyphen.name); - - const userSabine: UserE2E = getUserSabine(); - - before(() => { - initVorgaenge([vorgangToStay, vorgangToDisappear, vorgangHyphen, vorgangWOHyphen]); - initSearchIndex([vorgangToStay, vorgangToDisappear, vorgangHyphen, vorgangWOHyphen]); - initUsermanagerUsers([getUserManagerUserSabine()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - dropSearchIndex(); - }) - - it('should filter list', () => { - doSearchWith(vorgangToStay.name); - waitForSpinnerToDisappear(); - - exist(vorgangStayInList.getRoot()); - notExist(vorgangDisappearInList.getRoot()); - }) - - describe('Search for partial strings...', () => { - it ('should find partial string at the beginning', () => { - doSearchWith('VorgangToS'); - waitForSpinnerToDisappear(); - - exist(vorgangStayInList.getRoot()); - }) - - it ('should find partial string in the middle', () => { - doSearchWith('gangToSt'); - waitForSpinnerToDisappear(); - - exist(vorgangStayInList.getRoot()); - }) - - it ('should find partial string at the end, case insensitive', () => { - doSearchWith('toStay'); - waitForSpinnerToDisappear(); - - exist(vorgangStayInList.getRoot()); - }) - - }) - - describe ('Search with hyphen', () => { - it ('should find entry with hyphen', () => { - doSearchWith('Vorgang-mit'); - waitForSpinnerToDisappear(); - - exist(vorgangHyphenInList.getRoot()); - notExist(vorgangWOHyphenInList.getRoot()); - }) - - it ('should find entry without hyphen', () => { - doSearchWith('Vorgang mit'); - waitForSpinnerToDisappear(); - - notExist(vorgangHyphenInList.getRoot()); - exist(vorgangWOHyphenInList.getRoot()); - }) - }) - - describe ('Search using AND operator', () => { - it ('should find entry with all matches', () => { - doSearchWith('Vorgang mit Leerzeichen'); - waitForSpinnerToDisappear(); - - exist(vorgangWOHyphenInList.getRoot()); - }) - - it ('should not find entry when using additional words', () => { - doSearchWith('Vorgang mit als Leerzeichen'); - waitForSpinnerToDisappear(); - - notExist(vorgangWOHyphenInList.getRoot()); - }) - }) - - describe('navigate with filtered list to vorgang detail', () => { - - beforeEach(() => { - doSearchWith(vorgangToStay.name); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - vorgangStayInList.getRoot().click(); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('and navigate back', () => { - - it('should show filtered list after navigate back to list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - exist(vorgangStayInList.getRoot()); - notExist(vorgangDisappearInList.getRoot()); - }) - }) - }) - - describe('clear search button', () => { - - beforeEach(() => { - waitForSpinnerToDisappear(); - }) - - it('should not be visible if empty search field', () => { - - vorgangSearch.getInput().clear(); - - notExist(vorgangSearch.getClearButton()); - }) - - it('should be visible if search field contains text', () => { - vorgangSearch.getInput().clear().type('Gewe'); - - exist(vorgangSearch.getClearButton()); - }) - - it('should show unfiltered list if clicked', () => { - doSearchWith(vorgangToStay.name); - waitForSpinnerToDisappear(); - - vorgangSearch.getClearButton().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - exist(vorgangStayInList.getRoot()); - exist(vorgangDisappearInList.getRoot()); - }) - }) - - describe('loading vorgang', () => { - - it('should open vorgang', () => { - doSearchWith('Vorgang'); - vorgangStayInList.getRoot().click(); - exist(vorgangPage.getSpinner()); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - exist(vorgangHeader.getUserContainer().getIconContainer().getAssignedIcon()); - haveText(vorgangHeader.getUserContainer().getIconContainer().getAssignedIcon(), userSabine.initials); - }) - - it('should navigate back to list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - exist(vorgangPage.getSpinner()); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - - it('should open another vorgang', () => { - vorgangDisappearInList.getRoot().click(); - exist(vorgangPage.getSpinner()); - waitForSpinnerToDisappear(); - - exist(vorgangHeader.getRoot()); - exist(vorgangHeader.getUserContainer().getIconContainer().getUnassignedIcon()); - }) - - it('should navigate back to list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - - exist(vorgangList.getRoot()); - }) - }) - }) - - describe('filter by preview list', () => { - - const vorgangName: string = 'VorgangMatchBySearch'; - const vorgang: VorgangE2E = { ...createVorgang(), name: vorgangName }; - - const wiedervorlageForMatchBySearch: WiedervorlageE2E = { ...createWiedervorlageItem('WiedervorlageMatchBySearch'), done: false }; - const wiedervorlageAttachedItemForMatchBySearch: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[0], vorgang._id.$oid), item: wiedervorlageForMatchBySearch }; - - const kommentarForMatchBySearch: KommentarE2E = { ...createKommentar(), text: 'KommentarMatchBySearch' }; - const kommentarAttachedItemForMatchBySearch: VorgangAttachedItemE2E = { ...createKommentarAttachedItem(objectIds[1], vorgang._id.$oid ), item: kommentarForMatchBySearch} - - const postfachNachrichtForMatchBySearch: PostfachMailItemE2E = { - ...createPostfachNachrichtReplyItem(), - createdBy: getUserSabineInternalId(), - subject: 'PostfachNachrichtForMatchBySearch' - } - - const postfachNachrichtAttachedItemForMatchBySearch: VorgangAttachedItemE2E = { ...createPostfachNachrichtAttachedItem(objectIds[2], vorgang._id.$oid), item: postfachNachrichtForMatchBySearch }; - - const previewListItemVorgang: VorgangSearchPreviewListItemE2EComponent = vorgangSearch.getVorgangSearchPreviewListItem(vorgang.name); - - - - const vorgangOtherName: string = 'VorgangOther'; - const vorgangOther: VorgangE2E = { ...buildVorgang(objectIds[3], vorgangOtherName), status: VorgangStatusE2E.NEU }; - - const wiedervorlageForOther: WiedervorlageE2E = { ...createWiedervorlageItem('WiedervorlageOther'), done: true }; - const wiedervorlageAttachedItemForOther: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[4], vorgangOther._id.$oid), item: wiedervorlageForOther }; - - const kommentarForOther: KommentarE2E = { ...createKommentar(), text: 'KommentarOther' }; - const kommentarAttachedItemForOther: VorgangAttachedItemE2E = { ...createKommentarAttachedItem(objectIds[5], vorgangOther._id.$oid ), item: kommentarForOther }; - - const postfachNachrichtForOther: PostfachMailItemE2E = { - ...createPostfachNachrichtReplyItem(), - createdBy: getUserSabineInternalId(), - subject: 'PostfachNachrichtOther' - } - - const postfachNachrichtAttachedItemForOther: VorgangAttachedItemE2E = { ...createPostfachNachrichtAttachedItem(objectIds[6], vorgangOther._id.$oid), item: postfachNachrichtForOther }; - - const previewListItemVorgangOther: VorgangSearchPreviewListItemE2EComponent = vorgangSearch.getVorgangSearchPreviewListItem(vorgangOther.name); - - before(() => { - initVorgaenge([vorgang, vorgangOther]); - initVorgangAttachedItem([ - wiedervorlageAttachedItemForMatchBySearch, wiedervorlageAttachedItemForOther, - kommentarAttachedItemForMatchBySearch, - kommentarAttachedItemForOther, - postfachNachrichtAttachedItemForMatchBySearch, - postfachNachrichtAttachedItemForOther - ]); - initSearchIndex([vorgang, vorgangOther]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - dropSearchIndex(); - }) - - it('should NOT show preview list initial', () => { - notExist(vorgangSearch.getVorgangSearchPreviewList()); - }) - - it('should NOT show preview list on 2 character', () => { - vorgangSearch.getInput().clear().type(vorgangName.substring(0, 2)); - - notExist(vorgangSearch.getVorgangSearchPreviewList()); - }) - - it('should show content of preview list on 3 character', () => { - vorgangSearch.getInput().clear().type(vorgangName.substring(0, 3)); - - exist(previewListItemVorgang.getRoot()); - exist(previewListItemVorgangOther.getRoot()); - }) - - it('should list item informations', () => { - vorgangSearch.getInput().clear().type(vorgangName); - - exist(previewListItemVorgang.getRoot()); - exist(previewListItemVorgang.getCreatedAt()); - exist(previewListItemVorgang.getVorgangName()); - exist(previewListItemVorgang.getVorgangAktenzeichen()); - exist(previewListItemVorgang.getVorgangNummer()); - }) - - describe('select vorgang in vorganglist preview list', () => { - - it('should navigate to vorgang on selection', () => { - vorgangSearch.getInput().clear().type(vorgangName); - exist(previewListItemVorgang.getRoot()); - - previewListItemVorgang.getRoot().click(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - haveText(vorgangPage.getVorgangDetailHeader().getName(), vorgangName); - }) - }) - - describe('select vorgang in vorgangdetail preview list', () => { - - it('should navigate to vorgang on selection', () => { - vorgangSearch.getInput().clear().type(vorgangOtherName); - exist(previewListItemVorgangOther.getRoot()); - - previewListItemVorgangOther.getRoot().click(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - haveText(vorgangPage.getVorgangDetailHeader().getName(), vorgangOtherName); - }) - - it('should have wiedervorlage', () => { - const wiedervorlage: WiedervorlageInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer().getWiedervorlage('WiedervorlageOther'); - - exist(wiedervorlage.getRoot()); - }) - - it('should have kommentar', () => { - const kommentar: KommentarInVorgangE2E = vorgangPage.getKommentarContainer().getKommentar('KommentarOther'); - - exist(kommentar.getRoot()); - }) - - it('should have postfachNachricht', () => { - const postfachNachricht: PostfachMailListItem = vorgangPage.getPostfachMailcontainer().getListItem('PostfachNachrichtOther'); - - exist(postfachNachricht.getRoot()); - }) - }) - - describe('clear preview list if clicking clear button', () => { - - it('should hide preview list', () => { - vorgangSearch.getInput().clear().type(vorgangName.substring(0, 3)); - - exist(previewListItemVorgang.getRoot()); - exist(previewListItemVorgangOther.getRoot()); - - vorgangSearch.getClearButton().click(); - waitForSpinnerToDisappear(); - - notExist(vorgangSearch.getVorgangSearchPreviewList()); - }) - }) - - describe.skip('clear preview list on less than 3 character', () => { - - it('should hide preview list', () => { - vorgangSearch.getInput().clear().type(vorgangName.substring(0, 3), { delay: 220 }); - - exist(previewListItemVorgang.getRoot()); - exist(previewListItemVorgangOther.getRoot()); - - backspaceOn(vorgangSearch.getInput()); - - notExist(vorgangSearch.getVorgangSearchPreviewList()); - }) - }) - }) - - describe.skip('filter by all possible fields', () => { - - const NO_MATCH: string = 'no match'; - - const vorgangNameToMatch: string = 'VorgangStayByVorgangName'; - const eingangByVorgangName: EingangE2E = { - ...EingangE2ETestData, - antragsteller: { ...AntragstellerE2ETestData, vorname: NO_MATCH, nachname: NO_MATCH }, - header: { ...EingangHeaderE2ETestData, requestId: NO_MATCH } - } - const vorgangStayByVorgangName: VorgangE2E = { ...buildVorgang(objectIds[0], vorgangNameToMatch), aktenzeichen: NO_MATCH, eingangs: [eingangByVorgangName] }; - - - const aktenzeichenToMatch: string = 'Ein Aktenzeichen'; - const eingangByAktenzeichen: EingangE2E = { - ...EingangE2ETestData, - antragsteller: { ...AntragstellerE2ETestData, vorname: NO_MATCH, nachname: NO_MATCH }, - header: { ...EingangHeaderE2ETestData, requestId: NO_MATCH } - } - const vorgangStayByAktenzeichen: VorgangE2E = { ...createVorgang(), name: 'VorgangStayByAktenzeichen', aktenzeichen: aktenzeichenToMatch, eingangs: [eingangByAktenzeichen] }; - - - const antragstellerVornameToMatch: string = 'Vorname vom Antragsteller'; - const eingangByAntragstellerVorname: EingangE2E = { - ...EingangE2ETestData, - antragsteller: { ...AntragstellerE2ETestData, vorname: antragstellerVornameToMatch, nachname: NO_MATCH }, - header: { ...EingangHeaderE2ETestData, requestId: NO_MATCH } - } - const vorgangStayByAntragstellerVorname: VorgangE2E = { ...buildVorgang(objectIds[1], 'VorgangStayByAntragstellerVorname'), aktenzeichen: NO_MATCH, eingangs: [eingangByAntragstellerVorname] }; - - - const antragstellerNachnameToMatch: string = 'Nachname vom Antragsteller'; - const eingangByAntragstellerNachname: EingangE2E = { - ...EingangE2ETestData, - antragsteller: { ...AntragstellerE2ETestData, vorname: NO_MATCH, nachname: antragstellerNachnameToMatch }, - header: { ...EingangHeaderE2ETestData, requestId: NO_MATCH } - } - const vorgangStayByAntragstellerNachname: VorgangE2E = { ...buildVorgang(objectIds[2], 'VorgangStayByAntragstellerNachname'), aktenzeichen: NO_MATCH, eingangs: [eingangByAntragstellerNachname] }; - - - const vorgangNummerToMatch: string = 'VORGANGNUMMER_EHEMALS_REQUEST_ID'; - const eingangByRequestId: EingangE2E = { - ...EingangE2ETestData, - antragsteller: { ...AntragstellerE2ETestData, vorname: NO_MATCH, nachname: NO_MATCH } - } - const vorgangStayByRequestId: VorgangE2E = { ...buildVorgang(objectIds[3], 'VorgangStayByRequestId'), aktenzeichen: NO_MATCH, eingangs: [eingangByRequestId], nummer: vorgangNummerToMatch }; - - - before(() => { - initVorgaenge([vorgangStayByVorgangName, vorgangStayByAktenzeichen, vorgangStayByAntragstellerVorname, vorgangStayByAntragstellerNachname, vorgangStayByRequestId]) - initSearchIndex([vorgangStayByVorgangName, vorgangStayByAktenzeichen, vorgangStayByAntragstellerVorname, vorgangStayByAntragstellerNachname, vorgangStayByRequestId]) - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - dropSearchIndex(); - }) - - describe('do search with field...', () => { - - const byVorgangName: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangStayByVorgangName.name); - const byAktenzeichen: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangStayByAktenzeichen.name); - const byAntragstellerVorname: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangStayByAntragstellerVorname.name); - const byAntragstellerNachname: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangStayByAntragstellerNachname.name); - const byRequestId: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangStayByRequestId.name); - - it('should show result by vorgang name', () => { - doSearchWith(vorgangNameToMatch); - waitForSpinnerToDisappear(); - - exist(byVorgangName.getRoot()); - notExist(byAktenzeichen.getRoot()); - notExist(byAntragstellerVorname.getRoot()); - notExist(byAntragstellerNachname.getRoot()); - notExist(byRequestId.getRoot()); - }) - - it('should show result by aktenzeichen', () => { - doSearchWith(aktenzeichenToMatch); - waitForSpinnerToDisappear(); - - notExist(byVorgangName.getRoot()); - exist(byAktenzeichen.getRoot()); - notExist(byAntragstellerVorname.getRoot()); - notExist(byAntragstellerNachname.getRoot()); - notExist(byRequestId.getRoot()); - }) - - it('should show result by antragsteller vorname', () => { - doSearchWith(antragstellerVornameToMatch); - waitForSpinnerToDisappear(); - - notExist(byVorgangName.getRoot()); - notExist(byAktenzeichen.getRoot()); - exist(byAntragstellerVorname.getRoot()); - notExist(byAntragstellerNachname.getRoot()); - notExist(byRequestId.getRoot()); - }) - - it('should show result by antragsteller nachname', () => { - doSearchWith(antragstellerNachnameToMatch); - waitForSpinnerToDisappear(); - - notExist(byVorgangName.getRoot()); - notExist(byAktenzeichen.getRoot()); - notExist(byAntragstellerVorname.getRoot()); - exist(byAntragstellerNachname.getRoot()); - notExist(byRequestId.getRoot()); - }) - - it('should show result by vorgangnummer', () => { - doSearchWith(vorgangNummerToMatch); - waitForSpinnerToDisappear(); - - notExist(byVorgangName.getRoot()); - notExist(byAktenzeichen.getRoot()); - notExist(byAntragstellerVorname.getRoot()); - notExist(byAntragstellerNachname.getRoot()); - exist(byRequestId.getRoot()); - }) - - it('search button should show search result', () => { - doSearchWith(vorgangNummerToMatch); - waitForSpinnerToDisappear(); - - notExist(byVorgangName.getRoot()); - }) - }) - }) - - describe('leave search field', () => { - it('without submit should set previously entered text', () => { - doSearchWith('Gewerbe'); - - vorgangSearch.getInput().clear().type('Gewe'); - vorgangList.getRoot().click(); - - haveValue(vorgangSearch.getInput(), 'Gewerbe'); - }) - }) - - describe('empty search field', () => { - it('should not search with empty input', () => { - doSearchWith(''); - - notExist(vorgangPage.getSpinner()); - }) - }) - - - - function doSearchWith(searchBy: string): void { - enterWith(vorgangSearch.getInput(), searchBy); - } + const mainPage: MainPage = new MainPage(); + + const header: HeaderE2EComponent = mainPage.getHeader(); + const vorgangSearch: VorgangSearchE2EComponent = header.getVorgangSearch(); + + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + + describe.skip(`on user with role ${UserRoleE2E.VERWALTUNG_USER} by requestId/Eingangskennzeichen`, () => { + const requestId: string = faker.datatype.uuid(); + const eingang: EingangE2E = { + ...EingangE2ETestData, + header: { ...EingangHeaderE2ETestData, requestId }, + }; + const vorgangToStay: VorgangE2E = { + ...createVorgang(), + name: 'VorgangToStay', + eingangs: [eingang], + assignedTo: getUserSabineInternalId(), + }; + + const vorgangToDisappear: VorgangE2E = { + ...buildVorgang(objectIds[0], 'VorgangToDisappear'), + status: VorgangStatusE2E.NEU, + }; + const vorgangHyphen: VorgangE2E = { + ...buildVorgang(objectIds[1], 'Vorgang-mit-Bindestrich'), + status: VorgangStatusE2E.NEU, + }; + const vorgangWOHyphen: VorgangE2E = { + ...buildVorgang(objectIds[2], 'Vorgang mit Leerzeichen'), + status: VorgangStatusE2E.NEU, + }; + + const vorgangStayInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangToStay.name, + ); + const vorgangDisappearInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangToDisappear.name, + ); + const vorgangHyphenInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangHyphen.name, + ); + const vorgangWOHyphenInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangWOHyphen.name, + ); + + const userSabine: UserE2E = getUserSabine(); + + before(() => { + initVorgaenge([vorgangToStay, vorgangToDisappear, vorgangHyphen, vorgangWOHyphen]); + initSearchIndex([vorgangToStay, vorgangToDisappear, vorgangHyphen, vorgangWOHyphen]); + initUsermanagerUsers([getUserManagerUserSabine()]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + dropSearchIndex(); + }); + + it('should filter list', () => { + doSearchWith(vorgangToStay.name); + waitForSpinnerToDisappear(); + + exist(vorgangStayInList.getRoot()); + notExist(vorgangDisappearInList.getRoot()); + }); + + describe('Search for partial strings...', () => { + it('should find partial string at the beginning', () => { + doSearchWith('VorgangToS'); + waitForSpinnerToDisappear(); + + exist(vorgangStayInList.getRoot()); + }); + + it('should find partial string in the middle', () => { + doSearchWith('gangToSt'); + waitForSpinnerToDisappear(); + + exist(vorgangStayInList.getRoot()); + }); + + it('should find partial string at the end, case insensitive', () => { + doSearchWith('toStay'); + waitForSpinnerToDisappear(); + + exist(vorgangStayInList.getRoot()); + }); + }); + + describe('Search with hyphen', () => { + it('should find entry with hyphen', () => { + doSearchWith('Vorgang-mit'); + waitForSpinnerToDisappear(); + + exist(vorgangHyphenInList.getRoot()); + notExist(vorgangWOHyphenInList.getRoot()); + }); + + it('should find entry without hyphen', () => { + doSearchWith('Vorgang mit'); + waitForSpinnerToDisappear(); + + notExist(vorgangHyphenInList.getRoot()); + exist(vorgangWOHyphenInList.getRoot()); + }); + }); + + describe('Search using AND operator', () => { + it('should find entry with all matches', () => { + doSearchWith('Vorgang mit Leerzeichen'); + waitForSpinnerToDisappear(); + + exist(vorgangWOHyphenInList.getRoot()); + }); + + it('should not find entry when using additional words', () => { + doSearchWith('Vorgang mit als Leerzeichen'); + waitForSpinnerToDisappear(); + + notExist(vorgangWOHyphenInList.getRoot()); + }); + }); + + describe('navigate with filtered list to vorgang detail', () => { + beforeEach(() => { + doSearchWith(vorgangToStay.name); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + vorgangStayInList.getRoot().click(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('and navigate back', () => { + it('should show filtered list after navigate back to list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + exist(vorgangStayInList.getRoot()); + notExist(vorgangDisappearInList.getRoot()); + }); + }); + }); + + describe('clear search button', () => { + beforeEach(() => { + waitForSpinnerToDisappear(); + }); + + it('should not be visible if empty search field', () => { + vorgangSearch.getInput().clear(); + + notExist(vorgangSearch.getClearButton()); + }); + + it('should be visible if search field contains text', () => { + vorgangSearch.getInput().clear().type('Gewe'); + + exist(vorgangSearch.getClearButton()); + }); + + it('should show unfiltered list if clicked', () => { + doSearchWith(vorgangToStay.name); + waitForSpinnerToDisappear(); + + vorgangSearch.getClearButton().click(); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + exist(vorgangStayInList.getRoot()); + exist(vorgangDisappearInList.getRoot()); + }); + }); + + describe('loading vorgang', () => { + it('should open vorgang', () => { + doSearchWith('Vorgang'); + vorgangStayInList.getRoot().click(); + exist(vorgangPage.getSpinner()); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + exist(vorgangHeader.getUserContainer().getIconContainer().getAssignedIcon()); + haveText( + vorgangHeader.getUserContainer().getIconContainer().getAssignedIcon(), + userSabine.initials, + ); + }); + + it('should navigate back to list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + exist(vorgangPage.getSpinner()); + waitForSpinnerToDisappear(); + + exist(vorgangList.getRoot()); + }); + + it('should open another vorgang', () => { + vorgangDisappearInList.getRoot().click(); + exist(vorgangPage.getSpinner()); + waitForSpinnerToDisappear(); + + exist(vorgangHeader.getRoot()); + exist(vorgangHeader.getUserContainer().getIconContainer().getUnassignedIcon()); + }); + + it('should navigate back to list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + + exist(vorgangList.getRoot()); + }); + }); + }); + + describe('filter by preview list', () => { + const vorgangName: string = 'VorgangMatchBySearch'; + const vorgang: VorgangE2E = { ...createVorgang(), name: vorgangName }; + + const wiedervorlageForMatchBySearch: WiedervorlageE2E = { + ...createWiedervorlageItem('WiedervorlageMatchBySearch'), + done: false, + }; + const wiedervorlageAttachedItemForMatchBySearch: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[0], vorgang._id.$oid), + item: wiedervorlageForMatchBySearch, + }; + + const kommentarForMatchBySearch: KommentarE2E = { + ...createKommentar(), + text: 'KommentarMatchBySearch', + }; + const kommentarAttachedItemForMatchBySearch: VorgangAttachedItemE2E = { + ...createKommentarAttachedItem(objectIds[1], vorgang._id.$oid), + item: kommentarForMatchBySearch, + }; + + const postfachNachrichtForMatchBySearch: PostfachMailItemE2E = { + ...createPostfachNachrichtReplyItem(), + createdBy: getUserSabineInternalId(), + subject: 'PostfachNachrichtForMatchBySearch', + }; + + const postfachNachrichtAttachedItemForMatchBySearch: VorgangAttachedItemE2E = { + ...createPostfachNachrichtAttachedItem(objectIds[2], vorgang._id.$oid), + item: postfachNachrichtForMatchBySearch, + }; + + const previewListItemVorgang: VorgangSearchPreviewListItemE2EComponent = + vorgangSearch.getVorgangSearchPreviewListItem(vorgang.name); + + const vorgangOtherName: string = 'VorgangOther'; + const vorgangOther: VorgangE2E = { + ...buildVorgang(objectIds[3], vorgangOtherName), + status: VorgangStatusE2E.NEU, + }; + + const wiedervorlageForOther: WiedervorlageE2E = { + ...createWiedervorlageItem('WiedervorlageOther'), + done: true, + }; + const wiedervorlageAttachedItemForOther: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[4], vorgangOther._id.$oid), + item: wiedervorlageForOther, + }; + + const kommentarForOther: KommentarE2E = { ...createKommentar(), text: 'KommentarOther' }; + const kommentarAttachedItemForOther: VorgangAttachedItemE2E = { + ...createKommentarAttachedItem(objectIds[5], vorgangOther._id.$oid), + item: kommentarForOther, + }; + + const postfachNachrichtForOther: PostfachMailItemE2E = { + ...createPostfachNachrichtReplyItem(), + createdBy: getUserSabineInternalId(), + subject: 'PostfachNachrichtOther', + }; + + const postfachNachrichtAttachedItemForOther: VorgangAttachedItemE2E = { + ...createPostfachNachrichtAttachedItem(objectIds[6], vorgangOther._id.$oid), + item: postfachNachrichtForOther, + }; + + const previewListItemVorgangOther: VorgangSearchPreviewListItemE2EComponent = + vorgangSearch.getVorgangSearchPreviewListItem(vorgangOther.name); + + before(() => { + initVorgaenge([vorgang, vorgangOther]); + initVorgangAttachedItem([ + wiedervorlageAttachedItemForMatchBySearch, + wiedervorlageAttachedItemForOther, + kommentarAttachedItemForMatchBySearch, + kommentarAttachedItemForOther, + postfachNachrichtAttachedItemForMatchBySearch, + postfachNachrichtAttachedItemForOther, + ]); + initSearchIndex([vorgang, vorgangOther]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + dropSearchIndex(); + }); + + it('should NOT show preview list initial', () => { + notExist(vorgangSearch.getVorgangSearchPreviewList()); + }); + + it('should NOT show preview list on 2 character', () => { + vorgangSearch.getInput().clear().type(vorgangName.substring(0, 2)); + + notExist(vorgangSearch.getVorgangSearchPreviewList()); + }); + + it('should show content of preview list on 3 character', () => { + vorgangSearch.getInput().clear().type(vorgangName.substring(0, 3)); + + exist(previewListItemVorgang.getRoot()); + exist(previewListItemVorgangOther.getRoot()); + }); + + it('should list item informations', () => { + vorgangSearch.getInput().clear().type(vorgangName); + + exist(previewListItemVorgang.getRoot()); + exist(previewListItemVorgang.getCreatedAt()); + exist(previewListItemVorgang.getVorgangName()); + exist(previewListItemVorgang.getVorgangAktenzeichen()); + exist(previewListItemVorgang.getVorgangNummer()); + }); + + describe('select vorgang in vorganglist preview list', () => { + it('should navigate to vorgang on selection', () => { + vorgangSearch.getInput().clear().type(vorgangName); + exist(previewListItemVorgang.getRoot()); + + previewListItemVorgang.getRoot().click(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + haveText(vorgangPage.getVorgangDetailHeader().getName(), vorgangName); + }); + }); + + describe('select vorgang in vorgangdetail preview list', () => { + it('should navigate to vorgang on selection', () => { + vorgangSearch.getInput().clear().type(vorgangOtherName); + exist(previewListItemVorgangOther.getRoot()); + + previewListItemVorgangOther.getRoot().click(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + haveText(vorgangPage.getVorgangDetailHeader().getName(), vorgangOtherName); + }); + + it('should have wiedervorlage', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = vorgangPage + .getWiedervorlagenContainer() + .getWiedervorlage('WiedervorlageOther'); + + exist(wiedervorlage.getRoot()); + }); + + it('should have kommentar', () => { + const kommentar: KommentarInVorgangE2E = vorgangPage + .getKommentarContainer() + .getKommentar('KommentarOther'); + + exist(kommentar.getRoot()); + }); + + it('should have postfachNachricht', () => { + const postfachNachricht: PostfachMailListItem = vorgangPage + .getPostfachMailcontainer() + .getListItem('PostfachNachrichtOther'); + + exist(postfachNachricht.getRoot()); + }); + }); + + describe('clear preview list if clicking clear button', () => { + it('should hide preview list', () => { + vorgangSearch.getInput().clear().type(vorgangName.substring(0, 3)); + + exist(previewListItemVorgang.getRoot()); + exist(previewListItemVorgangOther.getRoot()); + + vorgangSearch.getClearButton().click(); + waitForSpinnerToDisappear(); + + notExist(vorgangSearch.getVorgangSearchPreviewList()); + }); + }); + + describe.skip('clear preview list on less than 3 character', () => { + it('should hide preview list', () => { + vorgangSearch.getInput().clear().type(vorgangName.substring(0, 3), { delay: 220 }); + + exist(previewListItemVorgang.getRoot()); + exist(previewListItemVorgangOther.getRoot()); + + backspaceOn(vorgangSearch.getInput()); + + notExist(vorgangSearch.getVorgangSearchPreviewList()); + }); + }); + }); + + describe.skip('filter by all possible fields', () => { + const NO_MATCH: string = 'no match'; + + const vorgangNameToMatch: string = 'VorgangStayByVorgangName'; + const eingangByVorgangName: EingangE2E = { + ...EingangE2ETestData, + antragsteller: { ...AntragstellerE2ETestData, vorname: NO_MATCH, nachname: NO_MATCH }, + header: { ...EingangHeaderE2ETestData, requestId: NO_MATCH }, + }; + const vorgangStayByVorgangName: VorgangE2E = { + ...buildVorgang(objectIds[0], vorgangNameToMatch), + aktenzeichen: NO_MATCH, + eingangs: [eingangByVorgangName], + }; + + const aktenzeichenToMatch: string = 'Ein Aktenzeichen'; + const eingangByAktenzeichen: EingangE2E = { + ...EingangE2ETestData, + antragsteller: { ...AntragstellerE2ETestData, vorname: NO_MATCH, nachname: NO_MATCH }, + header: { ...EingangHeaderE2ETestData, requestId: NO_MATCH }, + }; + const vorgangStayByAktenzeichen: VorgangE2E = { + ...createVorgang(), + name: 'VorgangStayByAktenzeichen', + aktenzeichen: aktenzeichenToMatch, + eingangs: [eingangByAktenzeichen], + }; + + const antragstellerVornameToMatch: string = 'Vorname vom Antragsteller'; + const eingangByAntragstellerVorname: EingangE2E = { + ...EingangE2ETestData, + antragsteller: { + ...AntragstellerE2ETestData, + vorname: antragstellerVornameToMatch, + nachname: NO_MATCH, + }, + header: { ...EingangHeaderE2ETestData, requestId: NO_MATCH }, + }; + const vorgangStayByAntragstellerVorname: VorgangE2E = { + ...buildVorgang(objectIds[1], 'VorgangStayByAntragstellerVorname'), + aktenzeichen: NO_MATCH, + eingangs: [eingangByAntragstellerVorname], + }; + + const antragstellerNachnameToMatch: string = 'Nachname vom Antragsteller'; + const eingangByAntragstellerNachname: EingangE2E = { + ...EingangE2ETestData, + antragsteller: { + ...AntragstellerE2ETestData, + vorname: NO_MATCH, + nachname: antragstellerNachnameToMatch, + }, + header: { ...EingangHeaderE2ETestData, requestId: NO_MATCH }, + }; + const vorgangStayByAntragstellerNachname: VorgangE2E = { + ...buildVorgang(objectIds[2], 'VorgangStayByAntragstellerNachname'), + aktenzeichen: NO_MATCH, + eingangs: [eingangByAntragstellerNachname], + }; + + const vorgangNummerToMatch: string = 'VORGANGNUMMER_EHEMALS_REQUEST_ID'; + const eingangByRequestId: EingangE2E = { + ...EingangE2ETestData, + antragsteller: { ...AntragstellerE2ETestData, vorname: NO_MATCH, nachname: NO_MATCH }, + }; + const vorgangStayByRequestId: VorgangE2E = { + ...buildVorgang(objectIds[3], 'VorgangStayByRequestId'), + aktenzeichen: NO_MATCH, + eingangs: [eingangByRequestId], + nummer: vorgangNummerToMatch, + }; + + before(() => { + initVorgaenge([ + vorgangStayByVorgangName, + vorgangStayByAktenzeichen, + vorgangStayByAntragstellerVorname, + vorgangStayByAntragstellerNachname, + vorgangStayByRequestId, + ]); + initSearchIndex([ + vorgangStayByVorgangName, + vorgangStayByAktenzeichen, + vorgangStayByAntragstellerVorname, + vorgangStayByAntragstellerNachname, + vorgangStayByRequestId, + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + dropSearchIndex(); + }); + + describe('do search with field...', () => { + const byVorgangName: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangStayByVorgangName.name, + ); + const byAktenzeichen: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangStayByAktenzeichen.name, + ); + const byAntragstellerVorname: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangStayByAntragstellerVorname.name, + ); + const byAntragstellerNachname: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangStayByAntragstellerNachname.name, + ); + const byRequestId: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangStayByRequestId.name, + ); + + it('should show result by vorgang name', () => { + doSearchWith(vorgangNameToMatch); + waitForSpinnerToDisappear(); + + exist(byVorgangName.getRoot()); + notExist(byAktenzeichen.getRoot()); + notExist(byAntragstellerVorname.getRoot()); + notExist(byAntragstellerNachname.getRoot()); + notExist(byRequestId.getRoot()); + }); + + it('should show result by aktenzeichen', () => { + doSearchWith(aktenzeichenToMatch); + waitForSpinnerToDisappear(); + + notExist(byVorgangName.getRoot()); + exist(byAktenzeichen.getRoot()); + notExist(byAntragstellerVorname.getRoot()); + notExist(byAntragstellerNachname.getRoot()); + notExist(byRequestId.getRoot()); + }); + + it('should show result by antragsteller vorname', () => { + doSearchWith(antragstellerVornameToMatch); + waitForSpinnerToDisappear(); + + notExist(byVorgangName.getRoot()); + notExist(byAktenzeichen.getRoot()); + exist(byAntragstellerVorname.getRoot()); + notExist(byAntragstellerNachname.getRoot()); + notExist(byRequestId.getRoot()); + }); + + it('should show result by antragsteller nachname', () => { + doSearchWith(antragstellerNachnameToMatch); + waitForSpinnerToDisappear(); + + notExist(byVorgangName.getRoot()); + notExist(byAktenzeichen.getRoot()); + notExist(byAntragstellerVorname.getRoot()); + exist(byAntragstellerNachname.getRoot()); + notExist(byRequestId.getRoot()); + }); + + it('should show result by vorgangnummer', () => { + doSearchWith(vorgangNummerToMatch); + waitForSpinnerToDisappear(); + + notExist(byVorgangName.getRoot()); + notExist(byAktenzeichen.getRoot()); + notExist(byAntragstellerVorname.getRoot()); + notExist(byAntragstellerNachname.getRoot()); + exist(byRequestId.getRoot()); + }); + + it('search button should show search result', () => { + doSearchWith(vorgangNummerToMatch); + waitForSpinnerToDisappear(); + + notExist(byVorgangName.getRoot()); + }); + }); + }); + + describe('leave search field', () => { + it('without submit should set previously entered text', () => { + doSearchWith('Gewerbe'); + + vorgangSearch.getInput().clear().type('Gewe'); + vorgangList.getRoot().click(); + + haveValue(vorgangSearch.getInput(), 'Gewerbe'); + }); + }); + + describe('empty search field', () => { + it('should not search with empty input', () => { + doSearchWith(''); + + notExist(vorgangPage.getSpinner()); + }); + }); + + function doSearchWith(searchBy: string): void { + enterWith(vorgangSearch.getInput(), searchBy); + } }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-search-view.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-search-view.cy.ts index 0f818107bd0d64abb3cd82256d75d1c1d2e4013d..b520bd9cb66f4b55ba6720a48c1c6ed5ec4e29b1 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-search-view.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-search-view.cy.ts @@ -3,7 +3,10 @@ import localeDe from '@angular/common/locales/de'; import localeDeExtra from '@angular/common/locales/extra/de'; import { CurrentUserProfileE2EComponent } from 'apps/alfa-e2e/src/components/user-profile/current-user-profile.component.e2e'; import { VorgangListE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-list.e2e.component'; -import { VorgangViewE2EComponent, VorgangViewsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component'; +import { + VorgangViewE2EComponent, + VorgangViewsE2EComponent, +} from 'apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component'; import { UserE2E } from 'apps/alfa-e2e/src/model/user'; import { VorgangE2E, VorgangStatusE2E } from 'apps/alfa-e2e/src/model/vorgang'; import { HeaderE2EComponent } from 'apps/alfa-e2e/src/page-objects/header.po'; @@ -16,55 +19,58 @@ import { createVorgang, initVorgang } from 'apps/alfa-e2e/src/support/vorgang-ut registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang search view', () => { - const mainPage: MainPage = new MainPage(); + const mainPage: MainPage = new MainPage(); - const header: HeaderE2EComponent = mainPage.getHeader(); - const currentUserProfile: CurrentUserProfileE2EComponent = header.getCurrentUserProfile(); + const header: HeaderE2EComponent = mainPage.getHeader(); + const currentUserProfile: CurrentUserProfileE2EComponent = header.getCurrentUserProfile(); - const views: VorgangViewsE2EComponent = mainPage.getViews(); - const sucheView: VorgangViewE2EComponent = views.getSuche(); + const views: VorgangViewsE2EComponent = mainPage.getViews(); + const sucheView: VorgangViewE2EComponent = views.getSuche(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const user: UserE2E = getUserSabine(); + const user: UserE2E = getUserSabine(); - const vorgang: VorgangE2E = { ...createVorgang(), name: 'VorgangToAppear', status: VorgangStatusE2E.NEU }; + const vorgang: VorgangE2E = { + ...createVorgang(), + name: 'VorgangToAppear', + status: VorgangStatusE2E.NEU, + }; - before(() => { - initVorgang(vorgang); + before(() => { + initVorgang(vorgang); - loginAsSabine(); + loginAsSabine(); - waitForSpinnerToDisappear(); - }) + waitForSpinnerToDisappear(); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - describe('should select search view', () => { + describe('should select search view', () => { + it('should set selected after click', () => { + sucheView.getRoot().click(); + waitForSpinnerToDisappear(); - it('should set selected after click', () => { - sucheView.getRoot().click(); - waitForSpinnerToDisappear(); + containClass(sucheView.getRoot(), 'selected'); + }); - containClass(sucheView.getRoot(), 'selected'); - }) + it('should show new view after logout and login', () => { + currentUserProfile.logout(); - it('should show new view after logout and login', () => { - currentUserProfile.logout(); + loginByUi(user); + waitForSpinnerToDisappear(); - loginByUi(user); - waitForSpinnerToDisappear(); + exist(views.getNeu().getRoot()); + }); - exist(views.getNeu().getRoot()); - }) + it('should show list after click on NEU view', () => { + views.getNeu().getRoot().click(); + waitForSpinnerToDisappear(); - it('should show list after click on NEU view', () => { - views.getNeu().getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangList.getRoot()); - }) - }) -}) \ No newline at end of file + exist(vorgangList.getRoot()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-view-wiedervorlagen.pages.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-view-wiedervorlagen.pages.cy.ts index 86c94c4871f7c7dbe4cb7c2dea506d70d3653879..422d16747b4656b7ffe8460af8234d94b85328d2 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-view-wiedervorlagen.pages.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-view-wiedervorlagen.pages.cy.ts @@ -8,217 +8,302 @@ import { VorgangViewsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/v import { HttpMethodE2E } from 'apps/alfa-e2e/src/model/util'; import { ClientAttributeNameE2E, VorgangE2E } from 'apps/alfa-e2e/src/model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from 'apps/alfa-e2e/src/page-objects/main.po'; -import { dropCollections, intercept, scrollToWindowBottom, waitOfInterceptor } from 'apps/alfa-e2e/src/support/cypress-helper'; +import { + dropCollections, + intercept, + scrollToWindowBottom, + waitOfInterceptor, +} from 'apps/alfa-e2e/src/support/cypress-helper'; import { exist } from 'apps/alfa-e2e/src/support/cypress.util'; import { createDateToday, generateIds } from 'apps/alfa-e2e/src/support/tech.util'; -import { getUserManagerUserSabine, getUserSabineInternalId, initUsermanagerUsers, loginAsSabine } from 'apps/alfa-e2e/src/support/user-util'; -import { VORGANG_LIST_NEXT_FRIST_PARAM, VORGANG_LIST_PAGE_SIZE, buildVorgang, buildVorgangListPageLink, createAlfaClientAttributes, createNextWiedervorlageFristClientAttribute, initVorgaenge } from 'apps/alfa-e2e/src/support/vorgang-util'; +import { + getUserManagerUserSabine, + getUserSabineInternalId, + initUsermanagerUsers, + loginAsSabine, +} from 'apps/alfa-e2e/src/support/user-util'; +import { + VORGANG_LIST_NEXT_FRIST_PARAM, + VORGANG_LIST_PAGE_SIZE, + buildVorgang, + buildVorgangListPageLink, + createAlfaClientAttributes, + createNextWiedervorlageFristClientAttribute, + initVorgaenge, +} from 'apps/alfa-e2e/src/support/vorgang-util'; import { Interception } from 'cypress/types/net-stubbing'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('VorgangList View Wiedervorlagen', () => { - const mainPage: MainPage = new MainPage(); - - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const navigation: NavigationE2EComponent = mainPage.getNavigation(); - - const views: VorgangViewsE2EComponent = mainPage.getViews(); - - const assignedTo: string = getUserSabineInternalId(); - - const ALLE_NAME_PREFIX: string = 'VorgangWithOpenWiedervorlagen_'; - const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangWithOpenWiedervorlagenAssigned_'; - - const ALLE_NAME: string = `${ALLE_NAME_PREFIX}_`; - const MEINE_VORGAENGE_NAME: string = `${MEINE_VORGAENGE_NAME_PREFIX}_`; - - before(() => { - const vorgaenge: VorgangE2E[] = createVorgaenge(ALLE_NAME_PREFIX, (id: string, name: string) => buildVorgangWithOpenWiedervorlagen(id, name)).concat( - createVorgaenge(MEINE_VORGAENGE_NAME_PREFIX, (id: string, name: string) => buildAssignedVorgangWithOpenWiedervorlagen(id, name))); - initVorgaenge(vorgaenge); - initUsermanagerUsers([getUserManagerUserSabine()]); - - loginAsSabine(); - exist(vorgangList.getRoot()); - waitForSpinnerToDisappear(); - }) - - after(() => { - dropCollections(); - }) - - function createVorgaenge(namePrefix: string, buildFunction: (id: string, name: string) => VorgangE2E): VorgangE2E[] { - let count = 1; - return generateIds(110).map(randomId => { - const vorgang: VorgangE2E = buildFunction(randomId, `${namePrefix}_${count}`); - count++; - return vorgang; - }) - } - - function buildVorgangWithOpenWiedervorlagen(id: string, name: string): VorgangE2E { - return { ...buildVorgang(id, name), clientAttributes: createAlfaClientAttributes(ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, createNextWiedervorlageFristClientAttribute(createDateToday())) }; - } - - function buildAssignedVorgangWithOpenWiedervorlagen(id: string, name: string): VorgangE2E { - return { ...buildVorgang(id, name), assignedTo, clientAttributes: createAlfaClientAttributes(ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, createNextWiedervorlageFristClientAttribute(createDateToday())) }; - } - - describe('Alle filter', () => { - - describe('1 page', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - navigation.getAlleFilter().click(); - waitForSpinnerToDisappear(); - intercept(HttpMethodE2E.GET, buildVorgangWithOpenWiedervorlagenPageLink(1)).as(loadPageInterceptor); - }) - - it('should show 1 page with 100 vorgaenge with open wiedervorlagen', () => { - views.getWiedervorlagen().getRoot().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === VORGANG_LIST_PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME + VORGANG_LIST_PAGE_SIZE); - }) - }) - }) - - describe('2 page', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangWithOpenWiedervorlagenPageLink(2)).as(loadPageInterceptor); - }) - - it('should show 2 page with 10 vorgaenge with open wiedervorlagen and 90 vorgaenge with open wiedervorlagen ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === VORGANG_LIST_PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME + VORGANG_LIST_PAGE_SIZE); - }) - }) - }) - - describe('3 page', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangWithOpenWiedervorlagenPageLink(3)).as(loadPageInterceptor); - }) - - it('should show 3 page with 10 vorgaenge with open wiedervorlagen ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 20); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME + 80); - assert(interception.response.body._embedded.vorgangHeaderList[19].name, MEINE_VORGAENGE_NAME + VORGANG_LIST_PAGE_SIZE); - }) - }) - }) - - function buildVorgangWithOpenWiedervorlagenPageLink(page: number): string { - return `${buildVorgangListPageLink(page)}&${VORGANG_LIST_NEXT_FRIST_PARAM}`; - } - }) - - describe('Meine Vorgänge filter', () => { - - describe('1 page', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangWithOpenWiedervorlagenAssignedPageLink(1)).as(loadPageInterceptor); - }) - - it('should show 1 page with 100 vorgaenge with open wiedervorlagen', () => { - navigation.getMeineVorgaengeFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === VORGANG_LIST_PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, MEINE_VORGAENGE_NAME + VORGANG_LIST_PAGE_SIZE); - }) - }) - }) - - describe('2 page', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildVorgangWithOpenWiedervorlagenAssignedPageLink(2)).as(loadPageInterceptor); - }) - - it('should show 2 page with 10 vorgaenge with open wiedervorlagen and 90 vorgaenge with open wiedervorlagen ASSIGNED on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, MEINE_VORGAENGE_NAME + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, MEINE_VORGAENGE_NAME + 110); - }) - }) - }) - - function buildVorgangWithOpenWiedervorlagenAssignedPageLink(page: number): string { - return `${buildVorgangListPageLink(page, assignedTo)}&${VORGANG_LIST_NEXT_FRIST_PARAM}`; - } - }) - - describe('Nicht zugewiesen', () => { - - describe('1 page', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildUnassignedVorgangWithOpenWiedervorlagenPageLink(1)).as(loadPageInterceptor); - }) - - it('should show 1 page with 100 vorgaenge with open wiedervorlagen', () => { - navigation.getNichtZugewiesenFilter().click(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === VORGANG_LIST_PAGE_SIZE); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME + 1); - assert(interception.response.body._embedded.vorgangHeaderList[99].name, ALLE_NAME + VORGANG_LIST_PAGE_SIZE); - }) - }) - }) - - describe('2 page', () => { - - const loadPageInterceptor: string = 'loadPage'; - - beforeEach(() => { - intercept(HttpMethodE2E.GET, buildUnassignedVorgangWithOpenWiedervorlagenPageLink(2)).as(loadPageInterceptor); - }) - - it('should show 2 page with 10 vorgaenge on scrolling to bottom', () => { - scrollToWindowBottom(); - - waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { - assert(interception.response.body._embedded.vorgangHeaderList.length === 10); - assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME + 101); - assert(interception.response.body._embedded.vorgangHeaderList[9].name, ALLE_NAME + 110); - }) - }) - }) - - function buildUnassignedVorgangWithOpenWiedervorlagenPageLink(page: number): string { - return `${buildVorgangListPageLink(page, EMPTY_STRING)}&${VORGANG_LIST_NEXT_FRIST_PARAM}`; - } - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const navigation: NavigationE2EComponent = mainPage.getNavigation(); + + const views: VorgangViewsE2EComponent = mainPage.getViews(); + + const assignedTo: string = getUserSabineInternalId(); + + const ALLE_NAME_PREFIX: string = 'VorgangWithOpenWiedervorlagen_'; + const MEINE_VORGAENGE_NAME_PREFIX: string = 'VorgangWithOpenWiedervorlagenAssigned_'; + + const ALLE_NAME: string = `${ALLE_NAME_PREFIX}_`; + const MEINE_VORGAENGE_NAME: string = `${MEINE_VORGAENGE_NAME_PREFIX}_`; + + before(() => { + const vorgaenge: VorgangE2E[] = createVorgaenge(ALLE_NAME_PREFIX, (id: string, name: string) => + buildVorgangWithOpenWiedervorlagen(id, name), + ).concat( + createVorgaenge(MEINE_VORGAENGE_NAME_PREFIX, (id: string, name: string) => + buildAssignedVorgangWithOpenWiedervorlagen(id, name), + ), + ); + initVorgaenge(vorgaenge); + initUsermanagerUsers([getUserManagerUserSabine()]); + + loginAsSabine(); + exist(vorgangList.getRoot()); + waitForSpinnerToDisappear(); + }); + + after(() => { + dropCollections(); + }); + + function createVorgaenge( + namePrefix: string, + buildFunction: (id: string, name: string) => VorgangE2E, + ): VorgangE2E[] { + let count = 1; + return generateIds(110).map((randomId) => { + const vorgang: VorgangE2E = buildFunction(randomId, `${namePrefix}_${count}`); + count++; + return vorgang; + }); + } + + function buildVorgangWithOpenWiedervorlagen(id: string, name: string): VorgangE2E { + return { + ...buildVorgang(id, name), + clientAttributes: createAlfaClientAttributes( + ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, + createNextWiedervorlageFristClientAttribute(createDateToday()), + ), + }; + } + + function buildAssignedVorgangWithOpenWiedervorlagen(id: string, name: string): VorgangE2E { + return { + ...buildVorgang(id, name), + assignedTo, + clientAttributes: createAlfaClientAttributes( + ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, + createNextWiedervorlageFristClientAttribute(createDateToday()), + ), + }; + } + + describe('Alle filter', () => { + describe('1 page', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + navigation.getAlleFilter().click(); + waitForSpinnerToDisappear(); + intercept(HttpMethodE2E.GET, buildVorgangWithOpenWiedervorlagenPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show 1 page with 100 vorgaenge with open wiedervorlagen', () => { + views.getWiedervorlagen().getRoot().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert( + interception.response.body._embedded.vorgangHeaderList.length === + VORGANG_LIST_PAGE_SIZE, + ); + assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME + 1); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME + VORGANG_LIST_PAGE_SIZE, + ); + }); + }); + }); + + describe('2 page', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangWithOpenWiedervorlagenPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show 2 page with 10 vorgaenge with open wiedervorlagen and 90 vorgaenge with open wiedervorlagen ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert( + interception.response.body._embedded.vorgangHeaderList.length === + VORGANG_LIST_PAGE_SIZE, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME + VORGANG_LIST_PAGE_SIZE, + ); + }); + }); + }); + + describe('3 page', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangWithOpenWiedervorlagenPageLink(3)).as( + loadPageInterceptor, + ); + }); + + it('should show 3 page with 10 vorgaenge with open wiedervorlagen ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 20); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME + 80, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[19].name, + MEINE_VORGAENGE_NAME + VORGANG_LIST_PAGE_SIZE, + ); + }); + }); + }); + + function buildVorgangWithOpenWiedervorlagenPageLink(page: number): string { + return `${buildVorgangListPageLink(page)}&${VORGANG_LIST_NEXT_FRIST_PARAM}`; + } + }); + + describe('Meine Vorgänge filter', () => { + describe('1 page', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangWithOpenWiedervorlagenAssignedPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show 1 page with 100 vorgaenge with open wiedervorlagen', () => { + navigation.getMeineVorgaengeFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert( + interception.response.body._embedded.vorgangHeaderList.length === + VORGANG_LIST_PAGE_SIZE, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME + 1, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + MEINE_VORGAENGE_NAME + VORGANG_LIST_PAGE_SIZE, + ); + }); + }); + }); + + describe('2 page', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildVorgangWithOpenWiedervorlagenAssignedPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show 2 page with 10 vorgaenge with open wiedervorlagen and 90 vorgaenge with open wiedervorlagen ASSIGNED on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert( + interception.response.body._embedded.vorgangHeaderList[0].name, + MEINE_VORGAENGE_NAME + 101, + ); + assert( + interception.response.body._embedded.vorgangHeaderList[9].name, + MEINE_VORGAENGE_NAME + 110, + ); + }); + }); + }); + + function buildVorgangWithOpenWiedervorlagenAssignedPageLink(page: number): string { + return `${buildVorgangListPageLink(page, assignedTo)}&${VORGANG_LIST_NEXT_FRIST_PARAM}`; + } + }); + + describe('Nicht zugewiesen', () => { + describe('1 page', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildUnassignedVorgangWithOpenWiedervorlagenPageLink(1)).as( + loadPageInterceptor, + ); + }); + + it('should show 1 page with 100 vorgaenge with open wiedervorlagen', () => { + navigation.getNichtZugewiesenFilter().click(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert( + interception.response.body._embedded.vorgangHeaderList.length === + VORGANG_LIST_PAGE_SIZE, + ); + assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME + 1); + assert( + interception.response.body._embedded.vorgangHeaderList[99].name, + ALLE_NAME + VORGANG_LIST_PAGE_SIZE, + ); + }); + }); + }); + + describe('2 page', () => { + const loadPageInterceptor: string = 'loadPage'; + + beforeEach(() => { + intercept(HttpMethodE2E.GET, buildUnassignedVorgangWithOpenWiedervorlagenPageLink(2)).as( + loadPageInterceptor, + ); + }); + + it('should show 2 page with 10 vorgaenge on scrolling to bottom', () => { + scrollToWindowBottom(); + + waitOfInterceptor(loadPageInterceptor).then((interception: Interception) => { + assert(interception.response.body._embedded.vorgangHeaderList.length === 10); + assert(interception.response.body._embedded.vorgangHeaderList[0].name, ALLE_NAME + 101); + assert(interception.response.body._embedded.vorgangHeaderList[9].name, ALLE_NAME + 110); + }); + }); + }); + + function buildUnassignedVorgangWithOpenWiedervorlagenPageLink(page: number): string { + return `${buildVorgangListPageLink(page, EMPTY_STRING)}&${VORGANG_LIST_NEXT_FRIST_PARAM}`; + } + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-views-filter.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-views-filter.cy.ts index 1d6b3a557cf6418ddf22a0704bee8529e38567e6..5d0b695073d068e82700811bcb501012c8e4ad59 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-views-filter.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-list/vorgang-views-filter.cy.ts @@ -5,812 +5,909 @@ import { NavigationE2EComponent } from 'apps/alfa-e2e/src/components/navigation/ import { VorgangListItemE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-item.e2e.component'; import { VorgangListE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-list.e2e.component'; import { VorgangSearchE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-search.e2e.component'; -import { VorgangViewE2EComponent, VorgangViewsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component'; -import { ClientAttributeNameE2E, VorgangE2E, VorgangStatusE2E } from 'apps/alfa-e2e/src/model/vorgang'; +import { + VorgangViewE2EComponent, + VorgangViewsE2EComponent, +} from 'apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component'; +import { + ClientAttributeNameE2E, + VorgangE2E, + VorgangStatusE2E, +} from 'apps/alfa-e2e/src/model/vorgang'; import { HeaderE2EComponent } from 'apps/alfa-e2e/src/page-objects/header.po'; import { MainPage, waitForSpinnerToDisappear } from 'apps/alfa-e2e/src/page-objects/main.po'; -import { isButtonToggleChecked, isButtonToggleNotChecked } from 'apps/alfa-e2e/src/support/angular.util'; +import { + isButtonToggleChecked, + isButtonToggleNotChecked, +} from 'apps/alfa-e2e/src/support/angular.util'; import { dropCollections, dropSearchIndex } from 'apps/alfa-e2e/src/support/cypress-helper'; -import { containClass, contains, enterWith, exist, haveLength, haveText, notContainClass } from 'apps/alfa-e2e/src/support/cypress.util'; +import { + containClass, + contains, + enterWith, + exist, + haveLength, + haveText, + notContainClass, +} from 'apps/alfa-e2e/src/support/cypress.util'; import { createDateToday } from 'apps/alfa-e2e/src/support/tech.util'; -import { getUserManagerUserSabine, getUserSabineInternalId, initUsermanagerUsers, loginAsSabine } from 'apps/alfa-e2e/src/support/user-util'; -import { buildVorgang, createAlfaClientAttributes, createNextWiedervorlageFristClientAttribute, createVorgang, initSearchIndex, initVorgaenge, objectIds } from 'apps/alfa-e2e/src/support/vorgang-util'; +import { + getUserManagerUserSabine, + getUserSabineInternalId, + initUsermanagerUsers, + loginAsSabine, +} from 'apps/alfa-e2e/src/support/user-util'; +import { + buildVorgang, + createAlfaClientAttributes, + createNextWiedervorlageFristClientAttribute, + createVorgang, + initSearchIndex, + initVorgaenge, + objectIds, +} from 'apps/alfa-e2e/src/support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang views and filter', () => { - const mainPage: MainPage = new MainPage(); - - const header: HeaderE2EComponent = mainPage.getHeader(); - const vorgangSearch: VorgangSearchE2EComponent = header.getVorgangSearch(); - - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - - const views: VorgangViewsE2EComponent = mainPage.getViews(); - const neuView: VorgangViewE2EComponent = views.getNeu(); - const angenommenView: VorgangViewE2EComponent = views.getAngenommen(); - const inBearbeitungView: VorgangViewE2EComponent = views.getInBearbeitung(); - const beschiedenView: VorgangViewE2EComponent = views.getBeschieden(); - const abgeschlossenView: VorgangViewE2EComponent = views.getAbgeschlossen(); - const verworfenView: VorgangViewE2EComponent = views.getVerworfen(); - const zuLoeschenView: VorgangViewE2EComponent = views.getZuLoeschen(); - const wiedervorlagenView: VorgangViewE2EComponent = views.getWiedervorlagen(); - const vorgangListView: VorgangViewE2EComponent = views.getVorgangList(); - const sucheView: VorgangViewE2EComponent = views.getSuche(); - - const navigation: NavigationE2EComponent = mainPage.getNavigation(); - - const vorgangNeuAssigned: VorgangE2E = { ...createVorgang(), name: 'VorgangNeuAssigned', status: VorgangStatusE2E.NEU, assignedTo: getUserSabineInternalId() }; - const vorgangNeuUnassigned: VorgangE2E = { ...buildVorgang(objectIds[0], 'VorgangNeuUnassigned'), status: VorgangStatusE2E.NEU }; - - const vorgangAngenommenAssigned: VorgangE2E = { ...buildVorgang(objectIds[1], 'VorgangAngenommenAssigned'), status: VorgangStatusE2E.ANGENOMMEN, assignedTo: getUserSabineInternalId() }; - const vorgangAngenommenUnassigned: VorgangE2E = { ...buildVorgang(objectIds[2], 'VorgangAngenommenUnassigned'), status: VorgangStatusE2E.ANGENOMMEN, - clientAttributes: createAlfaClientAttributes(ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, createNextWiedervorlageFristClientAttribute(createDateToday())) }; - - const vorgangInBearbeitungAssigned: VorgangE2E = { ...buildVorgang(objectIds[3], 'VorgangInBearbeitungAssigned'), status: VorgangStatusE2E.IN_BEARBEITUNG, assignedTo: getUserSabineInternalId() }; - const vorgangInBearbeitungUnassigned: VorgangE2E = { ...buildVorgang(objectIds[4], 'VorgangInBearbeitungUnassigned'), status: VorgangStatusE2E.IN_BEARBEITUNG }; - - const vorgangBeschiedenAssigned: VorgangE2E = { ...buildVorgang(objectIds[5], 'VorgangBeschiedenAssigned'), status: VorgangStatusE2E.BESCHIEDEN, assignedTo: getUserSabineInternalId() }; - const vorgangBeschiedenUnassigned: VorgangE2E = { ...buildVorgang(objectIds[6], 'VorgangBeschiedenUnassigned'), status: VorgangStatusE2E.BESCHIEDEN }; - - const vorgangAbgeschlossenAssigned: VorgangE2E = { ...buildVorgang(objectIds[7], 'VorgangAbgeschlossenAssigned'), status: VorgangStatusE2E.ABGESCHLOSSEN, assignedTo: getUserSabineInternalId(), - clientAttributes: createAlfaClientAttributes(ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, createNextWiedervorlageFristClientAttribute(createDateToday())) }; - - const vorgangAbgeschlossenUnassigned: VorgangE2E = { ...buildVorgang(objectIds[8], 'VorgangAbgeschlossenUnassigned'), status: VorgangStatusE2E.ABGESCHLOSSEN }; - - const vorgangVerworfenAssigned: VorgangE2E = { ...buildVorgang(objectIds[9], 'VorgangVerworfenAssigned'), status: VorgangStatusE2E.VERWORFEN, assignedTo: getUserSabineInternalId() }; - const vorgangVerworfenUnassigned: VorgangE2E = { ...buildVorgang(objectIds[10], 'VorgangVerworfenUnassigned'), status: VorgangStatusE2E.VERWORFEN }; - - const vorgangZuLoeschenAssigned: VorgangE2E = { ...buildVorgang(objectIds[11], 'VorgangZuLoeschenAssigned'), status: VorgangStatusE2E.ZU_LOESCHEN, assignedTo: getUserSabineInternalId() }; - const vorgangZuLoeschenUnassigned: VorgangE2E = { ...buildVorgang(objectIds[12], 'VorgangZuLoeschenUnassigned'), status: VorgangStatusE2E.ZU_LOESCHEN }; - - const vorgangNeuAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangNeuAssigned.name); - const vorgangNeuUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangNeuUnassigned.name); - - const vorgangAngenommenAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangAngenommenAssigned.name); - const vorgangAngenommenUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangAngenommenUnassigned.name); - - const vorgangInBearbeitungAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangInBearbeitungAssigned.name); - const vorgangInBearbeitungUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangInBearbeitungUnassigned.name); - - const vorgangBeschiedenAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangBeschiedenAssigned.name); - const vorgangBeschiedenUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangBeschiedenUnassigned.name); - - const vorgangAbgeschlossenAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangAbgeschlossenAssigned.name); - const vorgangAbgeschlossenUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangAbgeschlossenUnassigned.name); - - const vorgangVerworfenAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangVerworfenAssigned.name); - const vorgangVerworfenUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangVerworfenUnassigned.name); - - const vorgangZuLoeschenAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangZuLoeschenAssigned.name); - const vorgangZuLoeschenUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem(vorgangZuLoeschenUnassigned.name); - - const LIST_SIZE: number = 14; - - before(() => { - const vorgaenge: VorgangE2E[] = [vorgangNeuAssigned, vorgangNeuUnassigned, - vorgangAngenommenAssigned, vorgangAngenommenUnassigned, - vorgangInBearbeitungAssigned, vorgangInBearbeitungUnassigned, - vorgangBeschiedenAssigned, vorgangBeschiedenUnassigned, - vorgangAbgeschlossenAssigned, vorgangAbgeschlossenUnassigned, - vorgangVerworfenAssigned, vorgangVerworfenUnassigned, - vorgangZuLoeschenAssigned, vorgangZuLoeschenUnassigned - ]; - initVorgaenge(vorgaenge); - - initSearchIndex(vorgaenge); - initUsermanagerUsers([getUserManagerUserSabine()]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - }) - - after(() => { - dropCollections(); - dropSearchIndex(); - }) - - describe('Initial', () => { - - describe('on load', () => { - - it('should show vorgaenge in vorgangList', () => { - exist(vorgangList.getRoot()); - - haveLength(vorgangList.getItems(), LIST_SIZE); - }) - }) - - describe('filter', () => { - - it('Alle should be selected', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - }) - - it('Meine Vorgänge should not be selected', () => { - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - }) - - it('Nicht zugewiesen should not be selected', () => { - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - }) - - describe('view', () => { - - it('vorgangList should be selected', () => { - isSelected(vorgangListView.getRoot()); - }) - - it('other should be unselected', () => { - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(sucheView.getRoot()); - }) - - describe('count for', () => { - - it('neu', () => { - contains(neuView.getCount(), '2'); - }) - - it('angenommen', () => { - contains(angenommenView.getCount(), '2'); - }) - - it('in_bearbeitung', () => { - contains(inBearbeitungView.getCount(), '2'); - }) - - it('beschieden', () => { - contains(beschiedenView.getCount(), '2'); - }) - - it('abgeschlossen', () => { - contains(abgeschlossenView.getCount(), '2'); - }) - - it('verworfen', () => { - contains(verworfenView.getCount(), '2'); - }) - - it('zu löschen', () => { - contains(zuLoeschenView.getCount(), '2'); - }) - - it('wiedervorlagen', () => { - contains(wiedervorlagenView.getCount(), '2'); - }) - }) - }) - }) - - describe('Select view', () => { - - describe('Neu', () => { - - it('should set selected after click', () => { - neuView.getRoot().click(); - waitForSpinnerToDisappear(); - - isSelected(neuView.getRoot()); - }) - - it('should unselect other views', () => { - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - isNotSelected(sucheView.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should filter List', () => { - haveLength(vorgangList.getItems(), 2); - exist(vorgangNeuAssignedInList.getRoot()); - exist(vorgangNeuUnassignedInList.getRoot()); - }) - }) - - describe('Angenommen', () => { - - it('should set selected after click', () => { - angenommenView.getRoot().click(); - waitForSpinnerToDisappear(); - - isSelected(angenommenView.getRoot()); - }) - - it('should unselect other views', () => { - isNotSelected(neuView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - isNotSelected(sucheView.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should filter List', () => { - haveLength(vorgangList.getItems(), 2); - exist(vorgangAngenommenAssignedInList.getRoot()); - exist(vorgangAngenommenUnassignedInList.getRoot()); - }) - }) - - describe('In Bearbeitung', () => { - - it('should set selected after click', () => { - inBearbeitungView.getRoot().click(); - waitForSpinnerToDisappear(); - - isSelected(inBearbeitungView.getRoot()); - }) - - it('should unselect other views', () => { - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - isNotSelected(sucheView.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should filter List', () => { - haveLength(vorgangList.getItems(), LIST_SIZE - 12); - exist(vorgangInBearbeitungAssignedInList.getRoot()); - exist(vorgangInBearbeitungUnassignedInList.getRoot()); - }) - }) - - describe('Beschieden', () => { - - it('should set selected after click', () => { - beschiedenView.getRoot().click(); - waitForSpinnerToDisappear(); - - isSelected(beschiedenView.getRoot()); - }) - - it('should unselect other views', () => { - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - isNotSelected(sucheView.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should filter List', () => { - haveLength(vorgangList.getItems(), LIST_SIZE - 12); - exist(vorgangBeschiedenAssignedInList.getRoot()); - exist(vorgangBeschiedenUnassignedInList.getRoot()); - }) - }) - - describe('Abgeschlossen', () => { - - it('should set selected after click', () => { - abgeschlossenView.getRoot().click(); - waitForSpinnerToDisappear(); - - isSelected(abgeschlossenView.getRoot()); - }) - - it('should unselect other views', () => { - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - isNotSelected(sucheView.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should filter List', () => { - haveLength(vorgangList.getItems(), LIST_SIZE - 12); - exist(vorgangAbgeschlossenAssignedInList.getRoot()); - exist(vorgangAbgeschlossenUnassignedInList.getRoot()); - }) - }) - - describe('Verworfen', () => { - - it('should set selected after click', () => { - verworfenView.getRoot().click(); - waitForSpinnerToDisappear(); - - isSelected(verworfenView.getRoot()); - }) - - it('should unselect other views', () => { - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - isNotSelected(sucheView.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should filter List', () => { - haveLength(vorgangList.getItems(), LIST_SIZE - 12); - exist(vorgangVerworfenAssignedInList.getRoot()); - exist(vorgangVerworfenUnassignedInList.getRoot()); - }) - }) - - describe('Zu Löschen', () => { - - it('should set selected after click', () => { - zuLoeschenView.getRoot().click(); - waitForSpinnerToDisappear(); - - isSelected(zuLoeschenView.getRoot()); - }) - - it('should unselect other views', () => { - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - isNotSelected(sucheView.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should filter List', () => { - haveLength(vorgangList.getItems(), LIST_SIZE - 12); - exist(vorgangZuLoeschenAssignedInList.getRoot()); - exist(vorgangZuLoeschenUnassignedInList.getRoot()); - }) - }) - - describe('Wiedervorlagen', () => { - - it('should set selected after click', () => { - wiedervorlagenView.getRoot().click(); - waitForSpinnerToDisappear(); - - isSelected(wiedervorlagenView.getRoot()); - }) - - it('should unselect other views', () => { - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - isNotSelected(sucheView.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should filter List', () => { - haveLength(vorgangList.getItems(), 2); - - exist(vorgangAngenommenUnassignedInList.getRoot()); - exist(vorgangAbgeschlossenAssignedInList.getRoot()); - }) - }) - - describe('VorgangList', () => { - - it('should set selected after click', () => { - vorgangListView.getRoot().click(); - waitForSpinnerToDisappear(); - - isSelected(vorgangListView.getRoot()); - }) - - it('should unselect other views', () => { - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(sucheView.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should show full List', () => { - haveLength(vorgangList.getItems(), LIST_SIZE); - }) - }) - - describe('Suche', () => { - - it('should set selected after click', () => { - sucheView.getRoot().click(); - waitForSpinnerToDisappear(); - - isSelected(sucheView.getRoot()); - }) - - it('should unselect other views', () => { - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should show message', () => { - haveText(vorgangList.getEmptySucheMessage(), 'Bitte geben Sie einen Suchbegriff ein.'); - }) - }) - }) - - describe('Select Filter', () => { - - describe('Nicht zugewiesen', () => { - - it('should set selected after click', () => { - navigation.getNichtZugewiesenFilter().click(); - waitForSpinnerToDisappear(); - - isButtonToggleChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should unselect Meine Vorgänge', () => { - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - }) - - it('should keep Alle unselected', () => { - isButtonToggleNotChecked(navigation.getAlleFilter()); - }) - - it('should keep view selection', () => { - isSelected(sucheView.getRoot()); - - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - }) - - it('should show message', () => { - haveText(vorgangList.getEmptySucheMessage(), 'Bitte geben Sie einen Suchbegriff ein.'); - }) - }) - - describe('Meine Vorgänge', () => { - - it('should set selected after click', () => { - navigation.getMeineVorgaengeFilter().click(); - waitForSpinnerToDisappear(); - - isButtonToggleChecked(navigation.getMeineVorgaengeFilter()); - }) - - it('should unselect Alle', () => { - isButtonToggleNotChecked(navigation.getAlleFilter()); - }) - - it('should keep view selection', () => { - isSelected(sucheView.getRoot()); - - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - }) - - it('should show message', () => { - haveText(vorgangList.getEmptySucheMessage(), 'Bitte geben Sie einen Suchbegriff ein.'); - }) - }) - }) - - describe('Suche', () => { - - describe('on execute/enter with Meine Vorgänge filter selected', () => { - - it('should show filtered list', () => { - doSearch('Angenommen'); - waitForSpinnerToDisappear(); - - haveLength(vorgangList.getItems(), 1); - exist(vorgangAngenommenAssignedInList.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getMeineVorgaengeFilter()); - isButtonToggleNotChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should keep view selection', () => { - isSelected(sucheView.getRoot()); - - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - }) - }) - - describe('on Alle filter selection', () => { - - it('should show filtered list', () => { - navigation.getAlleFilter().click(); - waitForSpinnerToDisappear(); - - haveLength(vorgangList.getItems(), 2); - exist(vorgangAngenommenAssignedInList.getRoot()); - exist(vorgangAngenommenUnassignedInList.getRoot()); - }) - - it('should select Alle filter', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - }) - - it('should unselect Meine Vorgänge filter', () => { - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - }) - - it('should keep view selection', () => { - isSelected(sucheView.getRoot()); - - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - }) - }) - - describe('on Nicht zugewiesen filter selection', () => { - - it('should show filtered list', () => { - navigation.getNichtZugewiesenFilter().click(); - waitForSpinnerToDisappear(); - - haveLength(vorgangList.getItems(), 1); - exist(vorgangAngenommenUnassignedInList.getRoot()); - }) - - it('should show Nicht zugewiesen as selected', () => { - isButtonToggleChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should unselect Alle filter', () => { - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - }) - - it('should keep Meine Vorgänge unselected', () => { - isButtonToggleNotChecked(navigation.getAlleFilter()); - }) - - it('should keep view selection', () => { - isSelected(sucheView.getRoot()); - - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - }) - }) - - describe('on other search execution', () => { - - it('should show filtered list', () => { - navigation.getAlleFilter().click(); - waitForSpinnerToDisappear(); - - doSearch('VorgangA'); - waitForSpinnerToDisappear(); - - haveLength(vorgangList.getItems(), 4); - exist(vorgangAngenommenAssignedInList.getRoot()); - exist(vorgangAngenommenUnassignedInList.getRoot()); - exist(vorgangAbgeschlossenAssignedInList.getRoot()); - exist(vorgangAbgeschlossenUnassignedInList.getRoot()); - }) - - it('should keep filter selection', () => { - isButtonToggleChecked(navigation.getAlleFilter()); - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - }) - - it('should unselect Meine Vorgänge filter', () => { - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - }) - - it('should keep view selection', () => { - isSelected(sucheView.getRoot()); - - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - }) - }) - - describe('on Meine Vorgänge filter selection', () => { - - it('should show filtered list', () => { - navigation.getMeineVorgaengeFilter().click(); - waitForSpinnerToDisappear(); - - haveLength(vorgangList.getItems(), 2); - exist(vorgangAngenommenAssignedInList.getRoot()); - exist(vorgangAbgeschlossenAssignedInList.getRoot()); - }) - - it('should select', () => { - isButtonToggleChecked(navigation.getMeineVorgaengeFilter()); - }) - - it('should unselect Alle filter', () => { - isButtonToggleNotChecked(navigation.getAlleFilter()); - }) - - it('should keep view selection', () => { - isSelected(sucheView.getRoot()); - - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - }) - }) - - describe('on Nicht zugewiesen filter selection', () => { - - it('should show filtered list', () => { - navigation.getNichtZugewiesenFilter().click(); - waitForSpinnerToDisappear(); - - haveLength(vorgangList.getItems(), 2); - exist(vorgangAngenommenUnassignedInList.getRoot()); - exist(vorgangAbgeschlossenUnassignedInList.getRoot()); - }) - - it('should select', () => { - isButtonToggleChecked(navigation.getNichtZugewiesenFilter()); - }) - - it('should unselect Meine Vorgänge filter', () => { - isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); - }) - - it('should keep filter unselected', () => { - isButtonToggleNotChecked(navigation.getAlleFilter()); - }) - - it('should keep view selection', () => { - isSelected(sucheView.getRoot()); - - isNotSelected(neuView.getRoot()); - isNotSelected(angenommenView.getRoot()); - isNotSelected(inBearbeitungView.getRoot()); - isNotSelected(beschiedenView.getRoot()); - isNotSelected(abgeschlossenView.getRoot()); - isNotSelected(verworfenView.getRoot()); - isNotSelected(zuLoeschenView.getRoot()); - isNotSelected(vorgangListView.getRoot()); - }) - }) - }) - - function doSearch(searchString: string): void { - enterWith(vorgangSearch.getInput(), searchString); - } - - function isNotSelected(element){ - notContainClass(element, 'selected'); - } - - function isSelected(element){ - containClass(element, 'selected'); - } -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + + const header: HeaderE2EComponent = mainPage.getHeader(); + const vorgangSearch: VorgangSearchE2EComponent = header.getVorgangSearch(); + + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const views: VorgangViewsE2EComponent = mainPage.getViews(); + const neuView: VorgangViewE2EComponent = views.getNeu(); + const angenommenView: VorgangViewE2EComponent = views.getAngenommen(); + const inBearbeitungView: VorgangViewE2EComponent = views.getInBearbeitung(); + const beschiedenView: VorgangViewE2EComponent = views.getBeschieden(); + const abgeschlossenView: VorgangViewE2EComponent = views.getAbgeschlossen(); + const verworfenView: VorgangViewE2EComponent = views.getVerworfen(); + const zuLoeschenView: VorgangViewE2EComponent = views.getZuLoeschen(); + const wiedervorlagenView: VorgangViewE2EComponent = views.getWiedervorlagen(); + const vorgangListView: VorgangViewE2EComponent = views.getVorgangList(); + const sucheView: VorgangViewE2EComponent = views.getSuche(); + + const navigation: NavigationE2EComponent = mainPage.getNavigation(); + + const vorgangNeuAssigned: VorgangE2E = { + ...createVorgang(), + name: 'VorgangNeuAssigned', + status: VorgangStatusE2E.NEU, + assignedTo: getUserSabineInternalId(), + }; + const vorgangNeuUnassigned: VorgangE2E = { + ...buildVorgang(objectIds[0], 'VorgangNeuUnassigned'), + status: VorgangStatusE2E.NEU, + }; + + const vorgangAngenommenAssigned: VorgangE2E = { + ...buildVorgang(objectIds[1], 'VorgangAngenommenAssigned'), + status: VorgangStatusE2E.ANGENOMMEN, + assignedTo: getUserSabineInternalId(), + }; + const vorgangAngenommenUnassigned: VorgangE2E = { + ...buildVorgang(objectIds[2], 'VorgangAngenommenUnassigned'), + status: VorgangStatusE2E.ANGENOMMEN, + clientAttributes: createAlfaClientAttributes( + ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, + createNextWiedervorlageFristClientAttribute(createDateToday()), + ), + }; + + const vorgangInBearbeitungAssigned: VorgangE2E = { + ...buildVorgang(objectIds[3], 'VorgangInBearbeitungAssigned'), + status: VorgangStatusE2E.IN_BEARBEITUNG, + assignedTo: getUserSabineInternalId(), + }; + const vorgangInBearbeitungUnassigned: VorgangE2E = { + ...buildVorgang(objectIds[4], 'VorgangInBearbeitungUnassigned'), + status: VorgangStatusE2E.IN_BEARBEITUNG, + }; + + const vorgangBeschiedenAssigned: VorgangE2E = { + ...buildVorgang(objectIds[5], 'VorgangBeschiedenAssigned'), + status: VorgangStatusE2E.BESCHIEDEN, + assignedTo: getUserSabineInternalId(), + }; + const vorgangBeschiedenUnassigned: VorgangE2E = { + ...buildVorgang(objectIds[6], 'VorgangBeschiedenUnassigned'), + status: VorgangStatusE2E.BESCHIEDEN, + }; + + const vorgangAbgeschlossenAssigned: VorgangE2E = { + ...buildVorgang(objectIds[7], 'VorgangAbgeschlossenAssigned'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + assignedTo: getUserSabineInternalId(), + clientAttributes: createAlfaClientAttributes( + ClientAttributeNameE2E.NEXT_WIEDERVORLAGE_FRIST, + createNextWiedervorlageFristClientAttribute(createDateToday()), + ), + }; + + const vorgangAbgeschlossenUnassigned: VorgangE2E = { + ...buildVorgang(objectIds[8], 'VorgangAbgeschlossenUnassigned'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + + const vorgangVerworfenAssigned: VorgangE2E = { + ...buildVorgang(objectIds[9], 'VorgangVerworfenAssigned'), + status: VorgangStatusE2E.VERWORFEN, + assignedTo: getUserSabineInternalId(), + }; + const vorgangVerworfenUnassigned: VorgangE2E = { + ...buildVorgang(objectIds[10], 'VorgangVerworfenUnassigned'), + status: VorgangStatusE2E.VERWORFEN, + }; + + const vorgangZuLoeschenAssigned: VorgangE2E = { + ...buildVorgang(objectIds[11], 'VorgangZuLoeschenAssigned'), + status: VorgangStatusE2E.ZU_LOESCHEN, + assignedTo: getUserSabineInternalId(), + }; + const vorgangZuLoeschenUnassigned: VorgangE2E = { + ...buildVorgang(objectIds[12], 'VorgangZuLoeschenUnassigned'), + status: VorgangStatusE2E.ZU_LOESCHEN, + }; + + const vorgangNeuAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangNeuAssigned.name, + ); + const vorgangNeuUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangNeuUnassigned.name, + ); + + const vorgangAngenommenAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangAngenommenAssigned.name, + ); + const vorgangAngenommenUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangAngenommenUnassigned.name, + ); + + const vorgangInBearbeitungAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangInBearbeitungAssigned.name, + ); + const vorgangInBearbeitungUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangInBearbeitungUnassigned.name, + ); + + const vorgangBeschiedenAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangBeschiedenAssigned.name, + ); + const vorgangBeschiedenUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangBeschiedenUnassigned.name, + ); + + const vorgangAbgeschlossenAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangAbgeschlossenAssigned.name, + ); + const vorgangAbgeschlossenUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangAbgeschlossenUnassigned.name, + ); + + const vorgangVerworfenAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangVerworfenAssigned.name, + ); + const vorgangVerworfenUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangVerworfenUnassigned.name, + ); + + const vorgangZuLoeschenAssignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangZuLoeschenAssigned.name, + ); + const vorgangZuLoeschenUnassignedInList: VorgangListItemE2EComponent = vorgangList.getListItem( + vorgangZuLoeschenUnassigned.name, + ); + + const LIST_SIZE: number = 14; + + before(() => { + const vorgaenge: VorgangE2E[] = [ + vorgangNeuAssigned, + vorgangNeuUnassigned, + vorgangAngenommenAssigned, + vorgangAngenommenUnassigned, + vorgangInBearbeitungAssigned, + vorgangInBearbeitungUnassigned, + vorgangBeschiedenAssigned, + vorgangBeschiedenUnassigned, + vorgangAbgeschlossenAssigned, + vorgangAbgeschlossenUnassigned, + vorgangVerworfenAssigned, + vorgangVerworfenUnassigned, + vorgangZuLoeschenAssigned, + vorgangZuLoeschenUnassigned, + ]; + initVorgaenge(vorgaenge); + + initSearchIndex(vorgaenge); + initUsermanagerUsers([getUserManagerUserSabine()]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + }); + + after(() => { + dropCollections(); + dropSearchIndex(); + }); + + describe('Initial', () => { + describe('on load', () => { + it('should show vorgaenge in vorgangList', () => { + exist(vorgangList.getRoot()); + + haveLength(vorgangList.getItems(), LIST_SIZE); + }); + }); + + describe('filter', () => { + it('Alle should be selected', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + }); + + it('Meine Vorgänge should not be selected', () => { + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + }); + + it('Nicht zugewiesen should not be selected', () => { + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + }); + + describe('view', () => { + it('vorgangList should be selected', () => { + isSelected(vorgangListView.getRoot()); + }); + + it('other should be unselected', () => { + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(sucheView.getRoot()); + }); + + describe('count for', () => { + it('neu', () => { + contains(neuView.getCount(), '2'); + }); + + it('angenommen', () => { + contains(angenommenView.getCount(), '2'); + }); + + it('in_bearbeitung', () => { + contains(inBearbeitungView.getCount(), '2'); + }); + + it('beschieden', () => { + contains(beschiedenView.getCount(), '2'); + }); + + it('abgeschlossen', () => { + contains(abgeschlossenView.getCount(), '2'); + }); + + it('verworfen', () => { + contains(verworfenView.getCount(), '2'); + }); + + it('zu löschen', () => { + contains(zuLoeschenView.getCount(), '2'); + }); + + it('wiedervorlagen', () => { + contains(wiedervorlagenView.getCount(), '2'); + }); + }); + }); + }); + + describe('Select view', () => { + describe('Neu', () => { + it('should set selected after click', () => { + neuView.getRoot().click(); + waitForSpinnerToDisappear(); + + isSelected(neuView.getRoot()); + }); + + it('should unselect other views', () => { + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + isNotSelected(sucheView.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should filter List', () => { + haveLength(vorgangList.getItems(), 2); + exist(vorgangNeuAssignedInList.getRoot()); + exist(vorgangNeuUnassignedInList.getRoot()); + }); + }); + + describe('Angenommen', () => { + it('should set selected after click', () => { + angenommenView.getRoot().click(); + waitForSpinnerToDisappear(); + + isSelected(angenommenView.getRoot()); + }); + + it('should unselect other views', () => { + isNotSelected(neuView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + isNotSelected(sucheView.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should filter List', () => { + haveLength(vorgangList.getItems(), 2); + exist(vorgangAngenommenAssignedInList.getRoot()); + exist(vorgangAngenommenUnassignedInList.getRoot()); + }); + }); + + describe('In Bearbeitung', () => { + it('should set selected after click', () => { + inBearbeitungView.getRoot().click(); + waitForSpinnerToDisappear(); + + isSelected(inBearbeitungView.getRoot()); + }); + + it('should unselect other views', () => { + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + isNotSelected(sucheView.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should filter List', () => { + haveLength(vorgangList.getItems(), LIST_SIZE - 12); + exist(vorgangInBearbeitungAssignedInList.getRoot()); + exist(vorgangInBearbeitungUnassignedInList.getRoot()); + }); + }); + + describe('Beschieden', () => { + it('should set selected after click', () => { + beschiedenView.getRoot().click(); + waitForSpinnerToDisappear(); + + isSelected(beschiedenView.getRoot()); + }); + + it('should unselect other views', () => { + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + isNotSelected(sucheView.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should filter List', () => { + haveLength(vorgangList.getItems(), LIST_SIZE - 12); + exist(vorgangBeschiedenAssignedInList.getRoot()); + exist(vorgangBeschiedenUnassignedInList.getRoot()); + }); + }); + + describe('Abgeschlossen', () => { + it('should set selected after click', () => { + abgeschlossenView.getRoot().click(); + waitForSpinnerToDisappear(); + + isSelected(abgeschlossenView.getRoot()); + }); + + it('should unselect other views', () => { + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + isNotSelected(sucheView.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should filter List', () => { + haveLength(vorgangList.getItems(), LIST_SIZE - 12); + exist(vorgangAbgeschlossenAssignedInList.getRoot()); + exist(vorgangAbgeschlossenUnassignedInList.getRoot()); + }); + }); + + describe('Verworfen', () => { + it('should set selected after click', () => { + verworfenView.getRoot().click(); + waitForSpinnerToDisappear(); + + isSelected(verworfenView.getRoot()); + }); + + it('should unselect other views', () => { + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + isNotSelected(sucheView.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should filter List', () => { + haveLength(vorgangList.getItems(), LIST_SIZE - 12); + exist(vorgangVerworfenAssignedInList.getRoot()); + exist(vorgangVerworfenUnassignedInList.getRoot()); + }); + }); + + describe('Zu Löschen', () => { + it('should set selected after click', () => { + zuLoeschenView.getRoot().click(); + waitForSpinnerToDisappear(); + + isSelected(zuLoeschenView.getRoot()); + }); + + it('should unselect other views', () => { + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + isNotSelected(sucheView.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should filter List', () => { + haveLength(vorgangList.getItems(), LIST_SIZE - 12); + exist(vorgangZuLoeschenAssignedInList.getRoot()); + exist(vorgangZuLoeschenUnassignedInList.getRoot()); + }); + }); + + describe('Wiedervorlagen', () => { + it('should set selected after click', () => { + wiedervorlagenView.getRoot().click(); + waitForSpinnerToDisappear(); + + isSelected(wiedervorlagenView.getRoot()); + }); + + it('should unselect other views', () => { + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + isNotSelected(sucheView.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should filter List', () => { + haveLength(vorgangList.getItems(), 2); + + exist(vorgangAngenommenUnassignedInList.getRoot()); + exist(vorgangAbgeschlossenAssignedInList.getRoot()); + }); + }); + + describe('VorgangList', () => { + it('should set selected after click', () => { + vorgangListView.getRoot().click(); + waitForSpinnerToDisappear(); + + isSelected(vorgangListView.getRoot()); + }); + + it('should unselect other views', () => { + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(sucheView.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should show full List', () => { + haveLength(vorgangList.getItems(), LIST_SIZE); + }); + }); + + describe('Suche', () => { + it('should set selected after click', () => { + sucheView.getRoot().click(); + waitForSpinnerToDisappear(); + + isSelected(sucheView.getRoot()); + }); + + it('should unselect other views', () => { + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should show message', () => { + haveText(vorgangList.getEmptySucheMessage(), 'Bitte geben Sie einen Suchbegriff ein.'); + }); + }); + }); + + describe('Select Filter', () => { + describe('Nicht zugewiesen', () => { + it('should set selected after click', () => { + navigation.getNichtZugewiesenFilter().click(); + waitForSpinnerToDisappear(); + + isButtonToggleChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should unselect Meine Vorgänge', () => { + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + }); + + it('should keep Alle unselected', () => { + isButtonToggleNotChecked(navigation.getAlleFilter()); + }); + + it('should keep view selection', () => { + isSelected(sucheView.getRoot()); + + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + }); + + it('should show message', () => { + haveText(vorgangList.getEmptySucheMessage(), 'Bitte geben Sie einen Suchbegriff ein.'); + }); + }); + + describe('Meine Vorgänge', () => { + it('should set selected after click', () => { + navigation.getMeineVorgaengeFilter().click(); + waitForSpinnerToDisappear(); + + isButtonToggleChecked(navigation.getMeineVorgaengeFilter()); + }); + + it('should unselect Alle', () => { + isButtonToggleNotChecked(navigation.getAlleFilter()); + }); + + it('should keep view selection', () => { + isSelected(sucheView.getRoot()); + + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + }); + + it('should show message', () => { + haveText(vorgangList.getEmptySucheMessage(), 'Bitte geben Sie einen Suchbegriff ein.'); + }); + }); + }); + + describe('Suche', () => { + describe('on execute/enter with Meine Vorgänge filter selected', () => { + it('should show filtered list', () => { + doSearch('Angenommen'); + waitForSpinnerToDisappear(); + + haveLength(vorgangList.getItems(), 1); + exist(vorgangAngenommenAssignedInList.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getMeineVorgaengeFilter()); + isButtonToggleNotChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should keep view selection', () => { + isSelected(sucheView.getRoot()); + + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + }); + }); + + describe('on Alle filter selection', () => { + it('should show filtered list', () => { + navigation.getAlleFilter().click(); + waitForSpinnerToDisappear(); + + haveLength(vorgangList.getItems(), 2); + exist(vorgangAngenommenAssignedInList.getRoot()); + exist(vorgangAngenommenUnassignedInList.getRoot()); + }); + + it('should select Alle filter', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + }); + + it('should unselect Meine Vorgänge filter', () => { + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + }); + + it('should keep view selection', () => { + isSelected(sucheView.getRoot()); + + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + }); + }); + + describe('on Nicht zugewiesen filter selection', () => { + it('should show filtered list', () => { + navigation.getNichtZugewiesenFilter().click(); + waitForSpinnerToDisappear(); + + haveLength(vorgangList.getItems(), 1); + exist(vorgangAngenommenUnassignedInList.getRoot()); + }); + + it('should show Nicht zugewiesen as selected', () => { + isButtonToggleChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should unselect Alle filter', () => { + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + }); + + it('should keep Meine Vorgänge unselected', () => { + isButtonToggleNotChecked(navigation.getAlleFilter()); + }); + + it('should keep view selection', () => { + isSelected(sucheView.getRoot()); + + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + }); + }); + + describe('on other search execution', () => { + it('should show filtered list', () => { + navigation.getAlleFilter().click(); + waitForSpinnerToDisappear(); + + doSearch('VorgangA'); + waitForSpinnerToDisappear(); + + haveLength(vorgangList.getItems(), 4); + exist(vorgangAngenommenAssignedInList.getRoot()); + exist(vorgangAngenommenUnassignedInList.getRoot()); + exist(vorgangAbgeschlossenAssignedInList.getRoot()); + exist(vorgangAbgeschlossenUnassignedInList.getRoot()); + }); + + it('should keep filter selection', () => { + isButtonToggleChecked(navigation.getAlleFilter()); + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + }); + + it('should unselect Meine Vorgänge filter', () => { + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + }); + + it('should keep view selection', () => { + isSelected(sucheView.getRoot()); + + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + }); + }); + + describe('on Meine Vorgänge filter selection', () => { + it('should show filtered list', () => { + navigation.getMeineVorgaengeFilter().click(); + waitForSpinnerToDisappear(); + + haveLength(vorgangList.getItems(), 2); + exist(vorgangAngenommenAssignedInList.getRoot()); + exist(vorgangAbgeschlossenAssignedInList.getRoot()); + }); + + it('should select', () => { + isButtonToggleChecked(navigation.getMeineVorgaengeFilter()); + }); + + it('should unselect Alle filter', () => { + isButtonToggleNotChecked(navigation.getAlleFilter()); + }); + + it('should keep view selection', () => { + isSelected(sucheView.getRoot()); + + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + }); + }); + + describe('on Nicht zugewiesen filter selection', () => { + it('should show filtered list', () => { + navigation.getNichtZugewiesenFilter().click(); + waitForSpinnerToDisappear(); + + haveLength(vorgangList.getItems(), 2); + exist(vorgangAngenommenUnassignedInList.getRoot()); + exist(vorgangAbgeschlossenUnassignedInList.getRoot()); + }); + + it('should select', () => { + isButtonToggleChecked(navigation.getNichtZugewiesenFilter()); + }); + + it('should unselect Meine Vorgänge filter', () => { + isButtonToggleNotChecked(navigation.getMeineVorgaengeFilter()); + }); + + it('should keep filter unselected', () => { + isButtonToggleNotChecked(navigation.getAlleFilter()); + }); + + it('should keep view selection', () => { + isSelected(sucheView.getRoot()); + + isNotSelected(neuView.getRoot()); + isNotSelected(angenommenView.getRoot()); + isNotSelected(inBearbeitungView.getRoot()); + isNotSelected(beschiedenView.getRoot()); + isNotSelected(abgeschlossenView.getRoot()); + isNotSelected(verworfenView.getRoot()); + isNotSelected(zuLoeschenView.getRoot()); + isNotSelected(vorgangListView.getRoot()); + }); + }); + }); + + function doSearch(searchString: string): void { + enterWith(vorgangSearch.getInput(), searchString); + } + + function isNotSelected(element) { + notContainClass(element, 'selected'); + } + + function isSelected(element) { + containClass(element, 'selected'); + } +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-wiedervorlage/vorgang-wiedervorlage.routing.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-wiedervorlage/vorgang-wiedervorlage.routing.cy.ts index 84f1fee8bffd6573894345b56fe4a0ef99e96d3b..bb4ab1103485664c1f437d82dd204f19e5353c4e 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-wiedervorlage/vorgang-wiedervorlage.routing.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-wiedervorlage/vorgang-wiedervorlage.routing.cy.ts @@ -37,59 +37,59 @@ import { createVorgang, initVorgang } from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Detailansicht Wiedervorlage routing', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const vorgangPage: VorgangPage = new VorgangPage(); - const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); + const vorgangPage: VorgangPage = new VorgangPage(); + const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); - const vorgang: VorgangE2E = createVorgang(); + const vorgang: VorgangE2E = createVorgang(); - before(() => { - initVorgang(vorgang); + before(() => { + initVorgang(vorgang); - loginAsSabine(); + loginAsSabine(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - after(() => { - dropCollections(); - }) + after(() => { + dropCollections(); + }); - it('Open Vorgang-Detail-Page', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); + it('Open Vorgang-Detail-Page', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); - it('click on create wiedervorlage icon button should open page', () => { - vorgangPage.getSubnavigation().getWiedervorlageIconButton().click(); - waitForSpinnerToDisappear(); + it('click on create wiedervorlage icon button should open page', () => { + vorgangPage.getSubnavigation().getWiedervorlageIconButton().click(); + waitForSpinnerToDisappear(); - exist(wiedervorlagePage.getSubnavigation().getRoot()); - }) + exist(wiedervorlagePage.getSubnavigation().getRoot()); + }); - it('click on navigate back', () => { - wiedervorlagePage.getSubnavigation().navigateBack(); - waitForSpinnerToDisappear(); + it('click on navigate back', () => { + wiedervorlagePage.getSubnavigation().navigateBack(); + waitForSpinnerToDisappear(); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); - it('click on create wiedervorlage button should open page', () => { - vorgangPage.getWiedervorlagenContainer().getCreateWiedervorlageButton().click(); - waitForSpinnerToDisappear(); + it('click on create wiedervorlage button should open page', () => { + vorgangPage.getWiedervorlagenContainer().getCreateWiedervorlageButton().click(); + waitForSpinnerToDisappear(); - exist(wiedervorlagePage.getSubnavigation().getRoot()); - }) + exist(wiedervorlagePage.getSubnavigation().getRoot()); + }); - it('click on navigate back', () => { - wiedervorlagePage.getSubnavigation().navigateBack(); - waitForSpinnerToDisappear(); + it('click on navigate back', () => { + wiedervorlagePage.getSubnavigation().navigateBack(); + waitForSpinnerToDisappear(); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-wiedervorlage/vorgang.wiedervorlage-list.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-wiedervorlage/vorgang.wiedervorlage-list.cy.ts index 1f74abbe5392ae7ef76788d76b60795bb9286da8..84f47a6549307440173aad0237c835a0f3e6dcbb 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-wiedervorlage/vorgang.wiedervorlage-list.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/vorgang-wiedervorlage/vorgang.wiedervorlage-list.cy.ts @@ -25,7 +25,11 @@ import { registerLocaleData } from '@angular/common'; import localeDe from '@angular/common/locales/de'; import localeDeExtra from '@angular/common/locales/extra/de'; import { VorgangAttachedItemE2E } from 'apps/alfa-e2e/src/model/vorgang-attached-item'; -import { createDateInTheFuture, createDateInThePast, createDateToday } from 'apps/alfa-e2e/src/support/tech.util'; +import { + createDateInTheFuture, + createDateInThePast, + createDateToday, +} from 'apps/alfa-e2e/src/support/tech.util'; import { initVorgangAttachedItem } from 'apps/alfa-e2e/src/support/vorgang-attached-item-util'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; import { WiedervorlageInVorgangE2EComponent } from '../../../components/wiedervorlage/wiedervorlage-in-vorgang.e2e.component'; @@ -38,127 +42,171 @@ import { dropCollections } from '../../../support/cypress-helper'; import { containClass, exist, notContainClass, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang, objectIds } from '../../../support/vorgang-util'; -import { createWiedervorlageAttachedItem, createWiedervorlageItem } from '../../../support/wiedervorlage-util'; +import { + createWiedervorlageAttachedItem, + createWiedervorlageItem, +} from '../../../support/wiedervorlage-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('Vorgang Wiedervorlagen List', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + + const vorgangPage: VorgangPage = new VorgangPage(); + const wiedervorlageInVorgangContainer: WiedervorlagenInVorgangE2EComponent = + vorgangPage.getWiedervorlagenContainer(); + + const vorgang: VorgangE2E = createVorgang(); + + const wiedervorlageFristToday: WiedervorlageE2E = { + ...createWiedervorlageItem('WiedervorlageFristToday'), + frist: createDateToday(), + }; + const vorgangAttachedItemWithWiedervorlageFristToday: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[0], vorgang._id.$oid), + item: wiedervorlageFristToday, + }; + + const wiedervorlageFristInThePast: WiedervorlageE2E = { + ...createWiedervorlageItem('WiedervorlageFristInThePast'), + frist: createDateInThePast(), + }; + const vorgangAttachedItemWithWiedervorlageFristInThePast: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[1], vorgang._id.$oid), + item: wiedervorlageFristInThePast, + }; + + const wiedervorlageFristInTheFuture: WiedervorlageE2E = { + ...createWiedervorlageItem('WiedervorlageFristInTheFuture'), + frist: createDateInTheFuture(), + }; + const vorgangAttachedItemWithWiedervorlageFristInThFuture: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[2], vorgang._id.$oid), + item: wiedervorlageFristInTheFuture, + }; + + const wiedervorlageFristIsDone: WiedervorlageE2E = { + ...createWiedervorlageItem('WiedervorlageFristIsDone'), + done: true, + }; + const vorgangAttachedItemWithWiedervorlageIsDone: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[3], vorgang._id.$oid), + item: wiedervorlageFristIsDone, + }; + + const wiedervorlageWithoutDetails: WiedervorlageE2E = { + ...createWiedervorlageItem('WiedervorlageWithoutDetail'), + beschreibung: '', + }; + const vorgangAttachedItemWithWiedervorlageWithoutDetails: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[4], vorgang._id.$oid), + item: wiedervorlageWithoutDetails, + }; + + before(() => { + initVorgang(vorgang); + + initVorgangAttachedItem([ + vorgangAttachedItemWithWiedervorlageFristToday, + vorgangAttachedItemWithWiedervorlageFristInThePast, + vorgangAttachedItemWithWiedervorlageFristInThFuture, + vorgangAttachedItemWithWiedervorlageIsDone, + vorgangAttachedItemWithWiedervorlageWithoutDetails, + ]); + + loginAsSabine(); + + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + it('navigate to vorgang detail', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + describe('check status on wiedervorlage', () => { + it('should show status yellow on frist today', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = + wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristToday.betreff); + + exist(wiedervorlage.getRoot()); + notContainClass(wiedervorlage.getStatus().getStatusDot(), 'red'); + containClass(wiedervorlage.getStatus().getStatusDot(), 'yellow'); + + exist(wiedervorlage.getExpandButton()); + }); + + it('should show status red on frist in the past', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = + wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristInThePast.betreff); + + exist(wiedervorlage.getRoot()); + containClass(wiedervorlage.getStatus().getStatusDot(), 'red'); + notContainClass(wiedervorlage.getStatus().getStatusDot(), 'yellow'); + + exist(wiedervorlage.getExpandButton()); + }); + + it('should show status grey on frist in the future', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = + wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristInTheFuture.betreff); + + exist(wiedervorlage.getRoot()); + notContainClass(wiedervorlage.getStatus().getStatusDot(), 'red'); + notContainClass(wiedervorlage.getStatus().getStatusDot(), 'yellow'); + + exist(wiedervorlage.getExpandButton()); + }); + + it('should show status white with check on frist is done', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = + wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristIsDone.betreff); + + exist(wiedervorlage.getRoot()); + containClass(wiedervorlage.getStatus().getStatusDot(), 'erledigt'); + + exist(wiedervorlage.getExpandButton()); + }); + }); + + describe('on wiedervorlage with detailinformation', () => { + it('should show expand button', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = + wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristToday.betreff); + + exist(wiedervorlage.getRoot()); + exist(wiedervorlage.getExpandButton()); + }); + + it('should show detail information', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = + wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristToday.betreff); + + exist(wiedervorlage.getRoot()); + exist(wiedervorlage.getExpandButton()); + + wiedervorlage.expandItem(); + + exist(wiedervorlage.getExpandable()); + }); + }); + + describe('on wiedervorlage without detailinformation', () => { + it('should not show expand button for details', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = vorgangPage + .getWiedervorlagenContainer() + .getWiedervorlage(wiedervorlageWithoutDetails.betreff); - const vorgangPage: VorgangPage = new VorgangPage(); - const wiedervorlageInVorgangContainer: WiedervorlagenInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer(); - - const vorgang: VorgangE2E = createVorgang(); - - const wiedervorlageFristToday: WiedervorlageE2E = { ...createWiedervorlageItem('WiedervorlageFristToday'), frist: createDateToday() }; - const vorgangAttachedItemWithWiedervorlageFristToday: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[0], vorgang._id.$oid), item: wiedervorlageFristToday }; - - - const wiedervorlageFristInThePast: WiedervorlageE2E = { ...createWiedervorlageItem('WiedervorlageFristInThePast'), frist: createDateInThePast() }; - const vorgangAttachedItemWithWiedervorlageFristInThePast: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[1], vorgang._id.$oid), item: wiedervorlageFristInThePast }; - - const wiedervorlageFristInTheFuture: WiedervorlageE2E = { ...createWiedervorlageItem('WiedervorlageFristInTheFuture'), frist: createDateInTheFuture() }; - const vorgangAttachedItemWithWiedervorlageFristInThFuture: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[2], vorgang._id.$oid), item: wiedervorlageFristInTheFuture }; - - const wiedervorlageFristIsDone: WiedervorlageE2E = { ...createWiedervorlageItem('WiedervorlageFristIsDone'), done: true }; - const vorgangAttachedItemWithWiedervorlageIsDone: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[3], vorgang._id.$oid), item: wiedervorlageFristIsDone }; - - const wiedervorlageWithoutDetails: WiedervorlageE2E = { ...createWiedervorlageItem('WiedervorlageWithoutDetail'), beschreibung: '' }; - const vorgangAttachedItemWithWiedervorlageWithoutDetails: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[4], vorgang._id.$oid), item: wiedervorlageWithoutDetails }; - - before(() => { - initVorgang(vorgang); - - initVorgangAttachedItem([vorgangAttachedItemWithWiedervorlageFristToday, vorgangAttachedItemWithWiedervorlageFristInThePast, vorgangAttachedItemWithWiedervorlageFristInThFuture, vorgangAttachedItemWithWiedervorlageIsDone, vorgangAttachedItemWithWiedervorlageWithoutDetails]); - - loginAsSabine(); - - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - it('navigate to vorgang detail', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - describe('check status on wiedervorlage', () => { - - it('should show status yellow on frist today', () => { - const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristToday.betreff); - - exist(wiedervorlage.getRoot()); - notContainClass(wiedervorlage.getStatus().getStatusDot(), 'red'); - containClass(wiedervorlage.getStatus().getStatusDot(), 'yellow'); - - exist(wiedervorlage.getExpandButton()); - }) - - it('should show status red on frist in the past', () => { - const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristInThePast.betreff); - - exist(wiedervorlage.getRoot()); - containClass(wiedervorlage.getStatus().getStatusDot(), 'red'); - notContainClass(wiedervorlage.getStatus().getStatusDot(), 'yellow'); - - exist(wiedervorlage.getExpandButton()); - }) - - it('should show status grey on frist in the future', () => { - const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristInTheFuture.betreff); - - exist(wiedervorlage.getRoot()); - notContainClass(wiedervorlage.getStatus().getStatusDot(), 'red'); - notContainClass(wiedervorlage.getStatus().getStatusDot(), 'yellow'); - - exist(wiedervorlage.getExpandButton()); - }) - - it('should show status white with check on frist is done', () => { - const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristIsDone.betreff); - - exist(wiedervorlage.getRoot()); - containClass(wiedervorlage.getStatus().getStatusDot(), 'erledigt'); - - exist(wiedervorlage.getExpandButton()); - }) - }) - - describe('on wiedervorlage with detailinformation', () => { - - it('should show expand button', () => { - const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristToday.betreff); - - exist(wiedervorlage.getRoot()); - exist(wiedervorlage.getExpandButton()); - }) - - it('should show detail information', () => { - const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageInVorgangContainer.getWiedervorlage(wiedervorlageFristToday.betreff); - - exist(wiedervorlage.getRoot()); - exist(wiedervorlage.getExpandButton()); - - wiedervorlage.expandItem(); - - exist(wiedervorlage.getExpandable()); - }) - }) - - describe('on wiedervorlage without detailinformation', () => { - - it('should not show expand button for details', () => { - const wiedervorlage: WiedervorlageInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer().getWiedervorlage(wiedervorlageWithoutDetails.betreff); - - exist(wiedervorlage.getRoot()); - notExist(wiedervorlage.getExpandButton()); - }) - }) -}); \ No newline at end of file + exist(wiedervorlage.getRoot()); + notExist(wiedervorlage.getExpandButton()); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.cy.ts index cf9423807780c8666f230ed655eec8f8ee86d541..8695369283e2aea462f895f89a179cb37f984899 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.cy.ts @@ -21,11 +21,18 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { AttachmentContainerE2EComponent, AttachmentListE2EComponent } from 'apps/alfa-e2e/src/components/attachment/attachment.e2e.component'; +import { + AttachmentContainerE2EComponent, + AttachmentListE2EComponent, +} from 'apps/alfa-e2e/src/components/attachment/attachment.e2e.component'; import { WiedervorlageSubnavigationE2EComponent } from 'apps/alfa-e2e/src/components/wiedervorlage/wiedervorlage-subnavigation'; import { BinaryFileSnackbarMessageE2E } from 'apps/alfa-e2e/src/model/binary-file'; import { WiedervorlageE2E } from 'apps/alfa-e2e/src/model/wiedervorlage'; -import { dropCollections, readFileFromDownloads, wait } from 'apps/alfa-e2e/src/support/cypress-helper'; +import { + dropCollections, + readFileFromDownloads, + wait, +} from 'apps/alfa-e2e/src/support/cypress-helper'; import { initVorgangAttachedItem } from 'apps/alfa-e2e/src/support/vorgang-attached-item-util'; import { SnackBarE2EComponent } from '../../../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../../../components/vorgang/vorgang-list.e2e.component'; @@ -35,280 +42,382 @@ import { VorgangE2E } from '../../../model/vorgang'; import { MainPage, waitForSpinnerToDisappear } from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { WiedervorlagePage } from '../../../page-objects/wiedervorlage.po'; -import { containClass, contains, exist, haveLength, notContainClass, notExist } from '../../../support/cypress.util'; -import { TEST_FILE_WITHOUT_CONTENT, TEST_FILE_WITH_CONTENT, TEST_FILE_WITH_CONTENT_46MB } from '../../../support/data.util'; +import { + containClass, + contains, + exist, + haveLength, + notContainClass, + notExist, +} from '../../../support/cypress.util'; +import { + TEST_FILE_WITHOUT_CONTENT, + TEST_FILE_WITH_CONTENT, + TEST_FILE_WITH_CONTENT_46MB, +} from '../../../support/data.util'; import { uploadEmptyFile, uploadFile } from '../../../support/file-upload'; import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang, objectIds } from '../../../support/vorgang-util'; -import { createWiedervorlageAttachedItem, createWiedervorlageItem } from '../../../support/wiedervorlage-util'; +import { + createWiedervorlageAttachedItem, + createWiedervorlageItem, +} from '../../../support/wiedervorlage-util'; describe.skip('Wiedervorlage attachments', () => { - const mainPage: MainPage = new MainPage(); + const mainPage: MainPage = new MainPage(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const vorgangPage: VorgangPage = new VorgangPage(); - const wiedervorlageContainerInVorgang = vorgangPage.getWiedervorlagenContainer(); + const vorgangPage: VorgangPage = new VorgangPage(); + const wiedervorlageContainerInVorgang = vorgangPage.getWiedervorlagenContainer(); - const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); - const wiedervorlageContainer: WiedervorlageE2EComponent = wiedervorlagePage.getWiedervorlageContainer(); - const attachmentContainer: AttachmentContainerE2EComponent = wiedervorlageContainer.getAttachmentContainer(); - const attachmentList: AttachmentListE2EComponent = attachmentContainer.getList(); - const subnavigation: WiedervorlageSubnavigationE2EComponent = wiedervorlagePage.getSubnavigation(); + const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); + const wiedervorlageContainer: WiedervorlageE2EComponent = + wiedervorlagePage.getWiedervorlageContainer(); + const attachmentContainer: AttachmentContainerE2EComponent = + wiedervorlageContainer.getAttachmentContainer(); + const attachmentList: AttachmentListE2EComponent = attachmentContainer.getList(); + const subnavigation: WiedervorlageSubnavigationE2EComponent = + wiedervorlagePage.getSubnavigation(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - const WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF: string = 'WiedervorlageWithAttachments'; + const WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF: string = 'WiedervorlageWithAttachments'; - const vorgang: VorgangE2E = createVorgang(); - const wiedervorlage: WiedervorlageE2E = createWiedervorlageItem('Wiedervorlage'); - const wiedervorlageAttachedItem = createWiedervorlageAttachedItem(objectIds[0], vorgang._id.$oid); + const vorgang: VorgangE2E = createVorgang(); + const wiedervorlage: WiedervorlageE2E = createWiedervorlageItem('Wiedervorlage'); + const wiedervorlageAttachedItem = createWiedervorlageAttachedItem(objectIds[0], vorgang._id.$oid); - before(() => { - initVorgang(vorgang); - initVorgangAttachedItem([wiedervorlageAttachedItem]); + before(() => { + initVorgang(vorgang); + initVorgangAttachedItem([wiedervorlageAttachedItem]); - loginAsSabine(); + loginAsSabine(); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) - - after(() => { - dropCollections(); - }) - - describe('Upload attachment', () => { - - it('should show vorgang detail page on click on list item', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should show wiedervorlage page on click on create wiedervorlage button', () => { - wiedervorlageContainerInVorgang.getCreateWiedervorlageButton().click(); - waitForSpinnerToDisappear(); - - exist(wiedervorlagePage.getRoot()); - }) - - it('should show empty attachment after upload', () => { - uploadEmptyFile(attachmentContainer.getUploadInput(), TEST_FILE_WITHOUT_CONTENT); - waitForSpinnerToDisappear(); - - exist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - }) - - it('should download empty attachment on click', () => { - attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getDownloadButton().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(TEST_FILE_WITHOUT_CONTENT)); - }) - - it('should show attachment with content after download', () => { - uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITH_CONTENT); - waitForSpinnerToDisappear(); - - exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }) - - it('should error snackbar after upload to large file', { defaultCommandTimeout: 30000 }, () => { - uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITH_CONTENT_46MB); - waitForSpinnerToDisappear(); - - exist(snackbar.getMessage()); - contains(snackbar.getMessage(), BinaryFileSnackbarMessageE2E.ATTACHMENT_NOT_ADDED.replace('{size}', '40MB')); - }) - - it('should close snackbar on close button', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getMessage()); - }) - - it('should download attachment on click', () => { - attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDownloadButton().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(TEST_FILE_WITH_CONTENT)); - }) - - it('should show snackbar after save wiedervorlage', () => { - wiedervorlageContainer.getBetreff().clear().type(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF); - wiedervorlageContainer.getSpeichernButton().click(); - - exist(snackbar.getMessage()); - contains(snackbar.getMessage(), 'Die Wiedervorlage "' + WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF + '" wurde angelegt'); - exist(snackbar.getCloseButton()); - }) - - it('should close snackBar', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getMessage()); - }) - - it('should show attachments on wiedervorlage in vorgang-detail after save ', () => { - wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF).expandItem(); - - exist(wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF).getAttachmentContainer().getList().getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - exist(wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF).getAttachmentContainer().getList().getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }) - - it('should download empty attachment on click in list', () => { - wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlage.betreff).getAttachmentContainer().getList().getItem(TEST_FILE_WITHOUT_CONTENT).getDownloadButton().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(TEST_FILE_WITHOUT_CONTENT)); - }) - - it('should download attachment on click in list', () => { - wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlage.betreff).getAttachmentContainer().getList().getItem(TEST_FILE_WITH_CONTENT).getDownloadButton().click(); - waitForSpinnerToDisappear(); - - exist(readFileFromDownloads(TEST_FILE_WITH_CONTENT)); - }) - }) - - describe('Delete attachment', () => { - - const wiedervorlageComp: WiedervorlageInVorgangE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF); - - it('should open wiedervorlage page', () => { - wiedervorlageComp.getLink().click(); - waitForSpinnerToDisappear(); - - exist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }) - - it('delete', () => { - attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getDeleteButton().click(); - waitForSpinnerToDisappear(); - - notExist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }) - - it('should show snackbar on save', () => { - wiedervorlageContainer.getSpeichernButton().click(); - - exist(snackbar.getMessage()); - contains(snackbar.getMessage(), `Die Wiedervorlage "${WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF}" wurde gespeichert`); - snackbar.getCloseButton().click(); - }) - - it('(Skip reason in OZG-4658) check attachments in wiedervorlage list', () => { - waitForSpinnerToDisappear(); - - wiedervorlageComp.getExpandButton(); - wiedervorlageComp.expandItem(); - - notExist(wiedervorlageComp.getAttachmentContainer().getList().getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - exist(wiedervorlageComp.getAttachmentContainer().getList().getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }) - }) - - describe('switch to wiedervorlage without attachments', () => { - - const wiedervorlageComp: WiedervorlageInVorgangE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlage.betreff); - - it('should not show any attachments', () => { - wiedervorlageComp.getLink().click(); - waitForSpinnerToDisappear(); - - notExist(wiedervorlageComp.getAttachmentContainer().getList().getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - notExist(wiedervorlageComp.getAttachmentContainer().getList().getItem(TEST_FILE_WITH_CONTENT).getRoot()); - - wiedervorlagePage.getSubnavigation().navigateBack(); - }) - }) - - describe('Same number of attachments after status change', () => { - const wiedervorlageComp: WiedervorlageInVorgangE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF); - - it('should open wiedervorlage page', () => { - wait(500); - wiedervorlageComp.getLink().click(); - - waitForSpinnerToDisappear(); - - exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }) - - it('should mark as erledigt', () => { - subnavigation.erledigen(); - - waitForSpinnerToDisappear(); - - containClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); - contains(snackBar.getMessage(), `Die Wiedervorlage ${WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF} wurde erledigt`); - }) - - it('should close snackBar on close', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should mark as open', () => { - subnavigation.wiedereroeffnen(); - - waitForSpinnerToDisappear(); - - notContainClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); - contains(snackBar.getMessage(), `Die Wiedervorlage ${WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF} wurde wiedereröffnet`); - }) - - it('should close snackBar on close', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should still have 1 attachment only', () => { - const attachmentList: AttachmentListE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlage.betreff).getAttachmentContainer().getList(); - - haveLength(attachmentList.getRoot(), 1); - }) - }) - - describe('delete last attachment', () => { - - it('should remove on delete', () => { - attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDeleteButton().click(); - waitForSpinnerToDisappear(); - - notExist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }) - - it('should show snackbar on save', () => { - wiedervorlageContainer.getSpeichernButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getMessage()); - contains(snackbar.getMessage(), `Die Wiedervorlage "${WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF}" wurde gespeichert`); - }) - - it('should close snackBar on close', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('(Skip reason in OZG-4658) should have no attachments after save', () => { - const wiedervorlageComp: WiedervorlageInVorgangE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF); - - wiedervorlageComp.getExpandButton(); - wiedervorlageComp.expandItem(); - - notExist(wiedervorlageComp.getAttachmentContainer().getList().getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); - notExist(wiedervorlageComp.getAttachmentContainer().getList().getItem(TEST_FILE_WITH_CONTENT).getRoot()); - }) - }) -}) \ No newline at end of file + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); + + after(() => { + dropCollections(); + }); + + describe('Upload attachment', () => { + it('should show vorgang detail page on click on list item', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should show wiedervorlage page on click on create wiedervorlage button', () => { + wiedervorlageContainerInVorgang.getCreateWiedervorlageButton().click(); + waitForSpinnerToDisappear(); + + exist(wiedervorlagePage.getRoot()); + }); + + it('should show empty attachment after upload', () => { + uploadEmptyFile(attachmentContainer.getUploadInput(), TEST_FILE_WITHOUT_CONTENT); + waitForSpinnerToDisappear(); + + exist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); + }); + + it('should download empty attachment on click', () => { + attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getDownloadButton().click(); + waitForSpinnerToDisappear(); + + exist(readFileFromDownloads(TEST_FILE_WITHOUT_CONTENT)); + }); + + it('should show attachment with content after download', () => { + uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITH_CONTENT); + waitForSpinnerToDisappear(); + + exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + }); + + it('should error snackbar after upload to large file', { defaultCommandTimeout: 30000 }, () => { + uploadFile(attachmentContainer.getUploadInput(), TEST_FILE_WITH_CONTENT_46MB); + waitForSpinnerToDisappear(); + + exist(snackbar.getMessage()); + contains( + snackbar.getMessage(), + BinaryFileSnackbarMessageE2E.ATTACHMENT_NOT_ADDED.replace('{size}', '40MB'), + ); + }); + + it('should close snackbar on close button', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getMessage()); + }); + + it('should download attachment on click', () => { + attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDownloadButton().click(); + waitForSpinnerToDisappear(); + + exist(readFileFromDownloads(TEST_FILE_WITH_CONTENT)); + }); + + it('should show snackbar after save wiedervorlage', () => { + wiedervorlageContainer.getBetreff().clear().type(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF); + wiedervorlageContainer.getSpeichernButton().click(); + + exist(snackbar.getMessage()); + contains( + snackbar.getMessage(), + 'Die Wiedervorlage "' + WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF + '" wurde angelegt', + ); + exist(snackbar.getCloseButton()); + }); + + it('should close snackBar', () => { + snackbar.getCloseButton().click(); + + notExist(snackbar.getMessage()); + }); + + it('should show attachments on wiedervorlage in vorgang-detail after save ', () => { + wiedervorlageContainerInVorgang + .getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF) + .expandItem(); + + exist( + wiedervorlageContainerInVorgang + .getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF) + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITHOUT_CONTENT) + .getRoot(), + ); + exist( + wiedervorlageContainerInVorgang + .getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF) + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITH_CONTENT) + .getRoot(), + ); + }); + + it('should download empty attachment on click in list', () => { + wiedervorlageContainerInVorgang + .getWiedervorlage(wiedervorlage.betreff) + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITHOUT_CONTENT) + .getDownloadButton() + .click(); + waitForSpinnerToDisappear(); + + exist(readFileFromDownloads(TEST_FILE_WITHOUT_CONTENT)); + }); + + it('should download attachment on click in list', () => { + wiedervorlageContainerInVorgang + .getWiedervorlage(wiedervorlage.betreff) + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITH_CONTENT) + .getDownloadButton() + .click(); + waitForSpinnerToDisappear(); + + exist(readFileFromDownloads(TEST_FILE_WITH_CONTENT)); + }); + }); + + describe('Delete attachment', () => { + const wiedervorlageComp: WiedervorlageInVorgangE2EComponent = + wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF); + + it('should open wiedervorlage page', () => { + wiedervorlageComp.getLink().click(); + waitForSpinnerToDisappear(); + + exist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); + exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + }); + + it('delete', () => { + attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getDeleteButton().click(); + waitForSpinnerToDisappear(); + + notExist(attachmentList.getItem(TEST_FILE_WITHOUT_CONTENT).getRoot()); + exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + }); + + it('should show snackbar on save', () => { + wiedervorlageContainer.getSpeichernButton().click(); + + exist(snackbar.getMessage()); + contains( + snackbar.getMessage(), + `Die Wiedervorlage "${WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF}" wurde gespeichert`, + ); + snackbar.getCloseButton().click(); + }); + + it('(Skip reason in OZG-4658) check attachments in wiedervorlage list', () => { + waitForSpinnerToDisappear(); + + wiedervorlageComp.getExpandButton(); + wiedervorlageComp.expandItem(); + + notExist( + wiedervorlageComp + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITHOUT_CONTENT) + .getRoot(), + ); + exist( + wiedervorlageComp + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITH_CONTENT) + .getRoot(), + ); + }); + }); + + describe('switch to wiedervorlage without attachments', () => { + const wiedervorlageComp: WiedervorlageInVorgangE2EComponent = + wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlage.betreff); + + it('should not show any attachments', () => { + wiedervorlageComp.getLink().click(); + waitForSpinnerToDisappear(); + + notExist( + wiedervorlageComp + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITHOUT_CONTENT) + .getRoot(), + ); + notExist( + wiedervorlageComp + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITH_CONTENT) + .getRoot(), + ); + + wiedervorlagePage.getSubnavigation().navigateBack(); + }); + }); + + describe('Same number of attachments after status change', () => { + const wiedervorlageComp: WiedervorlageInVorgangE2EComponent = + wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF); + + it('should open wiedervorlage page', () => { + wait(500); + wiedervorlageComp.getLink().click(); + + waitForSpinnerToDisappear(); + + exist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + }); + + it('should mark as erledigt', () => { + subnavigation.erledigen(); + + waitForSpinnerToDisappear(); + + containClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); + contains( + snackBar.getMessage(), + `Die Wiedervorlage ${WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF} wurde erledigt`, + ); + }); + + it('should close snackBar on close', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should mark as open', () => { + subnavigation.wiedereroeffnen(); + + waitForSpinnerToDisappear(); + + notContainClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); + contains( + snackBar.getMessage(), + `Die Wiedervorlage ${WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF} wurde wiedereröffnet`, + ); + }); + + it('should close snackBar on close', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('should still have 1 attachment only', () => { + const attachmentList: AttachmentListE2EComponent = wiedervorlageContainerInVorgang + .getWiedervorlage(wiedervorlage.betreff) + .getAttachmentContainer() + .getList(); + + haveLength(attachmentList.getRoot(), 1); + }); + }); + + describe('delete last attachment', () => { + it('should remove on delete', () => { + attachmentList.getItem(TEST_FILE_WITH_CONTENT).getDeleteButton().click(); + waitForSpinnerToDisappear(); + + notExist(attachmentList.getItem(TEST_FILE_WITH_CONTENT).getRoot()); + }); + + it('should show snackbar on save', () => { + wiedervorlageContainer.getSpeichernButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getMessage()); + contains( + snackbar.getMessage(), + `Die Wiedervorlage "${WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF}" wurde gespeichert`, + ); + }); + + it('should close snackBar on close', () => { + snackBar.getCloseButton().click(); + + notExist(snackBar.getMessage()); + }); + + it('(Skip reason in OZG-4658) should have no attachments after save', () => { + const wiedervorlageComp: WiedervorlageInVorgangE2EComponent = + wiedervorlageContainerInVorgang.getWiedervorlage(WIEDERVORLAGE_WITH_ATTACHMENTS_BETREFF); + + wiedervorlageComp.getExpandButton(); + wiedervorlageComp.expandItem(); + + notExist( + wiedervorlageComp + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITHOUT_CONTENT) + .getRoot(), + ); + notExist( + wiedervorlageComp + .getAttachmentContainer() + .getList() + .getItem(TEST_FILE_WITH_CONTENT) + .getRoot(), + ); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage-authorize-by-role.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage-authorize-by-role.cy.ts index ce0680540b139282bcca03c02b0d71a292005a5b..cc24d81e009f0a1113b504c9c2467ec4c06e0bfe 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage-authorize-by-role.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage-authorize-by-role.cy.ts @@ -35,79 +35,101 @@ import { createWiedervorlageNeuUriByVorgangId } from 'apps/alfa-e2e/src/support/ import { dropCollections } from '../../../support/cypress-helper'; describe('Wiedervorlage should be authorized by role', () => { - - const mainPage: MainPage = new MainPage(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - - const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); - const wiedervorlageSubnavigation: WiedervorlageSubnavigationE2EComponent = wiedervorlagePage.getSubnavigation(); - - describe(`for user Peter with role ${UserRoleE2E.VERWALTUNG_POSTSTELLE}`, () => { - - const vorgangInStatusNeuId: string = '601bc78eabc134051570aab8'; - const vorgangInStatusNeuUrl: string = createWiedervorlageNeuUriByVorgangId(vorgangInStatusNeuId); - const vorgangInStatusNeu: VorgangE2E = { ...buildVorgang(vorgangInStatusNeuId, 'VorgangInStatusNeu'), status: VorgangStatusE2E.NEU }; - - const vorgangInStatusInBearbeitungId = '60250b9d383c182943f6ba79'; - const vorgangInStatusInBearbeitungUrl: string = createWiedervorlageNeuUriByVorgangId(vorgangInStatusInBearbeitungId); - const vorgangInStatusInBearbeitung: VorgangE2E = { ...buildVorgang(vorgangInStatusInBearbeitungId, 'vorgangInStatusInBearbeitung'), status: VorgangStatusE2E.IN_BEARBEITUNG }; - - const vorgangInStatusAbgeschlossenId: string = '602566a807bb665df9a86e87'; - const vorgangInStatusAbgeschlossenUrl: string = createWiedervorlageNeuUriByVorgangId(vorgangInStatusAbgeschlossenId); - const vorgangInStatusAbgeschlossen: VorgangE2E = { ...buildVorgang(vorgangInStatusAbgeschlossenId, 'vorgangInStatusAbgeschlossen'), status: VorgangStatusE2E.ABGESCHLOSSEN }; - - const vorgangInStatusBeschiedenId: string = '602566a207bb665df9a86e86'; - const vorgangInStatusBeschiedenUrl: string = createWiedervorlageNeuUriByVorgangId(vorgangInStatusBeschiedenId); - const vorgangInStatusBeschieden: VorgangE2E = { ...buildVorgang(vorgangInStatusBeschiedenId, 'vorgangInStatusBeschieden'), status: VorgangStatusE2E.BESCHIEDEN }; - - beforeEach(() => { - initVorgaenge([vorgangInStatusNeu, vorgangInStatusInBearbeitung, vorgangInStatusAbgeschlossen, vorgangInStatusBeschieden]); - - loginAsPeter(); - }) - - after(() => { - dropCollections(); - }) - - it(`should NOT show vorgang in status ${VorgangStatusE2E.NEU}`, () => { - visitUrl(vorgangInStatusNeuUrl); - waitForSpinnerToDisappear(); - - exist(mainPage.getHeader().getLogo()); - notExist(wiedervorlagePage.getRoot()); - }) - - describe('should hide vorgang in status', () => { - - it(`${VorgangStatusE2E.IN_BEARBEITUNG}`, () => { - visitUrl(vorgangInStatusInBearbeitungUrl); - waitForSpinnerToDisappear(); - - exist(mainPage.getHeader().getLogo()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - notExist(wiedervorlagePage.getRoot()); - }) - - it(`${VorgangStatusE2E.ABGESCHLOSSEN}`, () => { - visitUrl(vorgangInStatusAbgeschlossenUrl); - waitForSpinnerToDisappear(); - - exist(mainPage.getHeader().getLogo()); - notExist(wiedervorlagePage.getRoot()); - notExist(wiedervorlageSubnavigation.getRoot()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - - it(`${VorgangStatusE2E.BESCHIEDEN}`, () => { - visitUrl(vorgangInStatusBeschiedenUrl); - waitForSpinnerToDisappear(); - - exist(mainPage.getHeader().getLogo()); - notExist(wiedervorlagePage.getRoot()); - notExist(wiedervorlageSubnavigation.getRoot()); - contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); - }) - }) - }) -}) \ No newline at end of file + const mainPage: MainPage = new MainPage(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + + const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); + const wiedervorlageSubnavigation: WiedervorlageSubnavigationE2EComponent = + wiedervorlagePage.getSubnavigation(); + + describe(`for user Peter with role ${UserRoleE2E.VERWALTUNG_POSTSTELLE}`, () => { + const vorgangInStatusNeuId: string = '601bc78eabc134051570aab8'; + const vorgangInStatusNeuUrl: string = + createWiedervorlageNeuUriByVorgangId(vorgangInStatusNeuId); + const vorgangInStatusNeu: VorgangE2E = { + ...buildVorgang(vorgangInStatusNeuId, 'VorgangInStatusNeu'), + status: VorgangStatusE2E.NEU, + }; + + const vorgangInStatusInBearbeitungId = '60250b9d383c182943f6ba79'; + const vorgangInStatusInBearbeitungUrl: string = createWiedervorlageNeuUriByVorgangId( + vorgangInStatusInBearbeitungId, + ); + const vorgangInStatusInBearbeitung: VorgangE2E = { + ...buildVorgang(vorgangInStatusInBearbeitungId, 'vorgangInStatusInBearbeitung'), + status: VorgangStatusE2E.IN_BEARBEITUNG, + }; + + const vorgangInStatusAbgeschlossenId: string = '602566a807bb665df9a86e87'; + const vorgangInStatusAbgeschlossenUrl: string = createWiedervorlageNeuUriByVorgangId( + vorgangInStatusAbgeschlossenId, + ); + const vorgangInStatusAbgeschlossen: VorgangE2E = { + ...buildVorgang(vorgangInStatusAbgeschlossenId, 'vorgangInStatusAbgeschlossen'), + status: VorgangStatusE2E.ABGESCHLOSSEN, + }; + + const vorgangInStatusBeschiedenId: string = '602566a207bb665df9a86e86'; + const vorgangInStatusBeschiedenUrl: string = createWiedervorlageNeuUriByVorgangId( + vorgangInStatusBeschiedenId, + ); + const vorgangInStatusBeschieden: VorgangE2E = { + ...buildVorgang(vorgangInStatusBeschiedenId, 'vorgangInStatusBeschieden'), + status: VorgangStatusE2E.BESCHIEDEN, + }; + + beforeEach(() => { + initVorgaenge([ + vorgangInStatusNeu, + vorgangInStatusInBearbeitung, + vorgangInStatusAbgeschlossen, + vorgangInStatusBeschieden, + ]); + + loginAsPeter(); + }); + + after(() => { + dropCollections(); + }); + + it(`should NOT show vorgang in status ${VorgangStatusE2E.NEU}`, () => { + visitUrl(vorgangInStatusNeuUrl); + waitForSpinnerToDisappear(); + + exist(mainPage.getHeader().getLogo()); + notExist(wiedervorlagePage.getRoot()); + }); + + describe('should hide vorgang in status', () => { + it(`${VorgangStatusE2E.IN_BEARBEITUNG}`, () => { + visitUrl(vorgangInStatusInBearbeitungUrl); + waitForSpinnerToDisappear(); + + exist(mainPage.getHeader().getLogo()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + notExist(wiedervorlagePage.getRoot()); + }); + + it(`${VorgangStatusE2E.ABGESCHLOSSEN}`, () => { + visitUrl(vorgangInStatusAbgeschlossenUrl); + waitForSpinnerToDisappear(); + + exist(mainPage.getHeader().getLogo()); + notExist(wiedervorlagePage.getRoot()); + notExist(wiedervorlageSubnavigation.getRoot()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + + it(`${VorgangStatusE2E.BESCHIEDEN}`, () => { + visitUrl(vorgangInStatusBeschiedenUrl); + waitForSpinnerToDisappear(); + + exist(mainPage.getHeader().getLogo()); + notExist(wiedervorlagePage.getRoot()); + notExist(wiedervorlageSubnavigation.getRoot()); + contains(snackbar.getMessage(), MessagesE2E.HTTP_STATUS_FORBIDDEN); + }); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.cy.ts index 5d06e09d19edd83df89c4f874f39c6c091b8bfcb..d1b56acecf74d93fa4dc916d7ed29c2a33b4f491 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.cy.ts @@ -43,225 +43,242 @@ import { createVorgang, initVorgaenge } from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe.skip('Wiedervorlage', () => { - const mainPage: MainPage = new MainPage(); - const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); - const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); + const mainPage: MainPage = new MainPage(); + const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); + const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); - const vorgangPage: VorgangPage = new VorgangPage(); - const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); - const wiedervorlageContainer: WiedervorlageE2EComponent = wiedervorlagePage.getWiedervorlageContainer(); + const vorgangPage: VorgangPage = new VorgangPage(); + const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); + const wiedervorlageContainer: WiedervorlageE2EComponent = + wiedervorlagePage.getWiedervorlageContainer(); - const vorgang: VorgangE2E = createVorgang(); + const vorgang: VorgangE2E = createVorgang(); - const wiedervorlageBetreff: string = 'TestWiedervorlage'; - const wiedervorlageBeschreibung: string = 'Beschreibung einer Wiedervorlage'; - const wiedervorlageFrist: string = formatDateLocal(new Date(), 'dd.MM.yyyy'); + const wiedervorlageBetreff: string = 'TestWiedervorlage'; + const wiedervorlageBeschreibung: string = 'Beschreibung einer Wiedervorlage'; + const wiedervorlageFrist: string = formatDateLocal(new Date(), 'dd.MM.yyyy'); + before(() => { + initVorgaenge([vorgang]); - before(() => { - initVorgaenge([vorgang]); + loginAsSabine(); - loginAsSabine(); + waitForSpinnerToDisappear(); + exist(vorgangList.getRoot()); + }); - waitForSpinnerToDisappear(); - exist(vorgangList.getRoot()); - }) + after(() => { + dropCollections(); + }); - after(() => { - dropCollections(); - }) + describe('Open Vorgang-Detail-Page', () => { + it('should show vorgang detail by click on vorgang in list', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); - describe('Open Vorgang-Detail-Page', () => { + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + }); - it('should show vorgang detail by click on vorgang in list', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); + describe('create wiedervorlage', () => { + it('should open wiedervorlage pag by click on create wiedervorlage button', () => { + vorgangPage.getWiedervorlagenContainer().getCreateWiedervorlageButton().click(); + waitForSpinnerToDisappear(); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - }) + exist(wiedervorlagePage.getSubnavigation().getRoot()); + }); - describe('create wiedervorlage', () => { + it('should show validation error if betreff is to short', () => { + wiedervorlageContainer.getBetreff().clear().type('Ab'); - it('should open wiedervorlage pag by click on create wiedervorlage button', () => { - vorgangPage.getWiedervorlagenContainer().getCreateWiedervorlageButton().click(); - waitForSpinnerToDisappear(); + wiedervorlageContainer.getSpeichernButton().click(); + waitForSpinnerToDisappear(); - exist(wiedervorlagePage.getSubnavigation().getRoot()); - }) + exist(wiedervorlageContainer.getBetreffError()); + }); - it('should show validation error if betreff is to short', () => { - wiedervorlageContainer.getBetreff().clear().type('Ab'); + it('should show validation error if betreff is to long', () => { + wiedervorlageContainer.getBetreff().clear().type(faker.random.alphaNumeric(41)); - wiedervorlageContainer.getSpeichernButton().click(); - waitForSpinnerToDisappear(); + wiedervorlageContainer.getSpeichernButton().click(); + waitForSpinnerToDisappear(); - exist(wiedervorlageContainer.getBetreffError()); - }) + exist(wiedervorlageContainer.getBetreffError()); + }); - it('should show validation error if betreff is to long', () => { - wiedervorlageContainer.getBetreff().clear().type(faker.random.alphaNumeric(41)); + it('should show validation error on invalid frist', () => { + wiedervorlageContainer.getBeschreibung().clear().type('Dies ist ein Test'); + wiedervorlageContainer.getFrist().clear().type('1.1.2020'); - wiedervorlageContainer.getSpeichernButton().click(); - waitForSpinnerToDisappear(); + wiedervorlageContainer.getSpeichernButton().click(); + waitForSpinnerToDisappear(); - exist(wiedervorlageContainer.getBetreffError()); - }) + exist(wiedervorlageContainer.getDatumError()); + }); - it('should show validation error on invalid frist', () => { - wiedervorlageContainer.getBeschreibung().clear().type('Dies ist ein Test'); - wiedervorlageContainer.getFrist().clear().type('1.1.2020'); + it('should show snackbar on valid data', () => { + wiedervorlageContainer.getBetreff().clear().type(wiedervorlageBetreff); + wiedervorlageContainer.getBeschreibung().clear().type(wiedervorlageBeschreibung); + wiedervorlageContainer.getFrist().clear().type(wiedervorlageFrist); - wiedervorlageContainer.getSpeichernButton().click(); - waitForSpinnerToDisappear(); + wiedervorlageContainer.getSpeichernButton().click(); + waitForSpinnerToDisappear(); - exist(wiedervorlageContainer.getDatumError()); - }) + exist(snackbar.getMessage()); + haveText( + snackbar.getMessage(), + MessagesE2E.WIEDERVORLAGE_ANGELEGT.replace('%s', wiedervorlageBetreff), + ); + }); - it('should show snackbar on valid data', () => { - wiedervorlageContainer.getBetreff().clear().type(wiedervorlageBetreff); - wiedervorlageContainer.getBeschreibung().clear().type(wiedervorlageBeschreibung); - wiedervorlageContainer.getFrist().clear().type(wiedervorlageFrist); + it('should close snackbar on click on close button', () => { + snackbar.getCloseButton().click(); - wiedervorlageContainer.getSpeichernButton().click(); - waitForSpinnerToDisappear(); + notExist(snackbar.getMessage()); + }); - exist(snackbar.getMessage()); - haveText(snackbar.getMessage(), MessagesE2E.WIEDERVORLAGE_ANGELEGT.replace('%s', wiedervorlageBetreff)); - }) + it('should show wiedervorlage on vorgang page', () => { + const wiedervorlage = vorgangPage + .getWiedervorlagenContainer() + .getWiedervorlage(wiedervorlageBetreff); - it('should close snackbar on click on close button', () => { - snackbar.getCloseButton().click(); + exist(wiedervorlage.getRoot()); - notExist(snackbar.getMessage()); - }) + haveText(wiedervorlage.getFrist(), formatDateLocal(new Date(), 'dd. MMM')); + haveText(wiedervorlage.getBetreff(), wiedervorlageBetreff); + }); - it('should show wiedervorlage on vorgang page', () => { - const wiedervorlage = vorgangPage.getWiedervorlagenContainer().getWiedervorlage(wiedervorlageBetreff); + it('should show vorganglist on navigate back', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); - exist(wiedervorlage.getRoot()); + exist(vorgangList.getRoot()); + }); + }); - haveText(wiedervorlage.getFrist(), formatDateLocal(new Date(), 'dd. MMM')); - haveText(wiedervorlage.getBetreff(), wiedervorlageBetreff); - }) + describe('edit wiedervorlage', () => { + it('should open Vorgang-Detail-Page on click on vorgang in list', () => { + vorgangList.getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); - it('should show vorganglist on navigate back', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); - exist(vorgangList.getRoot()); - }) - }) + it('should open Wiedervorlage-Page by click on wiedervorlage ', () => { + const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage + .getWiedervorlagenContainer() + .getWiedervorlage(wiedervorlageBetreff); - describe('edit wiedervorlage', () => { + wait(500); + wiedervorlageInVorgang.getLink().click(); + waitForSpinnerToDisappear(); - it('should open Vorgang-Detail-Page on click on vorgang in list', () => { - vorgangList.getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); + exist(wiedervorlagePage.getSubnavigation().getRoot()); + }); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) + it('should have input values', () => { + haveValue(wiedervorlageContainer.getBeschreibung(), wiedervorlageBeschreibung); + haveValue(wiedervorlageContainer.getBetreff(), wiedervorlageBetreff); + haveValue(wiedervorlageContainer.getFrist(), wiedervorlageFrist); + }); - it('should open Wiedervorlage-Page by click on wiedervorlage ', () => { - const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer().getWiedervorlage(wiedervorlageBetreff); + it('should show snackbar on valid data', () => { + wiedervorlageContainer.getBetreff().clear().type('Editierter Betreff'); + wiedervorlageContainer.getBeschreibung().clear().type('Diese Wiedervorlage wurde bearbeitet'); + wiedervorlageContainer.getFrist().clear().type(formatDateLocal(new Date(), 'dd.MM.yyyy')); - wait(500); - wiedervorlageInVorgang.getLink().click(); - waitForSpinnerToDisappear(); + wiedervorlageContainer.getSpeichernButton().click(); + waitForSpinnerToDisappear(); - exist(wiedervorlagePage.getSubnavigation().getRoot()); - }) + exist(snackbar.getMessage()); + haveText( + snackbar.getMessage(), + MessagesE2E.WIEDERVORLAGE_GESPEICHERT.replace('%s', 'Editierter Betreff'), + ); + }); - it('should have input values', () => { - haveValue(wiedervorlageContainer.getBeschreibung(), wiedervorlageBeschreibung); - haveValue(wiedervorlageContainer.getBetreff(), wiedervorlageBetreff); - haveValue(wiedervorlageContainer.getFrist(), wiedervorlageFrist); - }) + it('should close snackbar on click on close button', () => { + snackbar.getCloseButton().click(); - it('should show snackbar on valid data', () => { - wiedervorlageContainer.getBetreff().clear().type('Editierter Betreff'); - wiedervorlageContainer.getBeschreibung().clear().type('Diese Wiedervorlage wurde bearbeitet'); - wiedervorlageContainer.getFrist().clear().type(formatDateLocal(new Date(), 'dd.MM.yyyy')); + notExist(snackbar.getMessage()); + }); - wiedervorlageContainer.getSpeichernButton().click(); - waitForSpinnerToDisappear(); + it('should navigate after click on "Speichern"', () => { + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); - exist(snackbar.getMessage()); - haveText(snackbar.getMessage(), MessagesE2E.WIEDERVORLAGE_GESPEICHERT.replace('%s', 'Editierter Betreff')); - }) + it('should show existing wiedervorlage', () => { + const wiedervorlage = vorgangPage + .getWiedervorlagenContainer() + .getWiedervorlage('Editierter Betreff'); - it('should close snackbar on click on close button', () => { - snackbar.getCloseButton().click(); + exist(wiedervorlage.getRoot()); + + haveText(wiedervorlage.getFrist(), formatDateLocal(new Date(), 'dd. MMM')); + haveText(wiedervorlage.getBetreff(), 'Editierter Betreff'); + }); + + it('should not show wiedervorlage with legacy data', () => { + const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage + .getWiedervorlagenContainer() + .getWiedervorlage(wiedervorlageBetreff); - notExist(snackbar.getMessage()); - }) + notExist(wiedervorlageInVorgang.getRoot()); + }); + }); - it('should navigate after click on "Speichern"', () => { - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) + describe('remove beschreibung from wiedervorlage', () => { + it('should open Wiedervorlage-Page by click on wiedervorlage ', () => { + const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage + .getWiedervorlagenContainer() + .getWiedervorlage('Editierter Betreff'); - it('should show existing wiedervorlage', () => { - const wiedervorlage = vorgangPage.getWiedervorlagenContainer().getWiedervorlage('Editierter Betreff'); + wiedervorlageInVorgang.getLink().click(); + waitForSpinnerToDisappear(); - exist(wiedervorlage.getRoot()); + exist(wiedervorlagePage.getSubnavigation().getRoot()); + }); - haveText(wiedervorlage.getFrist(), formatDateLocal(new Date(), 'dd. MMM')); - haveText(wiedervorlage.getBetreff(), 'Editierter Betreff'); - }) + it('should have beschreibung', () => { + haveValue(wiedervorlageContainer.getBeschreibung(), 'Diese Wiedervorlage wurde bearbeitet'); + }); - it('should not show wiedervorlage with legacy data', () => { - const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer().getWiedervorlage(wiedervorlageBetreff); + it('should show snackbar after clear beschreibung', () => { + wiedervorlageContainer.getBeschreibung().clear(); + + wiedervorlageContainer.getSpeichernButton().click(); + waitForSpinnerToDisappear(); + + exist(snackbar.getMessage()); + haveText( + snackbar.getMessage(), + MessagesE2E.WIEDERVORLAGE_GESPEICHERT.replace('%s', 'Editierter Betreff'), + ); + }); - notExist(wiedervorlageInVorgang.getRoot()); - }) - }) + it('should close snackbar on click on close button', () => { + snackbar.getCloseButton().click(); - describe('remove beschreibung from wiedervorlage', () => { + notExist(snackbar.getMessage()); + }); + + it('should navigate after click on "Speichern"', () => { + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + + it('should navigate to Wiedervorlage formular', () => { + const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage + .getWiedervorlagenContainer() + .getWiedervorlage('Editierter Betreff'); - it('should open Wiedervorlage-Page by click on wiedervorlage ', () => { - const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer().getWiedervorlage('Editierter Betreff'); - - wiedervorlageInVorgang.getLink().click(); - waitForSpinnerToDisappear(); - - exist(wiedervorlagePage.getSubnavigation().getRoot()); - }) - - it('should have beschreibung', () => { - haveValue(wiedervorlageContainer.getBeschreibung(), 'Diese Wiedervorlage wurde bearbeitet'); - }) - - it('should show snackbar after clear beschreibung', () => { - wiedervorlageContainer.getBeschreibung().clear(); - - wiedervorlageContainer.getSpeichernButton().click(); - waitForSpinnerToDisappear(); - - exist(snackbar.getMessage()); - haveText(snackbar.getMessage(), MessagesE2E.WIEDERVORLAGE_GESPEICHERT.replace('%s', 'Editierter Betreff')); - }) - - it('should close snackbar on click on close button', () => { - snackbar.getCloseButton().click(); - - notExist(snackbar.getMessage()); - }) - - it('should navigate after click on "Speichern"', () => { - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - - it('should navigate to Wiedervorlage formular', () => { - const wiedervorlageInVorgang: WiedervorlageInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer().getWiedervorlage('Editierter Betreff'); - - wiedervorlageInVorgang.getLink().click(); - waitForSpinnerToDisappear(); - - exist(wiedervorlagePage.getSubnavigation().getRoot()); - }) - - it('should show empty beschreibung', () => { - haveText(wiedervorlageContainer.getBeschreibung(), ''); - }) - }) + wiedervorlageInVorgang.getLink().click(); + waitForSpinnerToDisappear(); + + exist(wiedervorlagePage.getSubnavigation().getRoot()); + }); + + it('should show empty beschreibung', () => { + haveText(wiedervorlageContainer.getBeschreibung(), ''); + }); + }); }); diff --git a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.erledigen.cy.ts b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.erledigen.cy.ts index 48c570bda248ba29ef5174330db802a0deb81ded..7a79c8803451d6fa48fbec101504b9897bb0dd5c 100644 --- a/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.erledigen.cy.ts +++ b/alfa-client/apps/alfa-e2e/src/e2e/main-tests/wiedervorlage/wiedervorlage.erledigen.cy.ts @@ -23,7 +23,10 @@ */ import { SnackBarE2EComponent } from 'apps/alfa-e2e/src/components/ui/snackbar.e2e.component'; import { VorgangDetailHeaderE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-detail-header.e2e.component'; -import { VorgangViewE2EComponent, VorgangViewsE2EComponent } from 'apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component'; +import { + VorgangViewE2EComponent, + VorgangViewsE2EComponent, +} from 'apps/alfa-e2e/src/components/vorgang/vorgang-views.e2e.component'; import { VorgangAttachedItemE2E } from 'apps/alfa-e2e/src/model/vorgang-attached-item'; import { initVorgangAttachedItem } from 'apps/alfa-e2e/src/support/vorgang-attached-item-util'; import { WiedervorlageInVorgangE2EComponent } from '../../../components/wiedervorlage/wiedervorlage-in-vorgang.e2e.component'; @@ -32,270 +35,316 @@ import { WiedervorlageSubnavigationE2EComponent } from '../../../components/wied import { WiedervorlagenInVorgangE2EComponent } from '../../../components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component'; import { VorgangE2E } from '../../../model/vorgang'; import { WiedervorlageE2E } from '../../../model/wiedervorlage'; -import { MainPage, waitForSpinnerToDisappear, waitforSpinnerToAppear } from '../../../page-objects/main.po'; +import { + MainPage, + waitForSpinnerToDisappear, + waitforSpinnerToAppear, +} from '../../../page-objects/main.po'; import { VorgangPage } from '../../../page-objects/vorgang.po'; import { WiedervorlagePage } from '../../../page-objects/wiedervorlage.po'; import { dropCollections, wait } from '../../../support/cypress-helper'; -import { containClass, contains, exist, notContainClass, notExist } from '../../../support/cypress.util'; +import { + containClass, + contains, + exist, + notContainClass, + notExist, +} from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang, objectIds } from '../../../support/vorgang-util'; -import { createWiedervorlageAttachedItem, createWiedervorlageItem } from '../../../support/wiedervorlage-util'; +import { + createWiedervorlageAttachedItem, + createWiedervorlageItem, +} from '../../../support/wiedervorlage-util'; describe('Wiedervorlage erledigen/wiedereroeffnen', () => { - const mainPage: MainPage = new MainPage(); + const mainPage: MainPage = new MainPage(); - const views: VorgangViewsE2EComponent = mainPage.getViews(); - const wiedervorlagenView: VorgangViewE2EComponent = views.getWiedervorlagen(); + const views: VorgangViewsE2EComponent = mainPage.getViews(); + const wiedervorlagenView: VorgangViewE2EComponent = views.getWiedervorlagen(); - const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); + const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); - const vorgangPage: VorgangPage = new VorgangPage(); - const vorgangDetailHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); - const wiedervorlageContainerInVorgang: WiedervorlagenInVorgangE2EComponent = vorgangPage.getWiedervorlagenContainer(); + const vorgangPage: VorgangPage = new VorgangPage(); + const vorgangDetailHeader: VorgangDetailHeaderE2EComponent = vorgangPage.getVorgangDetailHeader(); + const wiedervorlageContainerInVorgang: WiedervorlagenInVorgangE2EComponent = + vorgangPage.getWiedervorlagenContainer(); + + const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); + const subnavigation: WiedervorlageSubnavigationE2EComponent = + wiedervorlagePage.getSubnavigation(); + const wiedervorlageContainer: WiedervorlageE2EComponent = + wiedervorlagePage.getWiedervorlageContainer(); - const wiedervorlagePage: WiedervorlagePage = new WiedervorlagePage(); - const subnavigation: WiedervorlageSubnavigationE2EComponent = wiedervorlagePage.getSubnavigation(); - const wiedervorlageContainer: WiedervorlageE2EComponent = wiedervorlagePage.getWiedervorlageContainer(); + const vorgang: VorgangE2E = createVorgang(); + + const wiedervorlageZumErledigen: WiedervorlageE2E = { + ...createWiedervorlageItem('WiedervorlageZumErledigen'), + done: false, + }; + const wiedervorlageAttachedItemZumErledigen: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[0], vorgang._id.$oid), + item: wiedervorlageZumErledigen, + }; - const vorgang: VorgangE2E = createVorgang(); + const wiedervorlageZumWiedereroeffnen: WiedervorlageE2E = { + ...createWiedervorlageItem('WiedervorlageZumWiedereroeffnen'), + done: true, + }; + const wiedervorlageAttachedItemZuWiedereroeffnen: VorgangAttachedItemE2E = { + ...createWiedervorlageAttachedItem(objectIds[1], vorgang._id.$oid), + item: wiedervorlageZumWiedereroeffnen, + }; - const wiedervorlageZumErledigen: WiedervorlageE2E = { ...createWiedervorlageItem('WiedervorlageZumErledigen'), done: false }; - const wiedervorlageAttachedItemZumErledigen: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[0], vorgang._id.$oid), item: wiedervorlageZumErledigen }; + before(() => { + initVorgang(vorgang); + initVorgangAttachedItem([ + wiedervorlageAttachedItemZumErledigen, + wiedervorlageAttachedItemZuWiedereroeffnen, + ]); - const wiedervorlageZumWiedereroeffnen: WiedervorlageE2E = { ...createWiedervorlageItem('WiedervorlageZumWiedereroeffnen'), done: true }; - const wiedervorlageAttachedItemZuWiedereroeffnen: VorgangAttachedItemE2E = { ...createWiedervorlageAttachedItem(objectIds[1], vorgang._id.$oid), item: wiedervorlageZumWiedereroeffnen }; + loginAsSabine(); - before(() => { - initVorgang(vorgang); - initVorgangAttachedItem([wiedervorlageAttachedItemZumErledigen, wiedervorlageAttachedItemZuWiedereroeffnen]); + waitForSpinnerToDisappear(); + exist(mainPage.getVorgangList().getRoot()); + }); - loginAsSabine(); + after(() => { + dropCollections(); + }); - waitForSpinnerToDisappear(); - exist(mainPage.getVorgangList().getRoot()); - }) + describe('Open Vorgang-Detail-Page', () => { + it('Open Vorgang-Detail-Page', () => { + mainPage.getVorgangList().getListItem(vorgang.name).getRoot().click(); - after(() => { - dropCollections(); - }) + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); - describe('Open Vorgang-Detail-Page', () => { + exist(vorgangPage.getVorgangDetailHeader().getRoot()); + }); + }); - it('Open Vorgang-Detail-Page', () => { - mainPage.getVorgangList().getListItem(vorgang.name).getRoot().click(); + describe('erledigen', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = + wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumErledigen.betreff); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); + it('should open wiedervorlage on click', () => { + exist(wiedervorlage.getRoot()); - exist(vorgangPage.getVorgangDetailHeader().getRoot()); - }) - }) + wait(500); + wiedervorlage.getLink().click(); + waitForSpinnerToDisappear(); - describe('erledigen', () => { + exist(subnavigation.getRoot()); + }); - const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumErledigen.betreff); + it('should mark as erledigt after do erledigen', () => { + subnavigation.erledigen(); - it('should open wiedervorlage on click', () => { - exist(wiedervorlage.getRoot()); + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); - wait(500); - wiedervorlage.getLink().click(); - waitForSpinnerToDisappear(); + containClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); + contains( + snackBar.getMessage(), + `Die Wiedervorlage ${wiedervorlageZumErledigen.betreff} wurde erledigt`, + ); + }); - exist(subnavigation.getRoot()); - }) + it('should close snackBar on close', () => { + snackBar.getCloseButton().click(); - it('should mark as erledigt after do erledigen', () => { - subnavigation.erledigen(); + notExist(snackBar.getMessage()); + }); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); + it('should open vorgang detail on click on back', () => { + subnavigation.navigateBack(); - containClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); - contains(snackBar.getMessage(), `Die Wiedervorlage ${wiedervorlageZumErledigen.betreff} wurde erledigt`); - }) + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); - it('should close snackBar on close', () => { - snackBar.getCloseButton().click(); + exist(vorgangDetailHeader.getRoot()); + }); + }); - notExist(snackBar.getMessage()); - }) + describe('wiedereroeffnen', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = + wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumWiedereroeffnen.betreff); - it('should open vorgang detail on click on back', () => { - subnavigation.navigateBack(); + it('should open wiedervorlage on click', () => { + wait(500); + wiedervorlage.getLink().click(); + waitForSpinnerToDisappear(); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); + exist(subnavigation.getRoot()); + }); - exist(vorgangDetailHeader.getRoot()); - }) - }) + it('should mark as open after do wiedereroeffnen', () => { + subnavigation.wiedereroeffnen(); - describe('wiedereroeffnen', () => { + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); - const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumWiedereroeffnen.betreff); + notContainClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); + contains( + snackBar.getMessage(), + `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde wiedereröffnet`, + ); + }); - it('should open wiedervorlage on click', () => { - wait(500); - wiedervorlage.getLink().click(); - waitForSpinnerToDisappear(); + it('should close snackBar on close', () => { + snackBar.getCloseButton().click(); - exist(subnavigation.getRoot()); - }) + notExist(snackBar.getMessage()); + }); - it('should mark as open after do wiedereroeffnen', () => { - subnavigation.wiedereroeffnen(); + it('should open vorgang detail on click on back', () => { + subnavigation.navigateBack(); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); - notContainClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); - contains(snackBar.getMessage(), `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde wiedereröffnet`); - }) + exist(vorgangDetailHeader.getRoot()); + }); + }); - it('should close snackBar on close', () => { - snackBar.getCloseButton().click(); + describe('tiny pentest for erledigen/wiedereroeffnen', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = + wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumWiedereroeffnen.betreff); - notExist(snackBar.getMessage()); - }) + it('should open wiedervorlage on click', () => { + wait(500); + wiedervorlage.getLink().click(); - it('should open vorgang detail on click on back', () => { - subnavigation.navigateBack(); + waitForSpinnerToDisappear(); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); + exist(subnavigation.getRoot()); + }); - exist(vorgangDetailHeader.getRoot()); - }) - }) + it('should mark as erledigt', () => { + subnavigation.erledigen(); - describe('tiny pentest for erledigen/wiedereroeffnen', () => { + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); - const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumWiedereroeffnen.betreff); + containClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); + contains( + snackBar.getMessage(), + `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde erledigt`, + ); + }); - it('should open wiedervorlage on click', () => { - wait(500); - wiedervorlage.getLink().click(); + it('should close snackBar on close', () => { + snackBar.getCloseButton().click(); - waitForSpinnerToDisappear(); + notExist(snackBar.getMessage()); + }); - exist(subnavigation.getRoot()); - }) + it('should mark as open', () => { + subnavigation.wiedereroeffnen(); - it('should mark as erledigt', () => { - subnavigation.erledigen(); + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); + notContainClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); + contains( + snackBar.getMessage(), + `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde wiedereröffnet`, + ); + }); - containClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); - contains(snackBar.getMessage(), `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde erledigt`); - }) + it('should close snackBar on close', () => { + snackBar.getCloseButton().click(); - it('should close snackBar on close', () => { - snackBar.getCloseButton().click(); + notExist(snackBar.getMessage()); + }); - notExist(snackBar.getMessage()); - }) + it('should mark as erledigt', () => { + subnavigation.erledigen(); - it('should mark as open', () => { - subnavigation.wiedereroeffnen(); + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + containClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); + contains( + snackBar.getMessage(), + `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde erledigt`, + ); + }); + + it('should close snackBar on close', () => { + snackBar.getCloseButton().click(); - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); + notExist(snackBar.getMessage()); + }); - notContainClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); - contains(snackBar.getMessage(), `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde wiedereröffnet`); - }) + it('should mark as open', () => { + subnavigation.wiedereroeffnen(); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + notContainClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); + contains( + snackBar.getMessage(), + `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde wiedereröffnet`, + ); + }); - it('should close snackBar on close', () => { - snackBar.getCloseButton().click(); + it('should close snackBar on close', () => { + snackBar.getCloseButton().click(); - notExist(snackBar.getMessage()); - }) - - it('should mark as erledigt', () => { - subnavigation.erledigen(); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - containClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); - contains(snackBar.getMessage(), `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde erledigt`); - }) - - it('should close snackBar on close', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should mark as open', () => { - subnavigation.wiedereroeffnen(); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - notContainClass(wiedervorlageContainer.getStatusDot(), 'erledigt'); - contains(snackBar.getMessage(), `Die Wiedervorlage ${wiedervorlageZumWiedereroeffnen.betreff} wurde wiedereröffnet`); - }) - - it('should close snackBar on close', () => { - snackBar.getCloseButton().click(); - - notExist(snackBar.getMessage()); - }) - - it('should open vorgang detail on click on back', () => { - subnavigation.navigateBack(); - - waitforSpinnerToAppear(); - waitForSpinnerToDisappear(); - - exist(vorgangDetailHeader.getRoot()); - }) - - }) - - //Test an die richtige Stelle verschieben und den Test vereinfachen - describe('View item icon', () => { - - const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumWiedereroeffnen.betreff); - const locatorIconIsOverdue: string = 'wiedervorlage-icon-is-overdue'; - const locatorIconDefault: string = 'wiedervorlage-icon-default'; - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - }) - - it('should show red icon', () => { - exist(wiedervorlagenView.getRoot().getTestElementWithClass(locatorIconIsOverdue)); - }) - - it('Open Vorgang-Detail-Page', () => { - mainPage.getVorgangList().getListItem(vorgang.name).getRoot().click(); - waitForSpinnerToDisappear(); - }) - - it('should mark as erledigt', () => { - wait(500); - wiedervorlage.getLink().click(); - waitForSpinnerToDisappear(); - subnavigation.erledigen(); - waitForSpinnerToDisappear(); - subnavigation.navigateBack(); - waitForSpinnerToDisappear(); - }) - - it('back to vorgang list', () => { - vorgangPage.getSubnavigation().getBackButton().click(); - waitForSpinnerToDisappear(); - }) - - it('should show default icon', () => { - exist(wiedervorlagenView.getRoot().getTestElementWithClass(locatorIconDefault)); - }) - }) - -}) \ No newline at end of file + notExist(snackBar.getMessage()); + }); + + it('should open vorgang detail on click on back', () => { + subnavigation.navigateBack(); + + waitforSpinnerToAppear(); + waitForSpinnerToDisappear(); + + exist(vorgangDetailHeader.getRoot()); + }); + }); + + //Test an die richtige Stelle verschieben und den Test vereinfachen + describe('View item icon', () => { + const wiedervorlage: WiedervorlageInVorgangE2EComponent = + wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumWiedereroeffnen.betreff); + const locatorIconIsOverdue: string = 'wiedervorlage-icon-is-overdue'; + const locatorIconDefault: string = 'wiedervorlage-icon-default'; + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + }); + + it('should show red icon', () => { + exist(wiedervorlagenView.getRoot().getTestElementWithClass(locatorIconIsOverdue)); + }); + + it('Open Vorgang-Detail-Page', () => { + mainPage.getVorgangList().getListItem(vorgang.name).getRoot().click(); + waitForSpinnerToDisappear(); + }); + + it('should mark as erledigt', () => { + wait(500); + wiedervorlage.getLink().click(); + waitForSpinnerToDisappear(); + subnavigation.erledigen(); + waitForSpinnerToDisappear(); + subnavigation.navigateBack(); + waitForSpinnerToDisappear(); + }); + + it('back to vorgang list', () => { + vorgangPage.getSubnavigation().getBackButton().click(); + waitForSpinnerToDisappear(); + }); + + it('should show default icon', () => { + exist(wiedervorlagenView.getRoot().getTestElementWithClass(locatorIconDefault)); + }); + }); +}); diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-ea-dev.yaml b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-ea-dev.yaml index 119ee06c4213eb9a121e2b64e0606e155230aef9..2ed43536be4d0c9b48c267fd90321593051cd27d 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-ea-dev.yaml +++ b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-ea-dev.yaml @@ -8,10 +8,10 @@ project: server: https://kubernetes.default.svc alfa: env: - overrideSpringProfiles: "oc,ea,e2e,dev" + overrideSpringProfiles: 'oc,ea,e2e,dev' sso: serverUrl: https://sso.dev.by.ozg-cloud.de - apiPassword: "Test1234!" + apiPassword: 'Test1234!' keycloak_clients: - client_name: alfa client_roles: @@ -23,7 +23,7 @@ alfa: vorgang_manager: env: - overrideSpringProfiles: "oc,e2e,dev" + overrideSpringProfiles: 'oc,e2e,dev' elasticsearch: enabled: true replicaCount: 1 @@ -43,10 +43,10 @@ vorgang_manager: user_manager: ozgcloud: usersync: - period: "5s" + onstart: true keycloak: api: - password: "Test1234!" + password: 'Test1234!' sso: serverUrl: https://sso.dev.by.ozg-cloud.de api_user: @@ -54,13 +54,13 @@ user_manager: first_name: UserManager last_name: ApiUser realm_roles: - - offline_access - - uma_authorization + - offline_access + - uma_authorization client_roles: - - name: realm-management - role: view-users - - name: realm-management - role: manage-users + - name: realm-management + role: view-users + - name: realm-management + role: manage-users baseUrl: dev.by.ozg-cloud.de ingress: @@ -71,26 +71,26 @@ smocker: enabled: false mocks: - - request: - method: POST - path: /externe-processor-success - response: - status: 200 - headers: - Content-Type: application/json - body: > - { - "action": "CREATE_AKTENNOTIZ", - "body": { - "headline": "Eine neue Notiz", - "severity": "INFO", - "text": "Alles fein" + - request: + method: POST + path: /externe-processor-success + response: + status: 200 + headers: + Content-Type: application/json + body: > + { + "action": "CREATE_AKTENNOTIZ", + "body": { + "headline": "Eine neue Notiz", + "severity": "INFO", + "text": "Alles fein" + } } - } - - request: - method: POST - path: /externe-processor-failure - response: - status: 500 - headers: - body: "Da ist etwas schiefgelaufen" \ No newline at end of file + - request: + method: POST + path: /externe-processor-failure + response: + status: 500 + headers: + body: 'Da ist etwas schiefgelaufen' diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml index 33e407ac081b5892464dee74d7b871f2a77c0f86..29cb77d3e82766b46ae332bd1c3ee8b8a03990c0 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml +++ b/alfa-client/apps/alfa-e2e/src/fixtures/argocd/by-main-dev.yaml @@ -8,10 +8,10 @@ project: server: https://kubernetes.default.svc alfa: env: - overrideSpringProfiles: "oc,e2e,dev" + overrideSpringProfiles: 'oc,e2e,dev' sso: serverUrl: https://sso.dev.by.ozg-cloud.de - apiPassword: "Test1234!" + apiPassword: 'Test1234!' ingress: use_staging_cert: true className: openshift-default @@ -19,7 +19,7 @@ alfa: vorgang_manager: env: - overrideSpringProfiles: "oc,e2e,dev" + overrideSpringProfiles: 'oc,e2e,dev' elasticsearch: enabled: true replicaCount: 1 @@ -39,10 +39,10 @@ vorgang_manager: user_manager: ozgcloud: usersync: - period: "5s" + onstart: true keycloak: api: - password: "Test1234!" + password: 'Test1234!' sso: serverUrl: https://sso.dev.by.ozg-cloud.de api_user: @@ -50,13 +50,13 @@ user_manager: first_name: UserManager last_name: ApiUser realm_roles: - - offline_access - - uma_authorization + - offline_access + - uma_authorization client_roles: - - name: realm-management - role: view-users - - name: realm-management - role: manage-users + - name: realm-management + role: view-users + - name: realm-management + role: manage-users baseUrl: dev.by.ozg-cloud.de ingress: @@ -67,26 +67,26 @@ smocker: enabled: false mocks: - - request: - method: POST - path: /externe-processor-success - response: - status: 200 - headers: - Content-Type: application/json - body: > - { - "action": "CREATE_AKTENNOTIZ", - "body": { - "headline": "Eine neue Notiz", - "severity": "INFO", - "text": "Alles fein" + - request: + method: POST + path: /externe-processor-success + response: + status: 200 + headers: + Content-Type: application/json + body: > + { + "action": "CREATE_AKTENNOTIZ", + "body": { + "headline": "Eine neue Notiz", + "severity": "INFO", + "text": "Alles fein" + } } - } - - request: - method: POST - path: /externe-processor-failure - response: - status: 500 - headers: - body: "Da ist etwas schiefgelaufen" \ No newline at end of file + - request: + method: POST + path: /externe-processor-failure + response: + status: 500 + headers: + body: 'Da ist etwas schiefgelaufen' diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/attachment/jpg.json b/alfa-client/apps/alfa-e2e/src/fixtures/attachment/jpg.json index bec983080963767598520a5edee8864c5188e79f..4c029ded7b8e5f33c7ecf24ed68e66b057848b01 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/attachment/jpg.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/attachment/jpg.json @@ -1,8 +1,8 @@ { - "_id": "6270c62e261af555e8f4f904", - "vendorId": "assistants.C45A300C4E5B1B764AE597F6C5DE9B445849AAA5", - "name" : "win.jpg", - "contentType" : "image/jpeg", - "size" : 10129, - "content" : "" -} \ No newline at end of file + "_id": "6270c62e261af555e8f4f904", + "vendorId": "assistants.C45A300C4E5B1B764AE597F6C5DE9B445849AAA5", + "name": "win.jpg", + "contentType": "image/jpeg", + "size": 10129, + "content": "" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/attachment/pdf.json b/alfa-client/apps/alfa-e2e/src/fixtures/attachment/pdf.json index 6a419761b2170f640934730dcc1e48ba03354228..741e703ad15e902db71930a846ebd2b9698748d1 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/attachment/pdf.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/attachment/pdf.json @@ -1,8 +1,8 @@ { - "_id" : "6270c62e261af555e8f4f900", - "vendorId" : "assistants.2546462108DD4C61C52C7FC31AE62F7E740315AB", - "name" : "Anlage Vollmacht.pdf", - "contentType" : "application/pdf", - "size" : 187585, - "content" : "" -} \ No newline at end of file + "_id": "6270c62e261af555e8f4f900", + "vendorId": "assistants.2546462108DD4C61C52C7FC31AE62F7E740315AB", + "name": "Anlage Vollmacht.pdf", + "contentType": "application/pdf", + "size": 187585, + "content": "" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-jpg.json b/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-jpg.json index 9ca6d5566437fea7927a0ded65c4585acc626bef..ba2a1221b872af610fefce5a93bc475bf3bb98ed 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-jpg.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-jpg.json @@ -1,13 +1,13 @@ { - "_id": "a93604e8-f38e-4e76-8ed8-ebbb1ee8e503", - "vendorId": "assistants.E0FBA361C191F8B723949467AE302BEA24E4745E", - "name": "Helge1.jpg", - "contentType": "image/jpeg", - "size": 155251, - "content": { - "$binary": { - "base64": "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", - "subType": "00" - } - } -} \ No newline at end of file + "_id": "a93604e8-f38e-4e76-8ed8-ebbb1ee8e503", + "vendorId": "assistants.E0FBA361C191F8B723949467AE302BEA24E4745E", + "name": "Helge1.jpg", + "contentType": "image/jpeg", + "size": 155251, + "content": { + "$binary": { + "base64": "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", + "subType": "00" + } + } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-odt.json b/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-odt.json index b443333dae08c1a3ae5ed0c5381413e5584254a4..0a741c3868e25fc8acd062686dd79024b2ffbf9b 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-odt.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-odt.json @@ -1,13 +1,13 @@ { - "_id": "edf63afa-9b30-414b-b237-d254ed1b49b5", - "vendorId": "assistants.52D79E5B2118D1740045AB87151535DCAD24E9A7", - "name": "Helgetext2.odt", - "contentType": "application/vnd.oasis.opendocument.text", - "size": 7993, - "content": { - "$binary": { - "base64": "UEsDBBQAAAgAACxEj1JexjIMJwAAACcAAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQub2FzaXMub3BlbmRvY3VtZW50LnRleHRQSwMEFAAACAAALESPUgYCUOZqAQAAagEAABgAAABUaHVtYm5haWxzL3RodW1ibmFpbC5wbmeJUE5HDQoaCgAAAA1JSERSAAAAtQAAAQAIAwAAAML9x+kAAAA8UExURYyQkJCTlZ6fo6qknrm2tri6vMW2qsrGv8rQ1d/Uytvm79vq9ezn5O/0+fDq5fT3+vj39////wAAAP///81aQL0AAADpSURBVHja7dK5DYAwEADB4zU2j6H/ZskpAOmk2Qom2HgyFtTU1NTU1NTU1NTU1J+us99Hz6ZexyGmPZu6LluZm6+pqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqan/6AXwWwUaPv4WoAAAAABJRU5ErkJgglBLAwQUAAgICAAsRI9SAAAAAAAAAAAAAAAACwAAAGNvbnRlbnQueG1spVddb9s2FH3vrxA0YG8M7bgDEi12H1oU2JoURZ0Be2UoSiYmiRpJWfa/3yVp0ZRjOVz8Ilu851zeb1IPn3Z1lWyZVFw0y3R+M0sT1lCR86Zcpn89f0V36afVhwdRFJyyLBe0q1mjERWNht8E2I3KnHSZdrLJBFFcZQ2pmco0zUTLmoGVhejM7uVWlN5X0XQLDtma7XQs2WBHXPISv7MFh+xckj6WbLAQ1JBeiFjyTlWoEBD1uiWan1ixq3jzzzLdaN1mGPd9f9MvboQs8fz+/h5bqTeYelzbycqicopZxcxmCs9v5njA1kyTWPsMNjSp6eoXJqNDQzR5lVW1LaMrYltOhIZuiIyuDQsep3eRx6d3kYfcmujNRE7u8BMI7ePp8VgLso7dy2BHoaKSt9FuOnTIF0J4Uw3BNag193Y2+4jde4DuL8J7yTWTAZxehFNSUR9xUZ8LGuDmGBCIbU2Z+sI3gVAThFvsxB6s8knV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", - "subType": "00" - } - } -} \ No newline at end of file + "_id": "edf63afa-9b30-414b-b237-d254ed1b49b5", + "vendorId": "assistants.52D79E5B2118D1740045AB87151535DCAD24E9A7", + "name": "Helgetext2.odt", + "contentType": "application/vnd.oasis.opendocument.text", + "size": 7993, + "content": { + "$binary": { + "base64": "UEsDBBQAAAgAACxEj1JexjIMJwAAACcAAAAIAAAAbWltZXR5cGVhcHBsaWNhdGlvbi92bmQub2FzaXMub3BlbmRvY3VtZW50LnRleHRQSwMEFAAACAAALESPUgYCUOZqAQAAagEAABgAAABUaHVtYm5haWxzL3RodW1ibmFpbC5wbmeJUE5HDQoaCgAAAA1JSERSAAAAtQAAAQAIAwAAAML9x+kAAAA8UExURYyQkJCTlZ6fo6qknrm2tri6vMW2qsrGv8rQ1d/Uytvm79vq9ezn5O/0+fDq5fT3+vj39////wAAAP///81aQL0AAADpSURBVHja7dK5DYAwEADB4zU2j6H/ZskpAOmk2Qom2HgyFtTU1NTU1NTU1NTU1J+us99Hz6ZexyGmPZu6LluZm6+pqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqampqan/6AXwWwUaPv4WoAAAAABJRU5ErkJgglBLAwQUAAgICAAsRI9SAAAAAAAAAAAAAAAACwAAAGNvbnRlbnQueG1spVddb9s2FH3vrxA0YG8M7bgDEi12H1oU2JoURZ0Be2UoSiYmiRpJWfa/3yVp0ZRjOVz8Ilu851zeb1IPn3Z1lWyZVFw0y3R+M0sT1lCR86Zcpn89f0V36afVhwdRFJyyLBe0q1mjERWNht8E2I3KnHSZdrLJBFFcZQ2pmco0zUTLmoGVhejM7uVWlN5X0XQLDtma7XQs2WBHXPISv7MFh+xckj6WbLAQ1JBeiFjyTlWoEBD1uiWan1ixq3jzzzLdaN1mGPd9f9MvboQs8fz+/h5bqTeYelzbycqicopZxcxmCs9v5njA1kyTWPsMNjSp6eoXJqNDQzR5lVW1LaMrYltOhIZuiIyuDQsep3eRx6d3kYfcmujNRE7u8BMI7ePp8VgLso7dy2BHoaKSt9FuOnTIF0J4Uw3BNag193Y2+4jde4DuL8J7yTWTAZxehFNSUR9xUZ8LGuDmGBCIbU2Z+sI3gVAThFvsxB6s8knV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", + "subType": "00" + } + } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-xml.json b/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-xml.json index 7b9f287bf3d72f7d42e2f61666fcfcf96421949a..46e1b4bf1ef9e720f88d098acd832fc6502468b5 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-xml.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/binary-file/binary-file-xml.json @@ -1,13 +1,13 @@ { - "_id": "61662dfc-cf90-47a8-8fc9-79bbc994ed16", - "vendorId": "myForm-xml", - "name": "XML-Daten.xml", - "contentType": "text/xml", - "size": 5520, - "content": { - "$binary": { - "base64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPG15Rm9ybSB4bWxuczpwZGY9Imh0dHA6Ly94bWxucy5jaXQuZGUvYXNzaXN0YW50cy9wZGYiIHhtbG5zOnQ9Imh0dHA6Ly94bWxucy5jaXQuZGUvaW50ZWxsaWZvcm0vdHJhbnNhY3Rpb24iIHQ6dXVpZD0iZWFjMjQ4MGUtNzE2Ni00YjE2LWJkZGQtODgwNTkxZTdkOTNiIiB0OmlkPSIyMDIxMDQxNTMwNzAyMDQxNDcwMSIgdDp0aW1lc3RhbXA9IjIwMjEtMDQtMTVUMDg6MzE6NDIuMzk4WiIgdDpzZW5kZXI9ImludGVsbGlmb3JtLm96Zy1zaC5kZSIgdDpmb3JtPSJTaW1wbGVGb3JtU2VuZGV0QW5Ib21lU2VydmVyVm9uVG9yc3RlbiIgdDpmb3JtLWlkPSJTaW1wbGVGb3JtU2VuZGV0QW5Ib21lU2VydmVyVm9uVG9yc3RlbiIgdDpjdXN0b21lcj0iS2llbCIgdDpjdXN0b21lci1pZD0iS2llbCIgdDpjbGllbnQ9InNoLWRldiIgdDpjbGllbnQtaWQ9InNoLWRldiI+PEtvbnRha3RzeXN0ZW1UeXBBPjIzMzAzNDYwMDwvS29udGFrdHN5c3RlbVR5cEE+PEtvbnRha3RzeXN0ZW1UeXBCPjIzMzAzNDYwMTwvS29udGFrdHN5c3RlbVR5cEI+PEFubGllZ2VuSUQ+ODk2NjY3MTwvQW5saWVnZW5JRD48YW50cmFnc3RlbGxlcj48c2hfc3RyYXNzZT5BbiBkZXIgU2NobmVpZGVyZWk8L3NoX3N0cmFzc2U+PHNoX2hhdXNudW1tZXI+MTwvc2hfaGF1c251bW1lcj48c2hfcGx6PjI0MTAzPC9zaF9wbHo+PG9ydF9hdXN3YWhsPjkwMDY0MDIkMDEwMDIwMDA8L29ydF9hdXN3YWhsPjxvcnQ+S2llbDwvb3J0PjxHZWJpZXRJRD45MDA2NDAyPC9HZWJpZXRJRD48R2ViaWV0QkVaRUlDSE5VTkc+S2llbDwvR2ViaWV0QkVaRUlDSE5VTkc+PEdlYmlldEdOUjk0X0dOUj4wMTAwMjAwMDwvR2ViaWV0R05SOTRfR05SPjxzdGFhdD4wMDA8L3N0YWF0Pjxpc28zMTY2bnVtZXJpc2NoPjI3NjwvaXNvMzE2Nm51bWVyaXNjaD48a29udF90ZWxlZm9ubnVtbWVyLz48a29udF9tb2JpbG51bW1lci8+PGtvbnRfdGVsZWZheG51bW1lci8+PGtvbnRfZW1haWwvPjxrb250X2RlbWFpbC8+PC9hbnRyYWdzdGVsbGVyPjxVcGxvYWQxPjxmaWxlIGNvbnRlbnQtdHlwZT0iaW1hZ2UvanBlZyIgZGVzY3JpcHRpb249IiIgaWQ9ImFzc2lzdGFudHMuRTBGQkEzNjFDMTkxRjhCNzIzOTQ5NDY3QUUzMDJCRUEyNEU0NzQ1RSIgbGVuZ3RoPSIxNTUyNTEiPkhlbGdlMS5qcGc8L2ZpbGU+PC9VcGxvYWQxPjxVcGxvYWQyPjxmaWxlIGNvbnRlbnQtdHlwZT0iYXBwbGljYXRpb24vdm5kLm9hc2lzLm9wZW5kb2N1bWVudC50ZXh0IiBkZXNjcmlwdGlvbj0iIiBpZD0iYXNzaXN0YW50cy41MkQ3OUU1QjIxMThEMTc0MDA0NUFCODcxNTE1MzVEQ0FEMjRFOUE3IiBsZW5ndGg9Ijc5OTMiPkhlbGdldGV4dDIub2R0PC9maWxlPjwvVXBsb2FkMj48R2ViaWV0SUQ+OTAwNjQwMjwvR2ViaWV0SUQ+PHp1c3RhZW5kaWdlc3RlbGxlPjxPcmdhbmlzYXRpb25zZWluaGVpdGVuQXVzd2FobD4xMDM2MzQ1NTwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5JRD4xMDM2MzQ1NTwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbklEPjxPcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+TGFuZGVzaGF1cHRzdGFkdCBLaWVsIC0gQsO8cmdlci0gdW5kIE9yZG51bmdzYW10LCBTYWNoYmVyZWljaCBHZWZhaHJlbmFid2VociwgV2FmZmVuYW5nZWxlZ2VuaGVpdGVuLCBKYWdkYmVow7ZyZGUsIEJlc3RhdHR1bmdzYW5nZWxlZ2VuaGVpdGVuPC9PcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+PHN0cmFzc2U+U3RyZXNlbWFubnBsYXR6PC9zdHJhc3NlPjxoYXVzbnVtbWVyPjU8L2hhdXNudW1tZXI+PHBvc3RsZWl0emFobD4yNDEwMzwvcG9zdGxlaXR6YWhsPjxvcnRJRD45MDA2NDAyPC9vcnRJRD48b3J0PktpZWw8L29ydD48dGVsZWZvbm51bW1lci8+PHRlbGVmYXhudW1tZXI+KzQ5IDQzMSA5MDEtNjIxODE8L3RlbGVmYXhudW1tZXI+PGVtYWlsYWRyZXNzZT5HZWZhaHJlbmFid2VockBLaWVsLmRlPC9lbWFpbGFkcmVzc2U+PGRlbWFpbGFkcmVzc2UvPjxrb250YWt0c3lzdGVtX2tlbm51bmcvPjxrb250YWt0c3lzdGVtX2tlbm51bmd6dXNhdHovPjxBbmxpZWdlbkJFWkVJQ0hOVU5HPldhZmZlbnNjaGVpbiAvIEtsZWluZXIgV2FmZmVuc2NoZWluPC9BbmxpZWdlbkJFWkVJQ0hOVU5HPjxsZWlrYUtFWUxJU1Q+OTkwODkwMDgwMDAwMDA7OTkwODkwMDgwMDEwMDA8L2xlaWthS0VZTElTVD48L3p1c3RhZW5kaWdlc3RlbGxlPjxlbXBmYW5nZW5kZXN0ZWxsZT48T3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+OTA2ODg3MzwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5JRD45MDY4ODczPC9PcmdhbmlzYXRpb25zZWluaGVpdGVuSUQ+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5CRVpFSUNITlVORz5FaW5oZWl0bGljaGVyIEFuc3ByZWNocGFydG5lciBTY2hsZXN3aWctSG9sc3RlaW48L09yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5CRVpFSUNITlVORz48c3RyYXNzZT5SZXZlbnRsb3VhbGxlZTwvc3RyYXNzZT48aGF1c251bW1lcj42PC9oYXVzbnVtbWVyPjxwb3N0bGVpdHphaGw+MjQxMDU8L3Bvc3RsZWl0emFobD48b3J0SUQ+OTAwNjQwMjwvb3J0SUQ+PG9ydD5LaWVsPC9vcnQ+PHRlbGVmb25udW1tZXI+KzQ5IDQzMSA5ODgtODY1MDwvdGVsZWZvbm51bW1lcj48dGVsZWZheG51bW1lcj4rNDkgNDMxIDk4OC02MTYxMTExPC90ZWxlZmF4bnVtbWVyPjxlbWFpbGFkcmVzc2U+aW5mb0BlYS1zaC5kZTwvZW1haWxhZHJlc3NlPjxkZW1haWxhZHJlc3NlPmVhLXBvc3RzdGVsbGVAZWEtc2guZGUtbWFpbC5kZTwvZGVtYWlsYWRyZXNzZT48a29udGFrdHN5c3RlbV9rZW5udW5nPmFmbXNoOjkwNjg4NzNfQXVzbmFobWVMS1dGYWhydmVyYm90PC9rb250YWt0c3lzdGVtX2tlbm51bmc+PGtvbnRha3RzeXN0ZW1fa2VubnVuZ3p1c2F0ej5hbGxlPC9rb250YWt0c3lzdGVtX2tlbm51bmd6dXNhdHo+PC9lbXBmYW5nZW5kZXN0ZWxsZT48ZXJrbGFlcnVuZ2VuPjxjaGVja19nZWJ1ZWhyZW4+dHJ1ZTwvY2hlY2tfZ2VidWVocmVuPjxjaGVja19yaWNodGlna2VpdD50cnVlPC9jaGVja19yaWNodGlna2VpdD48Y2hlY2tfZGF0ZW5zY2h1dHo+dHJ1ZTwvY2hlY2tfZGF0ZW5zY2h1dHo+PGNoZWNrX21pc3NicmF1Y2g+dHJ1ZTwvY2hlY2tfbWlzc2JyYXVjaD48Yl9nZWJ1ZWhyZW5fYmVzY2hyaWZ0dW5nPiogTWlyIGlzdCBiZWthbm50LCBkYXNzIGR1cmNoIGRhcyBFaW5yZWljaGVuIGRlcyBlbGVrdHJvbmlzY2hlbiBBbnRyYWdlcyB2b24gZGVyIHp1c3TDpG5kaWdlbiBTdGVsbGUgR2Viw7xocmVuIGVyaG9iZW4gd2VyZGVuIGvDtm5uZW4uPC9iX2dlYnVlaHJlbl9iZXNjaHJpZnR1bmc+PGJfZ2VidWVocmVuX2ludHJvPkdlYsO8aHIgYmVpIEF1c3N0ZWxsdW5nIGRlcyBrbGVpbmVuIFdhZmZlbnNjaGVpbnM6IDYwLDAwIEV1cm8uIEJlYXJiZWl0dW5nc2dlYsO8aHIgYmVpIFZlcnNhZ3VuZzogNDUsMDAgRXVyby4gClNpZSBzaW5kIGdlbcOkw58gwqcgMzkgV2FmZkcgdmVycGZsaWNodGV0LCBkZXIgenVzdMOkbmRpZ2VuIEJlaMO2cmRlIGRpZSB6dXIgRHVyY2hmw7xocnVuZyBkZXMgR2VzZXR6ZXMgZXJmb3JkZXJsaWNoZW4gQXVza8O8bmZ0ZSB6dSBlcnRlaWxlbi4gWnVyIFByw7xmdW5nIElocmVyIHdhZmZlbnJlY2h0bGljaGVuIFp1dmVybMOkc3NpZ2tlaXQgdW5kIEVpZ251bmcgaG9sdCBkaWUgQmVow7ZyZGUgZWluZSB1bmJlc2NocsOkbmt0ZSBBdXNrdW5mdCBhdXMgZGVtIEJ1bmRlc3plbnRyYWxyZWdpc3RlciwgZWluZSBBdXNrdW5mdCBhdXMgZGVtIHplbnRyYWxlbiBzdGFhdHNhbndhbHRzY2hhZnRsaWNoZW4gVmVyZmFocmVuc3JlZ2lzdGVyLCBlaW5lIFN0ZWxsdW5nbmFobWUgZGVyIMO2cnRsaWNoZW4gUG9saXplaWRpZW5zdHN0ZWxsZSB1bmQgSWhyZXIgV29obnNpdHpnZW1laW5kZSBlaW4uPC9iX2dlYnVlaHJlbl9pbnRybz48Yl9yaWNodGlna2VpdD4qIEljaCBiZXN0w6R0aWdlIGRpZSBSaWNodGlna2VpdCBtZWluZXIgQW5nYWJlbi48L2JfcmljaHRpZ2tlaXQ+PGJfZGF0ZW5zY2h1dHo+KiBJY2ggZXJrbMOkcmUgbWljaCBkYW1pdCBlaW52ZXJzdGFuZGVuLCBkYXNzIGRlciBFaW5oZWl0bGljaGVyIEFuc3ByZWNocGFydG5lciBTY2hsZXN3aWctSG9sc3RlaW4genVyIEVyZsO8bGx1bmcgc2VpbmVyIEF1ZmdhYmVuIG1laW5lIERhdGVuIHVudGVyIEVpbmhhbHR1bmcgZGVyIEJlc3RpbW11bmdlbiBkZXIgRGF0ZW5zY2h1dHotR3J1bmR2ZXJvcmRudW5nIChEUy1HVk8pIHVuZCBkZXMgTGFuZGVzZGF0ZW5zY2h1dHpnZXNldHplcyBTY2hsZXN3aWctSG9sc3RlaW4gKExEU0ctU0gpIHNwZWljaGVydCwgdmVyYXJiZWl0ZXQgIHVuZCBkaWVzZSBpbSBSYWhtZW4gZGVyIGdlc2V0emxpY2hlbiBCZXN0aW1tdW5nZW4gYW4gZGllIGbDvHIgZGllIEVudHNjaGVpZHVuZyB6dXN0w6RuZGlnZSBTdGVsbGUgd2VpdGVybGVpdGV0LiBFYmVuc28gYmluIGljaCBtaXQgZGVyIHJlY2h0c2tvbmZvcm1lbiAgRGF0ZW52ZXJhcmJlaXR1bmcgdW5kIFNwZWljaGVydW5nIGR1cmNoIGRpZSB6dXN0w6RuZGlnZSBTdGVsbGUgZWludmVyc3RhbmRlbi4gTWlyIGlzdCBiZWthbm50LCBkYXNzIGljaCBkaWUgRWlud2lsbGlndW5nIGluIGRpZSBWZXJhcmJlaXR1bmcgdW5kIMOcYmVybWl0dGx1bmcgamVkZXJ6ZWl0IGdlZ2Vuw7xiZXIgZGVtIEVpbmhlaXRsaWNoZXIgQW5zcHJlY2hwYXJ0bmVyIFNjaGxlc3dpZy1Ib2xzdGVpbiwgUmV2ZW50bG91YWxsZWUgNiwgMjQxMDUgS2llbCB3aWRlcnJ1ZmVuIGthbm4uIEVpbiBXaWRlcnJ1ZiBpc3QgYWJlciBudXIgd2lya3NhbSBmw7xyIGRpZSBadWt1bmZ0LiBWZXJhcmJlaXR1bmdlbiwgZGllIHZvciBkZW0gV2lkZXJydWYgZXJmb2xndCBzaW5kLCBzaW5kIGRhdm9uIG5pY2h0IGJldHJvZmZlbi4gw5xiZXIgZGllIFZlcmFyYmVpdHVuZyBtZWluZXIgcGVyc29uZW5iZXpvZ2VuZW4gRGF0ZW4gdW5kIGRpZSBtaXIgbmFjaCBkZW4gZGF0ZW5zY2h1dHpyZWNodGxpY2hlbiBSZWdlbHVuZ2VuIHp1c3RlaGVuZGVuIEFuc3Byw7xjaGUgdW5kIFJlY2h0ZSBoYWJlIGljaCB1bnRlciBEYXRlbnNjaHV0emVya2zDpHJ1bmcgS2VubnRuaXMgZXJsYW5ndC48L2JfZGF0ZW5zY2h1dHo+PGJfbWlzc2JyYXVjaD4qIE1pciBpc3QgYmVrYW5udCwgZGFzcyB6dXIgVmVyZm9sZ3VuZyB3aWRlcnJlY2h0bGljaGVyIE51dHp1bmcgZGllIERhdGVuIG1laW5lcyB6dXIgRGF0ZW5laW5nYWJlIGdlbnV0enRlbiBFbmRnZXLDpHRlcyBhdWZnZXplaWNobmV0IHVuZCB2ZXJ3ZW5kZXQgd2VyZGVuIGvDtm5uZW4uPC9iX21pc3NicmF1Y2g+PHBvbGljeXVybD5odHRwOi8vd3d3LmVhLXNoLmluZm8vZGF0ZW5zY2h1dHovZGF0ZW5zY2h1dHplcmtsYWVydW5nRUFfZGUuZG9jPC9wb2xpY3l1cmw+PC9lcmtsYWVydW5nZW4+PGxvZ291cmw+aHR0cDovL3d3dy5lYS1zaC5pbmZvL2xvZ29zL2tvcGZfOTA2ODg3My5kb2M8L2xvZ291cmw+PC9teUZvcm0+", - "subType": "00" - } - } -} \ No newline at end of file + "_id": "61662dfc-cf90-47a8-8fc9-79bbc994ed16", + "vendorId": "myForm-xml", + "name": "XML-Daten.xml", + "contentType": "text/xml", + "size": 5520, + "content": { + "$binary": { + "base64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPG15Rm9ybSB4bWxuczpwZGY9Imh0dHA6Ly94bWxucy5jaXQuZGUvYXNzaXN0YW50cy9wZGYiIHhtbG5zOnQ9Imh0dHA6Ly94bWxucy5jaXQuZGUvaW50ZWxsaWZvcm0vdHJhbnNhY3Rpb24iIHQ6dXVpZD0iZWFjMjQ4MGUtNzE2Ni00YjE2LWJkZGQtODgwNTkxZTdkOTNiIiB0OmlkPSIyMDIxMDQxNTMwNzAyMDQxNDcwMSIgdDp0aW1lc3RhbXA9IjIwMjEtMDQtMTVUMDg6MzE6NDIuMzk4WiIgdDpzZW5kZXI9ImludGVsbGlmb3JtLm96Zy1zaC5kZSIgdDpmb3JtPSJTaW1wbGVGb3JtU2VuZGV0QW5Ib21lU2VydmVyVm9uVG9yc3RlbiIgdDpmb3JtLWlkPSJTaW1wbGVGb3JtU2VuZGV0QW5Ib21lU2VydmVyVm9uVG9yc3RlbiIgdDpjdXN0b21lcj0iS2llbCIgdDpjdXN0b21lci1pZD0iS2llbCIgdDpjbGllbnQ9InNoLWRldiIgdDpjbGllbnQtaWQ9InNoLWRldiI+PEtvbnRha3RzeXN0ZW1UeXBBPjIzMzAzNDYwMDwvS29udGFrdHN5c3RlbVR5cEE+PEtvbnRha3RzeXN0ZW1UeXBCPjIzMzAzNDYwMTwvS29udGFrdHN5c3RlbVR5cEI+PEFubGllZ2VuSUQ+ODk2NjY3MTwvQW5saWVnZW5JRD48YW50cmFnc3RlbGxlcj48c2hfc3RyYXNzZT5BbiBkZXIgU2NobmVpZGVyZWk8L3NoX3N0cmFzc2U+PHNoX2hhdXNudW1tZXI+MTwvc2hfaGF1c251bW1lcj48c2hfcGx6PjI0MTAzPC9zaF9wbHo+PG9ydF9hdXN3YWhsPjkwMDY0MDIkMDEwMDIwMDA8L29ydF9hdXN3YWhsPjxvcnQ+S2llbDwvb3J0PjxHZWJpZXRJRD45MDA2NDAyPC9HZWJpZXRJRD48R2ViaWV0QkVaRUlDSE5VTkc+S2llbDwvR2ViaWV0QkVaRUlDSE5VTkc+PEdlYmlldEdOUjk0X0dOUj4wMTAwMjAwMDwvR2ViaWV0R05SOTRfR05SPjxzdGFhdD4wMDA8L3N0YWF0Pjxpc28zMTY2bnVtZXJpc2NoPjI3NjwvaXNvMzE2Nm51bWVyaXNjaD48a29udF90ZWxlZm9ubnVtbWVyLz48a29udF9tb2JpbG51bW1lci8+PGtvbnRfdGVsZWZheG51bW1lci8+PGtvbnRfZW1haWwvPjxrb250X2RlbWFpbC8+PC9hbnRyYWdzdGVsbGVyPjxVcGxvYWQxPjxmaWxlIGNvbnRlbnQtdHlwZT0iaW1hZ2UvanBlZyIgZGVzY3JpcHRpb249IiIgaWQ9ImFzc2lzdGFudHMuRTBGQkEzNjFDMTkxRjhCNzIzOTQ5NDY3QUUzMDJCRUEyNEU0NzQ1RSIgbGVuZ3RoPSIxNTUyNTEiPkhlbGdlMS5qcGc8L2ZpbGU+PC9VcGxvYWQxPjxVcGxvYWQyPjxmaWxlIGNvbnRlbnQtdHlwZT0iYXBwbGljYXRpb24vdm5kLm9hc2lzLm9wZW5kb2N1bWVudC50ZXh0IiBkZXNjcmlwdGlvbj0iIiBpZD0iYXNzaXN0YW50cy41MkQ3OUU1QjIxMThEMTc0MDA0NUFCODcxNTE1MzVEQ0FEMjRFOUE3IiBsZW5ndGg9Ijc5OTMiPkhlbGdldGV4dDIub2R0PC9maWxlPjwvVXBsb2FkMj48R2ViaWV0SUQ+OTAwNjQwMjwvR2ViaWV0SUQ+PHp1c3RhZW5kaWdlc3RlbGxlPjxPcmdhbmlzYXRpb25zZWluaGVpdGVuQXVzd2FobD4xMDM2MzQ1NTwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5JRD4xMDM2MzQ1NTwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbklEPjxPcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+TGFuZGVzaGF1cHRzdGFkdCBLaWVsIC0gQsO8cmdlci0gdW5kIE9yZG51bmdzYW10LCBTYWNoYmVyZWljaCBHZWZhaHJlbmFid2VociwgV2FmZmVuYW5nZWxlZ2VuaGVpdGVuLCBKYWdkYmVow7ZyZGUsIEJlc3RhdHR1bmdzYW5nZWxlZ2VuaGVpdGVuPC9PcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+PHN0cmFzc2U+U3RyZXNlbWFubnBsYXR6PC9zdHJhc3NlPjxoYXVzbnVtbWVyPjU8L2hhdXNudW1tZXI+PHBvc3RsZWl0emFobD4yNDEwMzwvcG9zdGxlaXR6YWhsPjxvcnRJRD45MDA2NDAyPC9vcnRJRD48b3J0PktpZWw8L29ydD48dGVsZWZvbm51bW1lci8+PHRlbGVmYXhudW1tZXI+KzQ5IDQzMSA5MDEtNjIxODE8L3RlbGVmYXhudW1tZXI+PGVtYWlsYWRyZXNzZT5HZWZhaHJlbmFid2VockBLaWVsLmRlPC9lbWFpbGFkcmVzc2U+PGRlbWFpbGFkcmVzc2UvPjxrb250YWt0c3lzdGVtX2tlbm51bmcvPjxrb250YWt0c3lzdGVtX2tlbm51bmd6dXNhdHovPjxBbmxpZWdlbkJFWkVJQ0hOVU5HPldhZmZlbnNjaGVpbiAvIEtsZWluZXIgV2FmZmVuc2NoZWluPC9BbmxpZWdlbkJFWkVJQ0hOVU5HPjxsZWlrYUtFWUxJU1Q+OTkwODkwMDgwMDAwMDA7OTkwODkwMDgwMDEwMDA8L2xlaWthS0VZTElTVD48L3p1c3RhZW5kaWdlc3RlbGxlPjxlbXBmYW5nZW5kZXN0ZWxsZT48T3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+OTA2ODg3MzwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5JRD45MDY4ODczPC9PcmdhbmlzYXRpb25zZWluaGVpdGVuSUQ+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5CRVpFSUNITlVORz5FaW5oZWl0bGljaGVyIEFuc3ByZWNocGFydG5lciBTY2hsZXN3aWctSG9sc3RlaW48L09yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5CRVpFSUNITlVORz48c3RyYXNzZT5SZXZlbnRsb3VhbGxlZTwvc3RyYXNzZT48aGF1c251bW1lcj42PC9oYXVzbnVtbWVyPjxwb3N0bGVpdHphaGw+MjQxMDU8L3Bvc3RsZWl0emFobD48b3J0SUQ+OTAwNjQwMjwvb3J0SUQ+PG9ydD5LaWVsPC9vcnQ+PHRlbGVmb25udW1tZXI+KzQ5IDQzMSA5ODgtODY1MDwvdGVsZWZvbm51bW1lcj48dGVsZWZheG51bW1lcj4rNDkgNDMxIDk4OC02MTYxMTExPC90ZWxlZmF4bnVtbWVyPjxlbWFpbGFkcmVzc2U+aW5mb0BlYS1zaC5kZTwvZW1haWxhZHJlc3NlPjxkZW1haWxhZHJlc3NlPmVhLXBvc3RzdGVsbGVAZWEtc2guZGUtbWFpbC5kZTwvZGVtYWlsYWRyZXNzZT48a29udGFrdHN5c3RlbV9rZW5udW5nPmFmbXNoOjkwNjg4NzNfQXVzbmFobWVMS1dGYWhydmVyYm90PC9rb250YWt0c3lzdGVtX2tlbm51bmc+PGtvbnRha3RzeXN0ZW1fa2VubnVuZ3p1c2F0ej5hbGxlPC9rb250YWt0c3lzdGVtX2tlbm51bmd6dXNhdHo+PC9lbXBmYW5nZW5kZXN0ZWxsZT48ZXJrbGFlcnVuZ2VuPjxjaGVja19nZWJ1ZWhyZW4+dHJ1ZTwvY2hlY2tfZ2VidWVocmVuPjxjaGVja19yaWNodGlna2VpdD50cnVlPC9jaGVja19yaWNodGlna2VpdD48Y2hlY2tfZGF0ZW5zY2h1dHo+dHJ1ZTwvY2hlY2tfZGF0ZW5zY2h1dHo+PGNoZWNrX21pc3NicmF1Y2g+dHJ1ZTwvY2hlY2tfbWlzc2JyYXVjaD48Yl9nZWJ1ZWhyZW5fYmVzY2hyaWZ0dW5nPiogTWlyIGlzdCBiZWthbm50LCBkYXNzIGR1cmNoIGRhcyBFaW5yZWljaGVuIGRlcyBlbGVrdHJvbmlzY2hlbiBBbnRyYWdlcyB2b24gZGVyIHp1c3TDpG5kaWdlbiBTdGVsbGUgR2Viw7xocmVuIGVyaG9iZW4gd2VyZGVuIGvDtm5uZW4uPC9iX2dlYnVlaHJlbl9iZXNjaHJpZnR1bmc+PGJfZ2VidWVocmVuX2ludHJvPkdlYsO8aHIgYmVpIEF1c3N0ZWxsdW5nIGRlcyBrbGVpbmVuIFdhZmZlbnNjaGVpbnM6IDYwLDAwIEV1cm8uIEJlYXJiZWl0dW5nc2dlYsO8aHIgYmVpIFZlcnNhZ3VuZzogNDUsMDAgRXVyby4gClNpZSBzaW5kIGdlbcOkw58gwqcgMzkgV2FmZkcgdmVycGZsaWNodGV0LCBkZXIgenVzdMOkbmRpZ2VuIEJlaMO2cmRlIGRpZSB6dXIgRHVyY2hmw7xocnVuZyBkZXMgR2VzZXR6ZXMgZXJmb3JkZXJsaWNoZW4gQXVza8O8bmZ0ZSB6dSBlcnRlaWxlbi4gWnVyIFByw7xmdW5nIElocmVyIHdhZmZlbnJlY2h0bGljaGVuIFp1dmVybMOkc3NpZ2tlaXQgdW5kIEVpZ251bmcgaG9sdCBkaWUgQmVow7ZyZGUgZWluZSB1bmJlc2NocsOkbmt0ZSBBdXNrdW5mdCBhdXMgZGVtIEJ1bmRlc3plbnRyYWxyZWdpc3RlciwgZWluZSBBdXNrdW5mdCBhdXMgZGVtIHplbnRyYWxlbiBzdGFhdHNhbndhbHRzY2hhZnRsaWNoZW4gVmVyZmFocmVuc3JlZ2lzdGVyLCBlaW5lIFN0ZWxsdW5nbmFobWUgZGVyIMO2cnRsaWNoZW4gUG9saXplaWRpZW5zdHN0ZWxsZSB1bmQgSWhyZXIgV29obnNpdHpnZW1laW5kZSBlaW4uPC9iX2dlYnVlaHJlbl9pbnRybz48Yl9yaWNodGlna2VpdD4qIEljaCBiZXN0w6R0aWdlIGRpZSBSaWNodGlna2VpdCBtZWluZXIgQW5nYWJlbi48L2JfcmljaHRpZ2tlaXQ+PGJfZGF0ZW5zY2h1dHo+KiBJY2ggZXJrbMOkcmUgbWljaCBkYW1pdCBlaW52ZXJzdGFuZGVuLCBkYXNzIGRlciBFaW5oZWl0bGljaGVyIEFuc3ByZWNocGFydG5lciBTY2hsZXN3aWctSG9sc3RlaW4genVyIEVyZsO8bGx1bmcgc2VpbmVyIEF1ZmdhYmVuIG1laW5lIERhdGVuIHVudGVyIEVpbmhhbHR1bmcgZGVyIEJlc3RpbW11bmdlbiBkZXIgRGF0ZW5zY2h1dHotR3J1bmR2ZXJvcmRudW5nIChEUy1HVk8pIHVuZCBkZXMgTGFuZGVzZGF0ZW5zY2h1dHpnZXNldHplcyBTY2hsZXN3aWctSG9sc3RlaW4gKExEU0ctU0gpIHNwZWljaGVydCwgdmVyYXJiZWl0ZXQgIHVuZCBkaWVzZSBpbSBSYWhtZW4gZGVyIGdlc2V0emxpY2hlbiBCZXN0aW1tdW5nZW4gYW4gZGllIGbDvHIgZGllIEVudHNjaGVpZHVuZyB6dXN0w6RuZGlnZSBTdGVsbGUgd2VpdGVybGVpdGV0LiBFYmVuc28gYmluIGljaCBtaXQgZGVyIHJlY2h0c2tvbmZvcm1lbiAgRGF0ZW52ZXJhcmJlaXR1bmcgdW5kIFNwZWljaGVydW5nIGR1cmNoIGRpZSB6dXN0w6RuZGlnZSBTdGVsbGUgZWludmVyc3RhbmRlbi4gTWlyIGlzdCBiZWthbm50LCBkYXNzIGljaCBkaWUgRWlud2lsbGlndW5nIGluIGRpZSBWZXJhcmJlaXR1bmcgdW5kIMOcYmVybWl0dGx1bmcgamVkZXJ6ZWl0IGdlZ2Vuw7xiZXIgZGVtIEVpbmhlaXRsaWNoZXIgQW5zcHJlY2hwYXJ0bmVyIFNjaGxlc3dpZy1Ib2xzdGVpbiwgUmV2ZW50bG91YWxsZWUgNiwgMjQxMDUgS2llbCB3aWRlcnJ1ZmVuIGthbm4uIEVpbiBXaWRlcnJ1ZiBpc3QgYWJlciBudXIgd2lya3NhbSBmw7xyIGRpZSBadWt1bmZ0LiBWZXJhcmJlaXR1bmdlbiwgZGllIHZvciBkZW0gV2lkZXJydWYgZXJmb2xndCBzaW5kLCBzaW5kIGRhdm9uIG5pY2h0IGJldHJvZmZlbi4gw5xiZXIgZGllIFZlcmFyYmVpdHVuZyBtZWluZXIgcGVyc29uZW5iZXpvZ2VuZW4gRGF0ZW4gdW5kIGRpZSBtaXIgbmFjaCBkZW4gZGF0ZW5zY2h1dHpyZWNodGxpY2hlbiBSZWdlbHVuZ2VuIHp1c3RlaGVuZGVuIEFuc3Byw7xjaGUgdW5kIFJlY2h0ZSBoYWJlIGljaCB1bnRlciBEYXRlbnNjaHV0emVya2zDpHJ1bmcgS2VubnRuaXMgZXJsYW5ndC48L2JfZGF0ZW5zY2h1dHo+PGJfbWlzc2JyYXVjaD4qIE1pciBpc3QgYmVrYW5udCwgZGFzcyB6dXIgVmVyZm9sZ3VuZyB3aWRlcnJlY2h0bGljaGVyIE51dHp1bmcgZGllIERhdGVuIG1laW5lcyB6dXIgRGF0ZW5laW5nYWJlIGdlbnV0enRlbiBFbmRnZXLDpHRlcyBhdWZnZXplaWNobmV0IHVuZCB2ZXJ3ZW5kZXQgd2VyZGVuIGvDtm5uZW4uPC9iX21pc3NicmF1Y2g+PHBvbGljeXVybD5odHRwOi8vd3d3LmVhLXNoLmluZm8vZGF0ZW5zY2h1dHovZGF0ZW5zY2h1dHplcmtsYWVydW5nRUFfZGUuZG9jPC9wb2xpY3l1cmw+PC9lcmtsYWVydW5nZW4+PGxvZ291cmw+aHR0cDovL3d3dy5lYS1zaC5pbmZvL2xvZ29zL2tvcGZfOTA2ODg3My5kb2M8L2xvZ291cmw+PC9teUZvcm0+", + "subType": "00" + } + } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/command/command.json b/alfa-client/apps/alfa-e2e/src/fixtures/command/command.json index 47f3893af6234327ffe583d5e768096c93ac9c09..854f9990ea113f9f3a5c3dd6158050917453b55d 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/command/command.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/command/command.json @@ -1,17 +1,17 @@ { - "vorgangId" : "602566a807bb665df9a86111", - "createdAt" : { - "$date": "2022-06-20T10:51:52.073Z" - }, - "createdBy" : "", - "createdByName" : "", - "status" : "FINISHED", - "relationId" : "602566a807bb665df9a86111", - "relationVersion" : 0, - "order" : "SEND_POSTFACH_MAIL", - "previousStatus" : "NEU", - "_class" : "Command", - "finishedAt" : { - "$date": "2022-06-20T10:51:53.600Z" - } -} \ No newline at end of file + "vorgangId": "602566a807bb665df9a86111", + "createdAt": { + "$date": "2022-06-20T10:51:52.073Z" + }, + "createdBy": "", + "createdByName": "", + "status": "FINISHED", + "relationId": "602566a807bb665df9a86111", + "relationVersion": 0, + "order": "SEND_POSTFACH_MAIL", + "previousStatus": "NEU", + "_class": "Command", + "finishedAt": { + "$date": "2022-06-20T10:51:53.600Z" + } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/jpg/chunk.json b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/jpg/chunk.json index 2cd549e5f619e91448f2ecdf47e4c349b1bb28ad..a2b46bf755c2935d34b460c715854cc4cd3099ea 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/jpg/chunk.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/jpg/chunk.json @@ -1,10 +1,10 @@ { - "_id" : { - "$oid": "6270c62e261af555e8f4f905" - }, - "files_id" : { - "$oid": "6270c62e261af555e8f4f904" - }, - "n" : 0, - "data" : "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" + "_id": { + "$oid": "6270c62e261af555e8f4f905" + }, + "files_id": { + "$oid": "6270c62e261af555e8f4f904" + }, + "n": 0, + "data": "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" } diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/jpg/file.json b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/jpg/file.json index 56781ad78f36a46444094b2c00f2c79b145dd536..7c11a540fe7abb57393df51727f7bc5d63e4a7c2 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/jpg/file.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/jpg/file.json @@ -1,19 +1,19 @@ { - "_id" : { - "$oid": "6270c62e261af555e8f4f904" - }, - "filename" : "602566a807bb665df9a86111/alfa/vorgangAttachment/win.jpg", - "length" : 10129, - "chunkSize" : 261120, - "uploadDate" : { - "$date": "2022-05-03T06:05:34.508Z" - }, - "metadata" : { - "vorgangId" : "602566a807bb665df9a86111", - "client" : "alfa", - "fieldName" : "vorgangAttachment", - "contentType" : "image/jpeg", - "name" : "win.jpg", - "createdBy" : "" - } -} \ No newline at end of file + "_id": { + "$oid": "6270c62e261af555e8f4f904" + }, + "filename": "602566a807bb665df9a86111/alfa/vorgangAttachment/win.jpg", + "length": 10129, + "chunkSize": 261120, + "uploadDate": { + "$date": "2022-05-03T06:05:34.508Z" + }, + "metadata": { + "vorgangId": "602566a807bb665df9a86111", + "client": "alfa", + "fieldName": "vorgangAttachment", + "contentType": "image/jpeg", + "name": "win.jpg", + "createdBy": "" + } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/pdf/chunk.json b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/pdf/chunk.json index 2ff6d8a81a401a9048b1f6a7c8ec777371c3d5b8..41beaa009a234cfae19e355a81de4c10cefe57c3 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/pdf/chunk.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/pdf/chunk.json @@ -1,10 +1,10 @@ { - "_id" : { - "$oid": "6270c62e261af555e8f4f901" - }, - "files_id" : { - "$oid": "6270c62e261af555e8f4f900" - }, - "n" : 0, - "data" : "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wWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0BactOG3BaQtOW3DagtMWnLbgtAWnLThtwWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0BactOG3BaQtOW3DagtMWnLbgtAWnLThtwWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0BactOG3BaQtOW3DagtMWnLZOOn1Cpx047cBpB047cNqB0w6cduC0A6cdOO3AaQdOO3DagdMOnHbgtAOnHTjtwGkHTjtw2oHTDpx24LQDpx047cBpB047cNqB0w6cduC0A6cdOO3AaQdOO3DagdMOnHbgtAOnHTjtwGkHTjtw2oHTDpx24LQDpx047cBpB047cNqB0w6cduC0A6cdOO3AaQdOO3DagdMOnHbgtAOnHTjtwGkHTjtw2oHTDpx24LQDpx047cBp56TTJ3TahdMunHbhtAunXTjtwmkXTrtw2oXTLpx24bQLp1047cJpF067cNqF0y6cduG0C6ddOO3CaRdOu3DahdMunHbhtAunXTjtwmkXTrtw2oXTLpx24bQLp1047cJpF067cNqF0y6cduG0C6ddOO3CaRdOu3DahdMunHbhtAunXTjtwmkXTrtw2oXTLpx24bQLp1047cJpF067cNqF0y6cduG0C6ddOO3CaRdOu3DahdMunHZ/7U7/Eq24sXVOJbyGCKcHzAZzwFywHpgHesFTQQX0gX4wCIZAFdRACppgGIyAUTAOJsAC8AywEDwTbAyeBTYFi8CzwXPA5uB5YDHYErwAbA1eBLYB24KXgu3By8GOYCfwCvBKsDN4FdgFvBrsCnYDu4PXgD3Aa8GeIOIHm8hb8xQQOWwih03ksJkPIodN5LBZH0Q+m8hnMwDy3D7p9ImctuC0BactOG3BaQtOW3DagtMWnLbgtAWnLThtwWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0BactOG3BaQtOW3DagtMWnLbgtAWnLThtwWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0BactOG3BaQtOW3DagtMWnLbgtAWnLThtwWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0Bad/9eXpX8hpG07bcNqG0zactuG0DadtOG3DaRtO23DahtM2nLbh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UqzCLbYLfSPzbw4XJ53jncC4bp2mHu57Gm/A7yGQP5gRtj9dvEt2vzPDpecjpUeZvKdUt3XiXm5g5yhyd2fN7zl4TMTEKovzDbxCXCdJnbv7zScqMvtp85Cj5CFHU31RdjnO1kIknC4t11pdMrvf2A+oBmpVrg30ja3h18cc9z26M3Itlca9qetg8rsPgeq3XzWFPF5/eOEWVTaaxHRM71bVbU5z29yFyMnEgfjqMqrwaVSmsqyH5/kOW9XHkxee9udXTPT1Ux9BWfbuFuv2qXomrBg5vZumLoLMeGjHQvE+vWtxgbC50gbh+YCCOLTCi3h14H8AgIRBbQ0KZW5kc3RyZWFtDQplbmRvYmoNCjE5IDAgb2JqDQo8PC9UeXBlL1hSZWYvU2l6ZSAxOS9XWyAxIDQgMl0gL1Jvb3QgMSAwIFIvSW5mbyA5IDAgUi9JRFs8Qjk4Njk4M0JBQkU3OTM0ODk0REI5RjJGMThFRkQ0MEE+PEI5ODY5ODNCQUJFNzkzNDg5NERCOUYyRjE4RUZENDBBPl0gL0ZpbHRlci9GbGF0ZURlY29kZS9MZW5ndGggNzc+Pg0Kc3RyZWFtDQp4nGNgAIL//xmBpCADA4iqhVBbwRTjYTDFzAihVoIplhkQ6iyYYmViYAAiBgEGJgjFDKFYIBQjhIIqYQVpeA7Wx54OpjicGBgArzoIVQ0KZW5kc3RyZWFtDQplbmRvYmoNCnhyZWYNCjAgMjANCjAwMDAwMDAwMTAgNjU1MzUgZg0KMDAwMDAwMDAxNyAwMDAwMCBuDQowMDAwMDAwMTI1IDAwMDAwIG4NCjAwMDAwMDAxODEgMDAwMDAgbg0KMDAwMDAwMDQ1MSAwMDAwMCBuDQowMDAwMDAwNzY5IDAwMDAwIG4NCjAwMDAwMDA5MzcgMDAwMDAgbg0KMDAwMDAwMTE3NiAwMDAwMCBuDQowMDAwMDAxMjI5IDAwMDAwIG4NCjAwMDAwMDEyODIgMDAwMDAgbg0KMDAwMDAwMDAxMSA2NTUzNSBmDQowMDAwMDAwMDEyIDY1NTM1IGYNCjAwMDAwMDAwMTMgNjU1MzUgZg0KMDAwMDAwMDAxNCA2NTUzNSBmDQowMDAwMDAwMDE1IDY1NTM1IGYNCjAwMDAwMDAwMTYgNjU1MzUgZg0KMDAwMDAwMDAwMCA2NTUzNSBmDQowMDAwMDAxODk1IDAwMDAwIG4NCjAwMDAwMDIxMTQgMDAwMDAgbg0KMDAwMDE4NjU3MSAwMDAwMCBuDQp0cmFpbGVyDQo8PC9TaXplIDIwL1Jvb3QgMSAwIFIvSW5mbyA5IDAgUi9JRFs8Qjk4Njk4M0JBQkU3OTM0ODk0REI5RjJGMThFRkQ0MEE+PEI5ODY5ODNCQUJFNzkzNDg5NERCOUYyRjE4RUZENDBBPl0gPj4NCnN0YXJ0eHJlZg0KMTg2ODQ3DQolJUVPRg0KeHJlZg0KMCAwDQp0cmFpbGVyDQo8PC9TaXplIDIwL1Jvb3QgMSAwIFIvSW5mbyA5IDAgUi9JRFs8Qjk4Njk4M0JBQkU3OTM0ODk0REI5RjJGMThFRkQ0MEE+PEI5ODY5ODNCQUJFNzkzNDg5NERCOUYyRjE4RUZENDBBPl0gL1ByZXYgMTg2ODQ3L1hSZWZTdG0gMTg2NTcxPj4NCnN0YXJ0eHJlZg0KMTg3NDA0DQolJUVPRg==" -} \ No newline at end of file + "_id": { + "$oid": "6270c62e261af555e8f4f901" + }, + "files_id": { + "$oid": "6270c62e261af555e8f4f900" + }, + "n": 0, + "data": "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wWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0BactOG3BaQtOW3DagtMWnLbgtAWnLThtwWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0BactOG3BaQtOW3DagtMWnLbgtAWnLThtwWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0BactOG3BaQtOW3DagtMWnLZOOn1Cpx047cBpB047cNqB0w6cduC0A6cdOO3AaQdOO3DagdMOnHbgtAOnHTjtwGkHTjtw2oHTDpx24LQDpx047cBpB047cNqB0w6cduC0A6cdOO3AaQdOO3DagdMOnHbgtAOnHTjtwGkHTjtw2oHTDpx24LQDpx047cBpB047cNqB0w6cduC0A6cdOO3AaQdOO3DagdMOnHbgtAOnHTjtwGkHTjtw2oHTDpx24LQDpx047cBp56TTJ3TahdMunHbhtAunXTjtwmkXTrtw2oXTLpx24bQLp1047cJpF067cNqF0y6cduG0C6ddOO3CaRdOu3DahdMunHbhtAunXTjtwmkXTrtw2oXTLpx24bQLp1047cJpF067cNqF0y6cduG0C6ddOO3CaRdOu3DahdMunHbhtAunXTjtwmkXTrtw2oXTLpx24bQLp1047cJpF067cNqF0y6cduG0C6ddOO3CaRdOu3DahdMunHZ/7U7/Eq24sXVOJbyGCKcHzAZzwFywHpgHesFTQQX0gX4wCIZAFdRACppgGIyAUTAOJsAC8AywEDwTbAyeBTYFi8CzwXPA5uB5YDHYErwAbA1eBLYB24KXgu3By8GOYCfwCvBKsDN4FdgFvBrsCnYDu4PXgD3Aa8GeIOIHm8hb8xQQOWwih03ksJkPIodN5LBZH0Q+m8hnMwDy3D7p9ImctuC0BactOG3BaQtOW3DagtMWnLbgtAWnLThtwWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0BactOG3BaQtOW3DagtMWnLbgtAWnLThtwWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0BactOG3BaQtOW3DagtMWnLbgtAWnLThtwWkLTltw2oLTFpy24LQFpy04bcFpC05bcNqC0xactuC0Bad/9eXpX8hpG07bcNqG0zactuG0DadtOG3DaRtO23DahtM2nLbh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UqzCLbYLfSPzbw4XJ53jncC4bp2mHu57Gm/A7yGQP5gRtj9dvEt2vzPDpecjpUeZvKdUt3XiXm5g5yhyd2fN7zl4TMTEKovzDbxCXCdJnbv7zScqMvtp85Cj5CFHU31RdjnO1kIknC4t11pdMrvf2A+oBmpVrg30ja3h18cc9z26M3Itlca9qetg8rsPgeq3XzWFPF5/eOEWVTaaxHRM71bVbU5z29yFyMnEgfjqMqrwaVSmsqyH5/kOW9XHkxee9udXTPT1Ux9BWfbuFuv2qXomrBg5vZumLoLMeGjHQvE+vWtxgbC50gbh+YCCOLTCi3h14H8AgIRBbQ0KZW5kc3RyZWFtDQplbmRvYmoNCjE5IDAgb2JqDQo8PC9UeXBlL1hSZWYvU2l6ZSAxOS9XWyAxIDQgMl0gL1Jvb3QgMSAwIFIvSW5mbyA5IDAgUi9JRFs8Qjk4Njk4M0JBQkU3OTM0ODk0REI5RjJGMThFRkQ0MEE+PEI5ODY5ODNCQUJFNzkzNDg5NERCOUYyRjE4RUZENDBBPl0gL0ZpbHRlci9GbGF0ZURlY29kZS9MZW5ndGggNzc+Pg0Kc3RyZWFtDQp4nGNgAIL//xmBpCADA4iqhVBbwRTjYTDFzAihVoIplhkQ6iyYYmViYAAiBgEGJgjFDKFYIBQjhIIqYQVpeA7Wx54OpjicGBgArzoIVQ0KZW5kc3RyZWFtDQplbmRvYmoNCnhyZWYNCjAgMjANCjAwMDAwMDAwMTAgNjU1MzUgZg0KMDAwMDAwMDAxNyAwMDAwMCBuDQowMDAwMDAwMTI1IDAwMDAwIG4NCjAwMDAwMDAxODEgMDAwMDAgbg0KMDAwMDAwMDQ1MSAwMDAwMCBuDQowMDAwMDAwNzY5IDAwMDAwIG4NCjAwMDAwMDA5MzcgMDAwMDAgbg0KMDAwMDAwMTE3NiAwMDAwMCBuDQowMDAwMDAxMjI5IDAwMDAwIG4NCjAwMDAwMDEyODIgMDAwMDAgbg0KMDAwMDAwMDAxMSA2NTUzNSBmDQowMDAwMDAwMDEyIDY1NTM1IGYNCjAwMDAwMDAwMTMgNjU1MzUgZg0KMDAwMDAwMDAxNCA2NTUzNSBmDQowMDAwMDAwMDE1IDY1NTM1IGYNCjAwMDAwMDAwMTYgNjU1MzUgZg0KMDAwMDAwMDAwMCA2NTUzNSBmDQowMDAwMDAxODk1IDAwMDAwIG4NCjAwMDAwMDIxMTQgMDAwMDAgbg0KMDAwMDE4NjU3MSAwMDAwMCBuDQp0cmFpbGVyDQo8PC9TaXplIDIwL1Jvb3QgMSAwIFIvSW5mbyA5IDAgUi9JRFs8Qjk4Njk4M0JBQkU3OTM0ODk0REI5RjJGMThFRkQ0MEE+PEI5ODY5ODNCQUJFNzkzNDg5NERCOUYyRjE4RUZENDBBPl0gPj4NCnN0YXJ0eHJlZg0KMTg2ODQ3DQolJUVPRg0KeHJlZg0KMCAwDQp0cmFpbGVyDQo8PC9TaXplIDIwL1Jvb3QgMSAwIFIvSW5mbyA5IDAgUi9JRFs8Qjk4Njk4M0JBQkU3OTM0ODk0REI5RjJGMThFRkQ0MEE+PEI5ODY5ODNCQUJFNzkzNDg5NERCOUYyRjE4RUZENDBBPl0gL1ByZXYgMTg2ODQ3L1hSZWZTdG0gMTg2NTcxPj4NCnN0YXJ0eHJlZg0KMTg3NDA0DQolJUVPRg==" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/pdf/file.json b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/pdf/file.json index a9ea07c1bb4096f1415796f0d51efcc3a3a40f32..398ce180a658e2d422edcc4b79ecc79da03d83b5 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/pdf/file.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/pdf/file.json @@ -1,19 +1,19 @@ { - "_id" : { - "$oid": "6270c62e261af555e8f4f900" - }, - "filename" : "602566a807bb665df9a86111/alfa/vorgangAttachment/Anlage Vollmacht.pdf", - "length" : 187585, - "chunkSize" : 261120, - "uploadDate" : { - "$date": "2022-05-03T06:05:34.491Z" - }, - "metadata" : { - "vorgangId" : "602566a807bb665df9a86111", - "client" : "alfa", - "fieldName" : "vorgangAttachment", - "contentType" : "application/pdf", - "name" : "Anlage Vollmacht.pdf", - "createdBy" : "" - } -} \ No newline at end of file + "_id": { + "$oid": "6270c62e261af555e8f4f900" + }, + "filename": "602566a807bb665df9a86111/alfa/vorgangAttachment/Anlage Vollmacht.pdf", + "length": 187585, + "chunkSize": 261120, + "uploadDate": { + "$date": "2022-05-03T06:05:34.491Z" + }, + "metadata": { + "vorgangId": "602566a807bb665df9a86111", + "client": "alfa", + "fieldName": "vorgangAttachment", + "contentType": "application/pdf", + "name": "Anlage Vollmacht.pdf", + "createdBy": "" + } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/xml/chunk.json b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/xml/chunk.json index d59dba94bc4d3767c91da2744b05a4cd19329f38..07573cf9854194c00bccacd4d43785d677e5a596 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/xml/chunk.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/xml/chunk.json @@ -1,10 +1,10 @@ { - "_id" : { - "$oid": "626e444157089b0cc5dcede8" - }, - "files_id" : { - "$oid": "626e444157089b0cc5dceddc" - }, - "n" : 0, - "data" : "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPG15Rm9ybSB4bWxuczp0PSJodHRwOi8veG1sbnMuY2l0LmRlL2ludGVsbGlmb3JtL3RyYW5zYWN0aW9uIiB0OmZvcm0tdmVyc2lvbj0iMi4wMTMiIHQ6dXVpZD0iNzgxNGI2YjUtMmZlYy00ZDBiLTg4OGYtYTM3N2ExOWIwZGEzIiB0OmlkPSIyMDIxMTIwODQyNjkyMDE3OTIwMCIgdDp0aW1lc3RhbXA9IjIwMjEtMTItMDhUMTA6NTE6MzIuNTMxWiIgdDpzZW5kZXI9InN0YWdlLmFmbS5zY2hsZXN3aWctaG9sc3RlaW4uZGUiIHQ6Zm9ybT0iV2FobGhlbGZlcmluIHdlcmRlbiIgdDpmb3JtLWlkPSJvZHBfd2FobGhlbGZlci9vZHBfd2FobGhlbGZlciIgdDpjdXN0b21lcj0iU2NobGVzd2lnLUhvbHN0ZWluIiB0OmN1c3RvbWVyLWlkPSJzaCIgdDpjbGllbnQ9IlNjaGxlc3dpZy1Ib2xzdGVpbiIgdDpjbGllbnQtaWQ9ImxhbmQiPjxnZWJpZXRfaWQ+OTAwNzE3ODwvZ2ViaWV0X2lkPjxzZXNzaW9uaWQ+ZjA1M2M0MmMtZjU0ZS00ZTZlLWIxODMtNWVmM2QxZDFlMDQyPC9zZXNzaW9uaWQ+PGFubGllZ2VuX2lkPjg5Njc5MTM8L2FubGllZ2VuX2lkPjx6c3Rfb25saW5lX2RpZW5zdD5XYWhsaGVsZmVyIC0gQWx0ZW5ob2x6L0UtTWFpbC1adXN0ZWxsdW5nOzI1NDQwNDQwMDtodHRwczovL3d3dy5kYXRhcG9ydC5kZS9kYXRlbnNjaHV0ei87aHR0cHM6Ly93d3cuZGF0YXBvcnQuZGUvaW1wcmVzc3VtLztFTUFJTF9MTjs7b2xhZi5sZWllckBkYXRhcG9ydC5kZTs7dHJ1ZTwvenN0X29ubGluZV9kaWVuc3Q+PGdlYmlldGJlemVpY2hudW5nPkFsdGVuaG9sejwvZ2ViaWV0YmV6ZWljaG51bmc+PGRhdGVuc2NodXR6X3p1c3RpbW11bmc+dHJ1ZTwvZGF0ZW5zY2h1dHpfenVzdGltbXVuZz48d2FobD5MYW5kdGFnc3dhaGwgU2NobGVzd2lnIEhvaGxzdGVpbiA4LiBNYWkgMjAyMjwvd2FobD48d2VpdGVyZV93YWhsZW4+dHJ1ZTwvd2VpdGVyZV93YWhsZW4+PGVpbnNhdHpvcnQ+PGF1c3NlcmhhbGIgbGFiZWw9Ik5pY2h0IGltIGVpZ2VuZW4gV2FobGJlemlyayI+ZmFsc2U8L2F1c3NlcmhhbGI+PG90aGVyIGxhYmVsPSIiPmZhbHNlPC9vdGhlcj48d29obm9ydCBsYWJlbD0iTnVyIGluIFdvaG5vcnRuw6RoZSI+dHJ1ZTwvd29obm9ydD48L2VpbnNhdHpvcnQ+PGVyZmFocnVuZz5KYTwvZXJmYWhydW5nPjxmdW5rdGlvbj48YmVpc2l0emVyIGxhYmVsPSJCZWlzaXR6ZXI6aW4iPmZhbHNlPC9iZWlzaXR6ZXI+PHNjaHJpZnRmdWVocmVyIGxhYmVsPSJTY2hyaWZ0ZsO8aHJlcjppbiI+ZmFsc2U8L3NjaHJpZnRmdWVocmVyPjxzdGVsbF9zY2hyaWZ0ZnVlaHJlciBsYWJlbD0iU3RlbGx2ZXJ0cmV0ZW5kZTpyIFNjaHJpZnRmw7xocmVyOmluIj5mYWxzZTwvc3RlbGxfc2NocmlmdGZ1ZWhyZXI+PHN0ZWxsX3dhaGx2b3JzdGVoZXIgbGFiZWw9IlN0ZWxsdmVydHJldGVuZGU6ciBXYWhsdm9yc3RlaGVyOmluIj5mYWxzZTwvc3RlbGxfd2FobHZvcnN0ZWhlcj48d2FobHZvcnN0ZWhlciBsYWJlbD0iV2FobHZvcnN0ZWhlcjppbiI+dHJ1ZTwvd2FobHZvcnN0ZWhlcj48L2Z1bmt0aW9uPjxwb3N0ZmFjaG5hY2hyaWNodD5TZWhyIGdlZWhydGUvciBBbnplaWdlbmRlKnIsICZsdDtici8mZ3Q7Jmx0O2JyLyZndDtJaHIgQW50cmFnIHd1cmRlIGFuIGRpZSB6dXN0w6RuZGlnZSBTdGVsbGUgZ2VzZW5kZXQuJmx0O2JyLyZndDsmbHQ7YnIvJmd0O0locmUgVm9yZ2FuZ3NudW1tZXIgdW5kIHp1c3TDpG5kaWdlIFN0ZWxsZSBmaW5kZW4gU2llIGltIGFuZ2Vow6RuZ3RlbiBEb2t1bWVudC4mbHQ7YnIvJmd0O0JpdHRlIGdlYmVuIFNpZSBkaWVzZSBWb3JnYW5nc251bW1lciBiZWkgYWxsZW4gQW5mcmFnZW4genUgSWhyZXIgQW56ZWlnZSBhbi4mbHQ7YnIvJmd0OyZsdDtici8mZ3Q7Jmx0O2JyLyZndDtNaXQgZnJldW5kbGljaGVuIEdyw7zDn2VuJmx0O2JyLyZndDtJaHJlIE9ubGluZS1CZWjDtnJkZSZsdDtici8mZ3Q7Jmx0O2JyLyZndDs8L3Bvc3RmYWNobmFjaHJpY2h0PjxuYW1laWQvPjxyZXN0X3Jlc3BvbnNlX25hbWUvPjxtYWlsYm94Z3VpZC8+PG5hY2huYW1lPmZyZ2g8L25hY2huYW1lPjx2b3JuYW1lPmZyZ2g8L3Zvcm5hbWU+PGdlYnVydHNkYXR1bS8+PHN0YWF0ZW4+REU8L3N0YWF0ZW4+PHN0cmFzc2VfbnI+PHN0cmFzc2VfbnItaXRlbT48c3RyYXNzZT5zZmc8L3N0cmFzc2U+PGhhdXNudW1tZXI+MjI8L2hhdXNudW1tZXI+PGFkcmVzc3p1c2F0ei8+PC9zdHJhc3NlX25yLWl0ZW0+PC9zdHJhc3NlX25yPjxwbHpfb3J0PjxwbHpfb3J0LWl0ZW0+PHBvc3RsZWl0emFobD4yMjIyMjwvcG9zdGxlaXR6YWhsPjxvcnQ+c2RmZ3NmZDwvb3J0PjwvcGx6X29ydC1pdGVtPjwvcGx6X29ydD48ZW1haWw+c2RmZ3NAYXNkZi5jb208L2VtYWlsPjx0ZWxlZm9uPjIzNDwvdGVsZWZvbj48T3JnYW5pc2F0aW9uc2VpbmhlaXRlbklEPjI1NDQwNDQwMDwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbklEPjxPcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+RGF0YXBvcnQtQUZNLVNILUVudHdpY2tsdW5nPC9PcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+PHp1c3Rfa29udGFrdHN5c3RlbWtlbm51bmdfbmIvPjx6dXN0X2tvbnRha3RzeXN0ZW1rZW5udW5nX2xuPm9sYWYubGVpZXJAZGF0YXBvcnQuZGU8L3p1c3Rfa29udGFrdHN5c3RlbWtlbm51bmdfbG4+PHp1c3Rfa29udGFrdHN5c3RlbWtlbm51bmdfd3MvPjx6dXN0X3N0cmFzc2U+QWx0ZW5ob2x6ZXIgU3RyYcOfZTwvenVzdF9zdHJhc3NlPjx6dXN0X2hhdXNudW1tZXI+MTA8L3p1c3RfaGF1c251bW1lcj48enVzdF9wb3N0bGVpdHphaGw+MjQxNjE8L3p1c3RfcG9zdGxlaXR6YWhsPjxvcnRJRD45MDA3MTc4PC9vcnRJRD48enVzdF9vcnQ+QWx0ZW5ob2x6PC96dXN0X29ydD48enVzdF90ZWxlZm9ubnVtbWVyPis0OSA0MCA0Mjg0Ni00MDMyPC96dXN0X3RlbGVmb25udW1tZXI+PHp1c3RfZmF4bnVtbWVyLz48enVzdF9lbWFpbGFkcmVzc2U+UmFtaW4uSmV5cmFuaUBkYXRhcG9ydC5kZTwvenVzdF9lbWFpbGFkcmVzc2U+PHp1c3RlbGx1bmdfbmFjaHJpY2h0ZW5icm9rZXI+ZmFsc2U8L3p1c3RlbGx1bmdfbmFjaHJpY2h0ZW5icm9rZXI+PHp1c3RlbGx1bmdfZWxla3Ryb25pc2NoPnRydWU8L3p1c3RlbGx1bmdfZWxla3Ryb25pc2NoPjwvbXlGb3JtPg==" -} \ No newline at end of file + "_id": { + "$oid": "626e444157089b0cc5dcede8" + }, + "files_id": { + "$oid": "626e444157089b0cc5dceddc" + }, + "n": 0, + "data": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPG15Rm9ybSB4bWxuczp0PSJodHRwOi8veG1sbnMuY2l0LmRlL2ludGVsbGlmb3JtL3RyYW5zYWN0aW9uIiB0OmZvcm0tdmVyc2lvbj0iMi4wMTMiIHQ6dXVpZD0iNzgxNGI2YjUtMmZlYy00ZDBiLTg4OGYtYTM3N2ExOWIwZGEzIiB0OmlkPSIyMDIxMTIwODQyNjkyMDE3OTIwMCIgdDp0aW1lc3RhbXA9IjIwMjEtMTItMDhUMTA6NTE6MzIuNTMxWiIgdDpzZW5kZXI9InN0YWdlLmFmbS5zY2hsZXN3aWctaG9sc3RlaW4uZGUiIHQ6Zm9ybT0iV2FobGhlbGZlcmluIHdlcmRlbiIgdDpmb3JtLWlkPSJvZHBfd2FobGhlbGZlci9vZHBfd2FobGhlbGZlciIgdDpjdXN0b21lcj0iU2NobGVzd2lnLUhvbHN0ZWluIiB0OmN1c3RvbWVyLWlkPSJzaCIgdDpjbGllbnQ9IlNjaGxlc3dpZy1Ib2xzdGVpbiIgdDpjbGllbnQtaWQ9ImxhbmQiPjxnZWJpZXRfaWQ+OTAwNzE3ODwvZ2ViaWV0X2lkPjxzZXNzaW9uaWQ+ZjA1M2M0MmMtZjU0ZS00ZTZlLWIxODMtNWVmM2QxZDFlMDQyPC9zZXNzaW9uaWQ+PGFubGllZ2VuX2lkPjg5Njc5MTM8L2FubGllZ2VuX2lkPjx6c3Rfb25saW5lX2RpZW5zdD5XYWhsaGVsZmVyIC0gQWx0ZW5ob2x6L0UtTWFpbC1adXN0ZWxsdW5nOzI1NDQwNDQwMDtodHRwczovL3d3dy5kYXRhcG9ydC5kZS9kYXRlbnNjaHV0ei87aHR0cHM6Ly93d3cuZGF0YXBvcnQuZGUvaW1wcmVzc3VtLztFTUFJTF9MTjs7b2xhZi5sZWllckBkYXRhcG9ydC5kZTs7dHJ1ZTwvenN0X29ubGluZV9kaWVuc3Q+PGdlYmlldGJlemVpY2hudW5nPkFsdGVuaG9sejwvZ2ViaWV0YmV6ZWljaG51bmc+PGRhdGVuc2NodXR6X3p1c3RpbW11bmc+dHJ1ZTwvZGF0ZW5zY2h1dHpfenVzdGltbXVuZz48d2FobD5MYW5kdGFnc3dhaGwgU2NobGVzd2lnIEhvaGxzdGVpbiA4LiBNYWkgMjAyMjwvd2FobD48d2VpdGVyZV93YWhsZW4+dHJ1ZTwvd2VpdGVyZV93YWhsZW4+PGVpbnNhdHpvcnQ+PGF1c3NlcmhhbGIgbGFiZWw9Ik5pY2h0IGltIGVpZ2VuZW4gV2FobGJlemlyayI+ZmFsc2U8L2F1c3NlcmhhbGI+PG90aGVyIGxhYmVsPSIiPmZhbHNlPC9vdGhlcj48d29obm9ydCBsYWJlbD0iTnVyIGluIFdvaG5vcnRuw6RoZSI+dHJ1ZTwvd29obm9ydD48L2VpbnNhdHpvcnQ+PGVyZmFocnVuZz5KYTwvZXJmYWhydW5nPjxmdW5rdGlvbj48YmVpc2l0emVyIGxhYmVsPSJCZWlzaXR6ZXI6aW4iPmZhbHNlPC9iZWlzaXR6ZXI+PHNjaHJpZnRmdWVocmVyIGxhYmVsPSJTY2hyaWZ0ZsO8aHJlcjppbiI+ZmFsc2U8L3NjaHJpZnRmdWVocmVyPjxzdGVsbF9zY2hyaWZ0ZnVlaHJlciBsYWJlbD0iU3RlbGx2ZXJ0cmV0ZW5kZTpyIFNjaHJpZnRmw7xocmVyOmluIj5mYWxzZTwvc3RlbGxfc2NocmlmdGZ1ZWhyZXI+PHN0ZWxsX3dhaGx2b3JzdGVoZXIgbGFiZWw9IlN0ZWxsdmVydHJldGVuZGU6ciBXYWhsdm9yc3RlaGVyOmluIj5mYWxzZTwvc3RlbGxfd2FobHZvcnN0ZWhlcj48d2FobHZvcnN0ZWhlciBsYWJlbD0iV2FobHZvcnN0ZWhlcjppbiI+dHJ1ZTwvd2FobHZvcnN0ZWhlcj48L2Z1bmt0aW9uPjxwb3N0ZmFjaG5hY2hyaWNodD5TZWhyIGdlZWhydGUvciBBbnplaWdlbmRlKnIsICZsdDtici8mZ3Q7Jmx0O2JyLyZndDtJaHIgQW50cmFnIHd1cmRlIGFuIGRpZSB6dXN0w6RuZGlnZSBTdGVsbGUgZ2VzZW5kZXQuJmx0O2JyLyZndDsmbHQ7YnIvJmd0O0locmUgVm9yZ2FuZ3NudW1tZXIgdW5kIHp1c3TDpG5kaWdlIFN0ZWxsZSBmaW5kZW4gU2llIGltIGFuZ2Vow6RuZ3RlbiBEb2t1bWVudC4mbHQ7YnIvJmd0O0JpdHRlIGdlYmVuIFNpZSBkaWVzZSBWb3JnYW5nc251bW1lciBiZWkgYWxsZW4gQW5mcmFnZW4genUgSWhyZXIgQW56ZWlnZSBhbi4mbHQ7YnIvJmd0OyZsdDtici8mZ3Q7Jmx0O2JyLyZndDtNaXQgZnJldW5kbGljaGVuIEdyw7zDn2VuJmx0O2JyLyZndDtJaHJlIE9ubGluZS1CZWjDtnJkZSZsdDtici8mZ3Q7Jmx0O2JyLyZndDs8L3Bvc3RmYWNobmFjaHJpY2h0PjxuYW1laWQvPjxyZXN0X3Jlc3BvbnNlX25hbWUvPjxtYWlsYm94Z3VpZC8+PG5hY2huYW1lPmZyZ2g8L25hY2huYW1lPjx2b3JuYW1lPmZyZ2g8L3Zvcm5hbWU+PGdlYnVydHNkYXR1bS8+PHN0YWF0ZW4+REU8L3N0YWF0ZW4+PHN0cmFzc2VfbnI+PHN0cmFzc2VfbnItaXRlbT48c3RyYXNzZT5zZmc8L3N0cmFzc2U+PGhhdXNudW1tZXI+MjI8L2hhdXNudW1tZXI+PGFkcmVzc3p1c2F0ei8+PC9zdHJhc3NlX25yLWl0ZW0+PC9zdHJhc3NlX25yPjxwbHpfb3J0PjxwbHpfb3J0LWl0ZW0+PHBvc3RsZWl0emFobD4yMjIyMjwvcG9zdGxlaXR6YWhsPjxvcnQ+c2RmZ3NmZDwvb3J0PjwvcGx6X29ydC1pdGVtPjwvcGx6X29ydD48ZW1haWw+c2RmZ3NAYXNkZi5jb208L2VtYWlsPjx0ZWxlZm9uPjIzNDwvdGVsZWZvbj48T3JnYW5pc2F0aW9uc2VpbmhlaXRlbklEPjI1NDQwNDQwMDwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbklEPjxPcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+RGF0YXBvcnQtQUZNLVNILUVudHdpY2tsdW5nPC9PcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+PHp1c3Rfa29udGFrdHN5c3RlbWtlbm51bmdfbmIvPjx6dXN0X2tvbnRha3RzeXN0ZW1rZW5udW5nX2xuPm9sYWYubGVpZXJAZGF0YXBvcnQuZGU8L3p1c3Rfa29udGFrdHN5c3RlbWtlbm51bmdfbG4+PHp1c3Rfa29udGFrdHN5c3RlbWtlbm51bmdfd3MvPjx6dXN0X3N0cmFzc2U+QWx0ZW5ob2x6ZXIgU3RyYcOfZTwvenVzdF9zdHJhc3NlPjx6dXN0X2hhdXNudW1tZXI+MTA8L3p1c3RfaGF1c251bW1lcj48enVzdF9wb3N0bGVpdHphaGw+MjQxNjE8L3p1c3RfcG9zdGxlaXR6YWhsPjxvcnRJRD45MDA3MTc4PC9vcnRJRD48enVzdF9vcnQ+QWx0ZW5ob2x6PC96dXN0X29ydD48enVzdF90ZWxlZm9ubnVtbWVyPis0OSA0MCA0Mjg0Ni00MDMyPC96dXN0X3RlbGVmb25udW1tZXI+PHp1c3RfZmF4bnVtbWVyLz48enVzdF9lbWFpbGFkcmVzc2U+UmFtaW4uSmV5cmFuaUBkYXRhcG9ydC5kZTwvenVzdF9lbWFpbGFkcmVzc2U+PHp1c3RlbGx1bmdfbmFjaHJpY2h0ZW5icm9rZXI+ZmFsc2U8L3p1c3RlbGx1bmdfbmFjaHJpY2h0ZW5icm9rZXI+PHp1c3RlbGx1bmdfZWxla3Ryb25pc2NoPnRydWU8L3p1c3RlbGx1bmdfZWxla3Ryb25pc2NoPjwvbXlGb3JtPg==" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/xml/file.json b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/xml/file.json index 73ea967fbd9de4d40d170aba1b46f8f0af4efa2a..b7c9bf892a60293fcdb086358959d249ff08617b 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/xml/file.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/grid-fs/xml/file.json @@ -1,19 +1,19 @@ { - "_id" : { - "$oid": "626e444157089b0cc5dceddc" - }, - "filename" : "602566a807bb665df9a86111/alfa/vorgangAttachment/XML-Daten.xml", - "length" : 3145, - "chunkSize" : 261120, - "uploadDate" : { - "$date": "2022-05-01T08:26:41.623Z" - }, - "metadata" : { - "vorgangId" : "602566a807bb665df9a86111", - "client" : "eingangAdapter", - "fieldName" : "vorgangAttachment", - "contentType" : "text/xml", - "name" : "XML-Daten.xml", - "createdBy" : "" - } -} \ No newline at end of file + "_id": { + "$oid": "626e444157089b0cc5dceddc" + }, + "filename": "602566a807bb665df9a86111/alfa/vorgangAttachment/XML-Daten.xml", + "length": 3145, + "chunkSize": 261120, + "uploadDate": { + "$date": "2022-05-01T08:26:41.623Z" + }, + "metadata": { + "vorgangId": "602566a807bb665df9a86111", + "client": "eingangAdapter", + "fieldName": "vorgangAttachment", + "contentType": "text/xml", + "name": "XML-Daten.xml", + "createdBy": "" + } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/group/abtl-10_0_1.json b/alfa-client/apps/alfa-e2e/src/fixtures/group/abtl-10_0_1.json index 07483c74a050745354660403f39b4d0309233177..e32214f74fc737924d5dd392e806726216753352 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/group/abtl-10_0_1.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/group/abtl-10_0_1.json @@ -1,5 +1,5 @@ { - "name": "Abtl. 10.0.1 Versammlungsbehörde, Identitätsfeststellung, Fundbüro", - "path": "/Abtl. 10.0.1 Versammlungsbehörde, Identitätsfeststellung, Fundbüro", - "attributes": {"organisationseinheitId": "9030229"} -} \ No newline at end of file + "name": "Abtl. 10.0.1 Versammlungsbehörde, Identitätsfeststellung, Fundbüro", + "path": "/Abtl. 10.0.1 Versammlungsbehörde, Identitätsfeststellung, Fundbüro", + "attributes": { "organisationseinheitId": "9030229" } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/group/abtl-10_5_1_2.json b/alfa-client/apps/alfa-e2e/src/fixtures/group/abtl-10_5_1_2.json index 9fb92d7751b9362807c0ac0e8b20daeb8711690c..37e9b8c7ed3a0deb631e317bd446fd66528c50cc 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/group/abtl-10_5_1_2.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/group/abtl-10_5_1_2.json @@ -1,5 +1,5 @@ { - "name": "Abtl. 10.5.1.2 Allgemeine Gefahrenabwehr und sonstige Ordnungsrechtsangelegenheiten", - "path": "/Abtl. 10.5.1.2 Allgemeine Gefahrenabwehr und sonstige Ordnungsrechtsangelegenheiten", - "attributes": {"organisationseinheitId": "10363455"} -} \ No newline at end of file + "name": "Abtl. 10.5.1.2 Allgemeine Gefahrenabwehr und sonstige Ordnungsrechtsangelegenheiten", + "path": "/Abtl. 10.5.1.2 Allgemeine Gefahrenabwehr und sonstige Ordnungsrechtsangelegenheiten", + "attributes": { "organisationseinheitId": "10363455" } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/group/e2e.json b/alfa-client/apps/alfa-e2e/src/fixtures/group/e2e.json index 2314bf420a64111989a03915de49a1ad74454989..7c4dcab09d9b548a451e66b1ff78de1766dee7e9 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/group/e2e.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/group/e2e.json @@ -1,5 +1,5 @@ { - "name": "E2E Tests", - "path": "/E2E Tests", - "attributes": {"organisationseinheitId": "12345678"} -} \ No newline at end of file + "name": "E2E Tests", + "path": "/E2E Tests", + "attributes": { "organisationseinheitId": "12345678" } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/kommentar/kommentar.json b/alfa-client/apps/alfa-e2e/src/fixtures/kommentar/kommentar.json index e8440df0ff024a362f4396fe58886b89932354e5..f1bad2ba77535e6b15dc38f9b896a3ef04ec7b2e 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/kommentar/kommentar.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/kommentar/kommentar.json @@ -1,5 +1,5 @@ { - "createdAt": "2024-01-10T12:57:35Z[UTC]", - "createdBy": "SetInCode", - "text": "Test text to test the test text test" -} \ No newline at end of file + "createdAt": "2024-01-10T12:57:35Z[UTC]", + "createdBy": "SetInCode", + "text": "Test text to test the test text test" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/loesch-anforderung/loesch-anforderung.json b/alfa-client/apps/alfa-e2e/src/fixtures/loesch-anforderung/loesch-anforderung.json index 39726b00f85b745e92a322b29757dd95601003f9..8e2c7c2fe8535d840a5c88892af37e4c865aea73 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/loesch-anforderung/loesch-anforderung.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/loesch-anforderung/loesch-anforderung.json @@ -1,4 +1,4 @@ { - "prevStatus": "ABGESCHLOSSEN", - "requestedBy": "63284e55c39b316b2ad02e2d" -} \ No newline at end of file + "prevStatus": "ABGESCHLOSSEN", + "requestedBy": "63284e55c39b316b2ad02e2d" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/main.json b/alfa-client/apps/alfa-e2e/src/fixtures/main.json index 5c6d3358dd0222d5042ceed72f995d931aa87bcd..d3d0135d87dce64c475d9fa342aaadcd6d6dceb0 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/main.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/main.json @@ -1,3 +1,3 @@ { - "title": "Alfa" + "title": "Alfa" } diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/postfach/postfach-nachricht-reply-item.json b/alfa-client/apps/alfa-e2e/src/fixtures/postfach/postfach-nachricht-reply-item.json index 553ebb9c81a452a2db6e7c1cea4f5b0c37ac1e7e..f8bcaf65c6708251c4535a5c98dc8b08839aace9 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/postfach/postfach-nachricht-reply-item.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/postfach/postfach-nachricht-reply-item.json @@ -1,10 +1,10 @@ -{ - "postfachId": "04d39269-81c5-4838-8b73-08d9567f06d7", - "createdAt": "2020-12-31T01:01:43.790Z[UTC]", - "mailBody": "Lorem ipsum dolor sit amet.", - "createdBy": "", - "subject": "Subject", - "vorgangId": "602566a807bb665df9a86111", - "replyOption": "FORBIDDEN", - "direction": "IN" -} \ No newline at end of file +{ + "postfachId": "04d39269-81c5-4838-8b73-08d9567f06d7", + "createdAt": "2020-12-31T01:01:43.790Z[UTC]", + "mailBody": "Lorem ipsum dolor sit amet.", + "createdBy": "", + "subject": "Subject", + "vorgangId": "602566a807bb665df9a86111", + "replyOption": "FORBIDDEN", + "direction": "IN" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/representation/xml.json b/alfa-client/apps/alfa-e2e/src/fixtures/representation/xml.json index bfe98b92533fcdf8c074aabc19ba6033e34270f7..264adc7122f9d139ecc1047dad40061bdc069459 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/representation/xml.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/representation/xml.json @@ -1,13 +1,13 @@ { - "_id": "626e444157089b0cc5dceddc", - "vendorId": "myForm-xml", - "name": "XML-Daten.xml", - "contentType": "text/xml", - "size": 5520, - "content": { - "$binary": { - "base64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPG15Rm9ybSB4bWxuczpwZGY9Imh0dHA6Ly94bWxucy5jaXQuZGUvYXNzaXN0YW50cy9wZGYiIHhtbG5zOnQ9Imh0dHA6Ly94bWxucy5jaXQuZGUvaW50ZWxsaWZvcm0vdHJhbnNhY3Rpb24iIHQ6dXVpZD0iZWFjMjQ4MGUtNzE2Ni00YjE2LWJkZGQtODgwNTkxZTdkOTNiIiB0OmlkPSIyMDIxMDQxNTMwNzAyMDQxNDcwMSIgdDp0aW1lc3RhbXA9IjIwMjEtMDQtMTVUMDg6MzE6NDIuMzk4WiIgdDpzZW5kZXI9ImludGVsbGlmb3JtLm96Zy1zaC5kZSIgdDpmb3JtPSJTaW1wbGVGb3JtU2VuZGV0QW5Ib21lU2VydmVyVm9uVG9yc3RlbiIgdDpmb3JtLWlkPSJTaW1wbGVGb3JtU2VuZGV0QW5Ib21lU2VydmVyVm9uVG9yc3RlbiIgdDpjdXN0b21lcj0iS2llbCIgdDpjdXN0b21lci1pZD0iS2llbCIgdDpjbGllbnQ9InNoLWRldiIgdDpjbGllbnQtaWQ9InNoLWRldiI+PEtvbnRha3RzeXN0ZW1UeXBBPjIzMzAzNDYwMDwvS29udGFrdHN5c3RlbVR5cEE+PEtvbnRha3RzeXN0ZW1UeXBCPjIzMzAzNDYwMTwvS29udGFrdHN5c3RlbVR5cEI+PEFubGllZ2VuSUQ+ODk2NjY3MTwvQW5saWVnZW5JRD48YW50cmFnc3RlbGxlcj48c2hfc3RyYXNzZT5BbiBkZXIgU2NobmVpZGVyZWk8L3NoX3N0cmFzc2U+PHNoX2hhdXNudW1tZXI+MTwvc2hfaGF1c251bW1lcj48c2hfcGx6PjI0MTAzPC9zaF9wbHo+PG9ydF9hdXN3YWhsPjkwMDY0MDIkMDEwMDIwMDA8L29ydF9hdXN3YWhsPjxvcnQ+S2llbDwvb3J0PjxHZWJpZXRJRD45MDA2NDAyPC9HZWJpZXRJRD48R2ViaWV0QkVaRUlDSE5VTkc+S2llbDwvR2ViaWV0QkVaRUlDSE5VTkc+PEdlYmlldEdOUjk0X0dOUj4wMTAwMjAwMDwvR2ViaWV0R05SOTRfR05SPjxzdGFhdD4wMDA8L3N0YWF0Pjxpc28zMTY2bnVtZXJpc2NoPjI3NjwvaXNvMzE2Nm51bWVyaXNjaD48a29udF90ZWxlZm9ubnVtbWVyLz48a29udF9tb2JpbG51bW1lci8+PGtvbnRfdGVsZWZheG51bW1lci8+PGtvbnRfZW1haWwvPjxrb250X2RlbWFpbC8+PC9hbnRyYWdzdGVsbGVyPjxVcGxvYWQxPjxmaWxlIGNvbnRlbnQtdHlwZT0iaW1hZ2UvanBlZyIgZGVzY3JpcHRpb249IiIgaWQ9ImFzc2lzdGFudHMuRTBGQkEzNjFDMTkxRjhCNzIzOTQ5NDY3QUUzMDJCRUEyNEU0NzQ1RSIgbGVuZ3RoPSIxNTUyNTEiPkhlbGdlMS5qcGc8L2ZpbGU+PC9VcGxvYWQxPjxVcGxvYWQyPjxmaWxlIGNvbnRlbnQtdHlwZT0iYXBwbGljYXRpb24vdm5kLm9hc2lzLm9wZW5kb2N1bWVudC50ZXh0IiBkZXNjcmlwdGlvbj0iIiBpZD0iYXNzaXN0YW50cy41MkQ3OUU1QjIxMThEMTc0MDA0NUFCODcxNTE1MzVEQ0FEMjRFOUE3IiBsZW5ndGg9Ijc5OTMiPkhlbGdldGV4dDIub2R0PC9maWxlPjwvVXBsb2FkMj48R2ViaWV0SUQ+OTAwNjQwMjwvR2ViaWV0SUQ+PHp1c3RhZW5kaWdlc3RlbGxlPjxPcmdhbmlzYXRpb25zZWluaGVpdGVuQXVzd2FobD4xMDM2MzQ1NTwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5JRD4xMDM2MzQ1NTwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbklEPjxPcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+TGFuZGVzaGF1cHRzdGFkdCBLaWVsIC0gQsO8cmdlci0gdW5kIE9yZG51bmdzYW10LCBTYWNoYmVyZWljaCBHZWZhaHJlbmFid2VociwgV2FmZmVuYW5nZWxlZ2VuaGVpdGVuLCBKYWdkYmVow7ZyZGUsIEJlc3RhdHR1bmdzYW5nZWxlZ2VuaGVpdGVuPC9PcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+PHN0cmFzc2U+U3RyZXNlbWFubnBsYXR6PC9zdHJhc3NlPjxoYXVzbnVtbWVyPjU8L2hhdXNudW1tZXI+PHBvc3RsZWl0emFobD4yNDEwMzwvcG9zdGxlaXR6YWhsPjxvcnRJRD45MDA2NDAyPC9vcnRJRD48b3J0PktpZWw8L29ydD48dGVsZWZvbm51bW1lci8+PHRlbGVmYXhudW1tZXI+KzQ5IDQzMSA5MDEtNjIxODE8L3RlbGVmYXhudW1tZXI+PGVtYWlsYWRyZXNzZT5HZWZhaHJlbmFid2VockBLaWVsLmRlPC9lbWFpbGFkcmVzc2U+PGRlbWFpbGFkcmVzc2UvPjxrb250YWt0c3lzdGVtX2tlbm51bmcvPjxrb250YWt0c3lzdGVtX2tlbm51bmd6dXNhdHovPjxBbmxpZWdlbkJFWkVJQ0hOVU5HPldhZmZlbnNjaGVpbiAvIEtsZWluZXIgV2FmZmVuc2NoZWluPC9BbmxpZWdlbkJFWkVJQ0hOVU5HPjxsZWlrYUtFWUxJU1Q+OTkwODkwMDgwMDAwMDA7OTkwODkwMDgwMDEwMDA8L2xlaWthS0VZTElTVD48L3p1c3RhZW5kaWdlc3RlbGxlPjxlbXBmYW5nZW5kZXN0ZWxsZT48T3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+OTA2ODg3MzwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5JRD45MDY4ODczPC9PcmdhbmlzYXRpb25zZWluaGVpdGVuSUQ+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5CRVpFSUNITlVORz5FaW5oZWl0bGljaGVyIEFuc3ByZWNocGFydG5lciBTY2hsZXN3aWctSG9sc3RlaW48L09yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5CRVpFSUNITlVORz48c3RyYXNzZT5SZXZlbnRsb3VhbGxlZTwvc3RyYXNzZT48aGF1c251bW1lcj42PC9oYXVzbnVtbWVyPjxwb3N0bGVpdHphaGw+MjQxMDU8L3Bvc3RsZWl0emFobD48b3J0SUQ+OTAwNjQwMjwvb3J0SUQ+PG9ydD5LaWVsPC9vcnQ+PHRlbGVmb25udW1tZXI+KzQ5IDQzMSA5ODgtODY1MDwvdGVsZWZvbm51bW1lcj48dGVsZWZheG51bW1lcj4rNDkgNDMxIDk4OC02MTYxMTExPC90ZWxlZmF4bnVtbWVyPjxlbWFpbGFkcmVzc2U+aW5mb0BlYS1zaC5kZTwvZW1haWxhZHJlc3NlPjxkZW1haWxhZHJlc3NlPmVhLXBvc3RzdGVsbGVAZWEtc2guZGUtbWFpbC5kZTwvZGVtYWlsYWRyZXNzZT48a29udGFrdHN5c3RlbV9rZW5udW5nPmFmbXNoOjkwNjg4NzNfQXVzbmFobWVMS1dGYWhydmVyYm90PC9rb250YWt0c3lzdGVtX2tlbm51bmc+PGtvbnRha3RzeXN0ZW1fa2VubnVuZ3p1c2F0ej5hbGxlPC9rb250YWt0c3lzdGVtX2tlbm51bmd6dXNhdHo+PC9lbXBmYW5nZW5kZXN0ZWxsZT48ZXJrbGFlcnVuZ2VuPjxjaGVja19nZWJ1ZWhyZW4+dHJ1ZTwvY2hlY2tfZ2VidWVocmVuPjxjaGVja19yaWNodGlna2VpdD50cnVlPC9jaGVja19yaWNodGlna2VpdD48Y2hlY2tfZGF0ZW5zY2h1dHo+dHJ1ZTwvY2hlY2tfZGF0ZW5zY2h1dHo+PGNoZWNrX21pc3NicmF1Y2g+dHJ1ZTwvY2hlY2tfbWlzc2JyYXVjaD48Yl9nZWJ1ZWhyZW5fYmVzY2hyaWZ0dW5nPiogTWlyIGlzdCBiZWthbm50LCBkYXNzIGR1cmNoIGRhcyBFaW5yZWljaGVuIGRlcyBlbGVrdHJvbmlzY2hlbiBBbnRyYWdlcyB2b24gZGVyIHp1c3TDpG5kaWdlbiBTdGVsbGUgR2Viw7xocmVuIGVyaG9iZW4gd2VyZGVuIGvDtm5uZW4uPC9iX2dlYnVlaHJlbl9iZXNjaHJpZnR1bmc+PGJfZ2VidWVocmVuX2ludHJvPkdlYsO8aHIgYmVpIEF1c3N0ZWxsdW5nIGRlcyBrbGVpbmVuIFdhZmZlbnNjaGVpbnM6IDYwLDAwIEV1cm8uIEJlYXJiZWl0dW5nc2dlYsO8aHIgYmVpIFZlcnNhZ3VuZzogNDUsMDAgRXVyby4gClNpZSBzaW5kIGdlbcOkw58gwqcgMzkgV2FmZkcgdmVycGZsaWNodGV0LCBkZXIgenVzdMOkbmRpZ2VuIEJlaMO2cmRlIGRpZSB6dXIgRHVyY2hmw7xocnVuZyBkZXMgR2VzZXR6ZXMgZXJmb3JkZXJsaWNoZW4gQXVza8O8bmZ0ZSB6dSBlcnRlaWxlbi4gWnVyIFByw7xmdW5nIElocmVyIHdhZmZlbnJlY2h0bGljaGVuIFp1dmVybMOkc3NpZ2tlaXQgdW5kIEVpZ251bmcgaG9sdCBkaWUgQmVow7ZyZGUgZWluZSB1bmJlc2NocsOkbmt0ZSBBdXNrdW5mdCBhdXMgZGVtIEJ1bmRlc3plbnRyYWxyZWdpc3RlciwgZWluZSBBdXNrdW5mdCBhdXMgZGVtIHplbnRyYWxlbiBzdGFhdHNhbndhbHRzY2hhZnRsaWNoZW4gVmVyZmFocmVuc3JlZ2lzdGVyLCBlaW5lIFN0ZWxsdW5nbmFobWUgZGVyIMO2cnRsaWNoZW4gUG9saXplaWRpZW5zdHN0ZWxsZSB1bmQgSWhyZXIgV29obnNpdHpnZW1laW5kZSBlaW4uPC9iX2dlYnVlaHJlbl9pbnRybz48Yl9yaWNodGlna2VpdD4qIEljaCBiZXN0w6R0aWdlIGRpZSBSaWNodGlna2VpdCBtZWluZXIgQW5nYWJlbi48L2JfcmljaHRpZ2tlaXQ+PGJfZGF0ZW5zY2h1dHo+KiBJY2ggZXJrbMOkcmUgbWljaCBkYW1pdCBlaW52ZXJzdGFuZGVuLCBkYXNzIGRlciBFaW5oZWl0bGljaGVyIEFuc3ByZWNocGFydG5lciBTY2hsZXN3aWctSG9sc3RlaW4genVyIEVyZsO8bGx1bmcgc2VpbmVyIEF1ZmdhYmVuIG1laW5lIERhdGVuIHVudGVyIEVpbmhhbHR1bmcgZGVyIEJlc3RpbW11bmdlbiBkZXIgRGF0ZW5zY2h1dHotR3J1bmR2ZXJvcmRudW5nIChEUy1HVk8pIHVuZCBkZXMgTGFuZGVzZGF0ZW5zY2h1dHpnZXNldHplcyBTY2hsZXN3aWctSG9sc3RlaW4gKExEU0ctU0gpIHNwZWljaGVydCwgdmVyYXJiZWl0ZXQgIHVuZCBkaWVzZSBpbSBSYWhtZW4gZGVyIGdlc2V0emxpY2hlbiBCZXN0aW1tdW5nZW4gYW4gZGllIGbDvHIgZGllIEVudHNjaGVpZHVuZyB6dXN0w6RuZGlnZSBTdGVsbGUgd2VpdGVybGVpdGV0LiBFYmVuc28gYmluIGljaCBtaXQgZGVyIHJlY2h0c2tvbmZvcm1lbiAgRGF0ZW52ZXJhcmJlaXR1bmcgdW5kIFNwZWljaGVydW5nIGR1cmNoIGRpZSB6dXN0w6RuZGlnZSBTdGVsbGUgZWludmVyc3RhbmRlbi4gTWlyIGlzdCBiZWthbm50LCBkYXNzIGljaCBkaWUgRWlud2lsbGlndW5nIGluIGRpZSBWZXJhcmJlaXR1bmcgdW5kIMOcYmVybWl0dGx1bmcgamVkZXJ6ZWl0IGdlZ2Vuw7xiZXIgZGVtIEVpbmhlaXRsaWNoZXIgQW5zcHJlY2hwYXJ0bmVyIFNjaGxlc3dpZy1Ib2xzdGVpbiwgUmV2ZW50bG91YWxsZWUgNiwgMjQxMDUgS2llbCB3aWRlcnJ1ZmVuIGthbm4uIEVpbiBXaWRlcnJ1ZiBpc3QgYWJlciBudXIgd2lya3NhbSBmw7xyIGRpZSBadWt1bmZ0LiBWZXJhcmJlaXR1bmdlbiwgZGllIHZvciBkZW0gV2lkZXJydWYgZXJmb2xndCBzaW5kLCBzaW5kIGRhdm9uIG5pY2h0IGJldHJvZmZlbi4gw5xiZXIgZGllIFZlcmFyYmVpdHVuZyBtZWluZXIgcGVyc29uZW5iZXpvZ2VuZW4gRGF0ZW4gdW5kIGRpZSBtaXIgbmFjaCBkZW4gZGF0ZW5zY2h1dHpyZWNodGxpY2hlbiBSZWdlbHVuZ2VuIHp1c3RlaGVuZGVuIEFuc3Byw7xjaGUgdW5kIFJlY2h0ZSBoYWJlIGljaCB1bnRlciBEYXRlbnNjaHV0emVya2zDpHJ1bmcgS2VubnRuaXMgZXJsYW5ndC48L2JfZGF0ZW5zY2h1dHo+PGJfbWlzc2JyYXVjaD4qIE1pciBpc3QgYmVrYW5udCwgZGFzcyB6dXIgVmVyZm9sZ3VuZyB3aWRlcnJlY2h0bGljaGVyIE51dHp1bmcgZGllIERhdGVuIG1laW5lcyB6dXIgRGF0ZW5laW5nYWJlIGdlbnV0enRlbiBFbmRnZXLDpHRlcyBhdWZnZXplaWNobmV0IHVuZCB2ZXJ3ZW5kZXQgd2VyZGVuIGvDtm5uZW4uPC9iX21pc3NicmF1Y2g+PHBvbGljeXVybD5odHRwOi8vd3d3LmVhLXNoLmluZm8vZGF0ZW5zY2h1dHovZGF0ZW5zY2h1dHplcmtsYWVydW5nRUFfZGUuZG9jPC9wb2xpY3l1cmw+PC9lcmtsYWVydW5nZW4+PGxvZ291cmw+aHR0cDovL3d3dy5lYS1zaC5pbmZvL2xvZ29zL2tvcGZfOTA2ODg3My5kb2M8L2xvZ291cmw+PC9teUZvcm0+", - "subType": "00" - } - } -} \ No newline at end of file + "_id": "626e444157089b0cc5dceddc", + "vendorId": "myForm-xml", + "name": "XML-Daten.xml", + "contentType": "text/xml", + "size": 5520, + "content": { + "$binary": { + "base64": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPG15Rm9ybSB4bWxuczpwZGY9Imh0dHA6Ly94bWxucy5jaXQuZGUvYXNzaXN0YW50cy9wZGYiIHhtbG5zOnQ9Imh0dHA6Ly94bWxucy5jaXQuZGUvaW50ZWxsaWZvcm0vdHJhbnNhY3Rpb24iIHQ6dXVpZD0iZWFjMjQ4MGUtNzE2Ni00YjE2LWJkZGQtODgwNTkxZTdkOTNiIiB0OmlkPSIyMDIxMDQxNTMwNzAyMDQxNDcwMSIgdDp0aW1lc3RhbXA9IjIwMjEtMDQtMTVUMDg6MzE6NDIuMzk4WiIgdDpzZW5kZXI9ImludGVsbGlmb3JtLm96Zy1zaC5kZSIgdDpmb3JtPSJTaW1wbGVGb3JtU2VuZGV0QW5Ib21lU2VydmVyVm9uVG9yc3RlbiIgdDpmb3JtLWlkPSJTaW1wbGVGb3JtU2VuZGV0QW5Ib21lU2VydmVyVm9uVG9yc3RlbiIgdDpjdXN0b21lcj0iS2llbCIgdDpjdXN0b21lci1pZD0iS2llbCIgdDpjbGllbnQ9InNoLWRldiIgdDpjbGllbnQtaWQ9InNoLWRldiI+PEtvbnRha3RzeXN0ZW1UeXBBPjIzMzAzNDYwMDwvS29udGFrdHN5c3RlbVR5cEE+PEtvbnRha3RzeXN0ZW1UeXBCPjIzMzAzNDYwMTwvS29udGFrdHN5c3RlbVR5cEI+PEFubGllZ2VuSUQ+ODk2NjY3MTwvQW5saWVnZW5JRD48YW50cmFnc3RlbGxlcj48c2hfc3RyYXNzZT5BbiBkZXIgU2NobmVpZGVyZWk8L3NoX3N0cmFzc2U+PHNoX2hhdXNudW1tZXI+MTwvc2hfaGF1c251bW1lcj48c2hfcGx6PjI0MTAzPC9zaF9wbHo+PG9ydF9hdXN3YWhsPjkwMDY0MDIkMDEwMDIwMDA8L29ydF9hdXN3YWhsPjxvcnQ+S2llbDwvb3J0PjxHZWJpZXRJRD45MDA2NDAyPC9HZWJpZXRJRD48R2ViaWV0QkVaRUlDSE5VTkc+S2llbDwvR2ViaWV0QkVaRUlDSE5VTkc+PEdlYmlldEdOUjk0X0dOUj4wMTAwMjAwMDwvR2ViaWV0R05SOTRfR05SPjxzdGFhdD4wMDA8L3N0YWF0Pjxpc28zMTY2bnVtZXJpc2NoPjI3NjwvaXNvMzE2Nm51bWVyaXNjaD48a29udF90ZWxlZm9ubnVtbWVyLz48a29udF9tb2JpbG51bW1lci8+PGtvbnRfdGVsZWZheG51bW1lci8+PGtvbnRfZW1haWwvPjxrb250X2RlbWFpbC8+PC9hbnRyYWdzdGVsbGVyPjxVcGxvYWQxPjxmaWxlIGNvbnRlbnQtdHlwZT0iaW1hZ2UvanBlZyIgZGVzY3JpcHRpb249IiIgaWQ9ImFzc2lzdGFudHMuRTBGQkEzNjFDMTkxRjhCNzIzOTQ5NDY3QUUzMDJCRUEyNEU0NzQ1RSIgbGVuZ3RoPSIxNTUyNTEiPkhlbGdlMS5qcGc8L2ZpbGU+PC9VcGxvYWQxPjxVcGxvYWQyPjxmaWxlIGNvbnRlbnQtdHlwZT0iYXBwbGljYXRpb24vdm5kLm9hc2lzLm9wZW5kb2N1bWVudC50ZXh0IiBkZXNjcmlwdGlvbj0iIiBpZD0iYXNzaXN0YW50cy41MkQ3OUU1QjIxMThEMTc0MDA0NUFCODcxNTE1MzVEQ0FEMjRFOUE3IiBsZW5ndGg9Ijc5OTMiPkhlbGdldGV4dDIub2R0PC9maWxlPjwvVXBsb2FkMj48R2ViaWV0SUQ+OTAwNjQwMjwvR2ViaWV0SUQ+PHp1c3RhZW5kaWdlc3RlbGxlPjxPcmdhbmlzYXRpb25zZWluaGVpdGVuQXVzd2FobD4xMDM2MzQ1NTwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5JRD4xMDM2MzQ1NTwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbklEPjxPcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+TGFuZGVzaGF1cHRzdGFkdCBLaWVsIC0gQsO8cmdlci0gdW5kIE9yZG51bmdzYW10LCBTYWNoYmVyZWljaCBHZWZhaHJlbmFid2VociwgV2FmZmVuYW5nZWxlZ2VuaGVpdGVuLCBKYWdkYmVow7ZyZGUsIEJlc3RhdHR1bmdzYW5nZWxlZ2VuaGVpdGVuPC9PcmdhbmlzYXRpb25zZWluaGVpdGVuQkVaRUlDSE5VTkc+PHN0cmFzc2U+U3RyZXNlbWFubnBsYXR6PC9zdHJhc3NlPjxoYXVzbnVtbWVyPjU8L2hhdXNudW1tZXI+PHBvc3RsZWl0emFobD4yNDEwMzwvcG9zdGxlaXR6YWhsPjxvcnRJRD45MDA2NDAyPC9vcnRJRD48b3J0PktpZWw8L29ydD48dGVsZWZvbm51bW1lci8+PHRlbGVmYXhudW1tZXI+KzQ5IDQzMSA5MDEtNjIxODE8L3RlbGVmYXhudW1tZXI+PGVtYWlsYWRyZXNzZT5HZWZhaHJlbmFid2VockBLaWVsLmRlPC9lbWFpbGFkcmVzc2U+PGRlbWFpbGFkcmVzc2UvPjxrb250YWt0c3lzdGVtX2tlbm51bmcvPjxrb250YWt0c3lzdGVtX2tlbm51bmd6dXNhdHovPjxBbmxpZWdlbkJFWkVJQ0hOVU5HPldhZmZlbnNjaGVpbiAvIEtsZWluZXIgV2FmZmVuc2NoZWluPC9BbmxpZWdlbkJFWkVJQ0hOVU5HPjxsZWlrYUtFWUxJU1Q+OTkwODkwMDgwMDAwMDA7OTkwODkwMDgwMDEwMDA8L2xlaWthS0VZTElTVD48L3p1c3RhZW5kaWdlc3RlbGxlPjxlbXBmYW5nZW5kZXN0ZWxsZT48T3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+OTA2ODg3MzwvT3JnYW5pc2F0aW9uc2VpbmhlaXRlbkF1c3dhaGw+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5JRD45MDY4ODczPC9PcmdhbmlzYXRpb25zZWluaGVpdGVuSUQ+PE9yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5CRVpFSUNITlVORz5FaW5oZWl0bGljaGVyIEFuc3ByZWNocGFydG5lciBTY2hsZXN3aWctSG9sc3RlaW48L09yZ2FuaXNhdGlvbnNlaW5oZWl0ZW5CRVpFSUNITlVORz48c3RyYXNzZT5SZXZlbnRsb3VhbGxlZTwvc3RyYXNzZT48aGF1c251bW1lcj42PC9oYXVzbnVtbWVyPjxwb3N0bGVpdHphaGw+MjQxMDU8L3Bvc3RsZWl0emFobD48b3J0SUQ+OTAwNjQwMjwvb3J0SUQ+PG9ydD5LaWVsPC9vcnQ+PHRlbGVmb25udW1tZXI+KzQ5IDQzMSA5ODgtODY1MDwvdGVsZWZvbm51bW1lcj48dGVsZWZheG51bW1lcj4rNDkgNDMxIDk4OC02MTYxMTExPC90ZWxlZmF4bnVtbWVyPjxlbWFpbGFkcmVzc2U+aW5mb0BlYS1zaC5kZTwvZW1haWxhZHJlc3NlPjxkZW1haWxhZHJlc3NlPmVhLXBvc3RzdGVsbGVAZWEtc2guZGUtbWFpbC5kZTwvZGVtYWlsYWRyZXNzZT48a29udGFrdHN5c3RlbV9rZW5udW5nPmFmbXNoOjkwNjg4NzNfQXVzbmFobWVMS1dGYWhydmVyYm90PC9rb250YWt0c3lzdGVtX2tlbm51bmc+PGtvbnRha3RzeXN0ZW1fa2VubnVuZ3p1c2F0ej5hbGxlPC9rb250YWt0c3lzdGVtX2tlbm51bmd6dXNhdHo+PC9lbXBmYW5nZW5kZXN0ZWxsZT48ZXJrbGFlcnVuZ2VuPjxjaGVja19nZWJ1ZWhyZW4+dHJ1ZTwvY2hlY2tfZ2VidWVocmVuPjxjaGVja19yaWNodGlna2VpdD50cnVlPC9jaGVja19yaWNodGlna2VpdD48Y2hlY2tfZGF0ZW5zY2h1dHo+dHJ1ZTwvY2hlY2tfZGF0ZW5zY2h1dHo+PGNoZWNrX21pc3NicmF1Y2g+dHJ1ZTwvY2hlY2tfbWlzc2JyYXVjaD48Yl9nZWJ1ZWhyZW5fYmVzY2hyaWZ0dW5nPiogTWlyIGlzdCBiZWthbm50LCBkYXNzIGR1cmNoIGRhcyBFaW5yZWljaGVuIGRlcyBlbGVrdHJvbmlzY2hlbiBBbnRyYWdlcyB2b24gZGVyIHp1c3TDpG5kaWdlbiBTdGVsbGUgR2Viw7xocmVuIGVyaG9iZW4gd2VyZGVuIGvDtm5uZW4uPC9iX2dlYnVlaHJlbl9iZXNjaHJpZnR1bmc+PGJfZ2VidWVocmVuX2ludHJvPkdlYsO8aHIgYmVpIEF1c3N0ZWxsdW5nIGRlcyBrbGVpbmVuIFdhZmZlbnNjaGVpbnM6IDYwLDAwIEV1cm8uIEJlYXJiZWl0dW5nc2dlYsO8aHIgYmVpIFZlcnNhZ3VuZzogNDUsMDAgRXVyby4gClNpZSBzaW5kIGdlbcOkw58gwqcgMzkgV2FmZkcgdmVycGZsaWNodGV0LCBkZXIgenVzdMOkbmRpZ2VuIEJlaMO2cmRlIGRpZSB6dXIgRHVyY2hmw7xocnVuZyBkZXMgR2VzZXR6ZXMgZXJmb3JkZXJsaWNoZW4gQXVza8O8bmZ0ZSB6dSBlcnRlaWxlbi4gWnVyIFByw7xmdW5nIElocmVyIHdhZmZlbnJlY2h0bGljaGVuIFp1dmVybMOkc3NpZ2tlaXQgdW5kIEVpZ251bmcgaG9sdCBkaWUgQmVow7ZyZGUgZWluZSB1bmJlc2NocsOkbmt0ZSBBdXNrdW5mdCBhdXMgZGVtIEJ1bmRlc3plbnRyYWxyZWdpc3RlciwgZWluZSBBdXNrdW5mdCBhdXMgZGVtIHplbnRyYWxlbiBzdGFhdHNhbndhbHRzY2hhZnRsaWNoZW4gVmVyZmFocmVuc3JlZ2lzdGVyLCBlaW5lIFN0ZWxsdW5nbmFobWUgZGVyIMO2cnRsaWNoZW4gUG9saXplaWRpZW5zdHN0ZWxsZSB1bmQgSWhyZXIgV29obnNpdHpnZW1laW5kZSBlaW4uPC9iX2dlYnVlaHJlbl9pbnRybz48Yl9yaWNodGlna2VpdD4qIEljaCBiZXN0w6R0aWdlIGRpZSBSaWNodGlna2VpdCBtZWluZXIgQW5nYWJlbi48L2JfcmljaHRpZ2tlaXQ+PGJfZGF0ZW5zY2h1dHo+KiBJY2ggZXJrbMOkcmUgbWljaCBkYW1pdCBlaW52ZXJzdGFuZGVuLCBkYXNzIGRlciBFaW5oZWl0bGljaGVyIEFuc3ByZWNocGFydG5lciBTY2hsZXN3aWctSG9sc3RlaW4genVyIEVyZsO8bGx1bmcgc2VpbmVyIEF1ZmdhYmVuIG1laW5lIERhdGVuIHVudGVyIEVpbmhhbHR1bmcgZGVyIEJlc3RpbW11bmdlbiBkZXIgRGF0ZW5zY2h1dHotR3J1bmR2ZXJvcmRudW5nIChEUy1HVk8pIHVuZCBkZXMgTGFuZGVzZGF0ZW5zY2h1dHpnZXNldHplcyBTY2hsZXN3aWctSG9sc3RlaW4gKExEU0ctU0gpIHNwZWljaGVydCwgdmVyYXJiZWl0ZXQgIHVuZCBkaWVzZSBpbSBSYWhtZW4gZGVyIGdlc2V0emxpY2hlbiBCZXN0aW1tdW5nZW4gYW4gZGllIGbDvHIgZGllIEVudHNjaGVpZHVuZyB6dXN0w6RuZGlnZSBTdGVsbGUgd2VpdGVybGVpdGV0LiBFYmVuc28gYmluIGljaCBtaXQgZGVyIHJlY2h0c2tvbmZvcm1lbiAgRGF0ZW52ZXJhcmJlaXR1bmcgdW5kIFNwZWljaGVydW5nIGR1cmNoIGRpZSB6dXN0w6RuZGlnZSBTdGVsbGUgZWludmVyc3RhbmRlbi4gTWlyIGlzdCBiZWthbm50LCBkYXNzIGljaCBkaWUgRWlud2lsbGlndW5nIGluIGRpZSBWZXJhcmJlaXR1bmcgdW5kIMOcYmVybWl0dGx1bmcgamVkZXJ6ZWl0IGdlZ2Vuw7xiZXIgZGVtIEVpbmhlaXRsaWNoZXIgQW5zcHJlY2hwYXJ0bmVyIFNjaGxlc3dpZy1Ib2xzdGVpbiwgUmV2ZW50bG91YWxsZWUgNiwgMjQxMDUgS2llbCB3aWRlcnJ1ZmVuIGthbm4uIEVpbiBXaWRlcnJ1ZiBpc3QgYWJlciBudXIgd2lya3NhbSBmw7xyIGRpZSBadWt1bmZ0LiBWZXJhcmJlaXR1bmdlbiwgZGllIHZvciBkZW0gV2lkZXJydWYgZXJmb2xndCBzaW5kLCBzaW5kIGRhdm9uIG5pY2h0IGJldHJvZmZlbi4gw5xiZXIgZGllIFZlcmFyYmVpdHVuZyBtZWluZXIgcGVyc29uZW5iZXpvZ2VuZW4gRGF0ZW4gdW5kIGRpZSBtaXIgbmFjaCBkZW4gZGF0ZW5zY2h1dHpyZWNodGxpY2hlbiBSZWdlbHVuZ2VuIHp1c3RlaGVuZGVuIEFuc3Byw7xjaGUgdW5kIFJlY2h0ZSBoYWJlIGljaCB1bnRlciBEYXRlbnNjaHV0emVya2zDpHJ1bmcgS2VubnRuaXMgZXJsYW5ndC48L2JfZGF0ZW5zY2h1dHo+PGJfbWlzc2JyYXVjaD4qIE1pciBpc3QgYmVrYW5udCwgZGFzcyB6dXIgVmVyZm9sZ3VuZyB3aWRlcnJlY2h0bGljaGVyIE51dHp1bmcgZGllIERhdGVuIG1laW5lcyB6dXIgRGF0ZW5laW5nYWJlIGdlbnV0enRlbiBFbmRnZXLDpHRlcyBhdWZnZXplaWNobmV0IHVuZCB2ZXJ3ZW5kZXQgd2VyZGVuIGvDtm5uZW4uPC9iX21pc3NicmF1Y2g+PHBvbGljeXVybD5odHRwOi8vd3d3LmVhLXNoLmluZm8vZGF0ZW5zY2h1dHovZGF0ZW5zY2h1dHplcmtsYWVydW5nRUFfZGUuZG9jPC9wb2xpY3l1cmw+PC9lcmtsYWVydW5nZW4+PGxvZ291cmw+aHR0cDovL3d3dy5lYS1zaC5pbmZvL2xvZ29zL2tvcGZfOTA2ODg3My5kb2M8L2xvZ291cmw+PC9teUZvcm0+", + "subType": "00" + } + } +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/smocker/mocks.yaml b/alfa-client/apps/alfa-e2e/src/fixtures/smocker/mocks.yaml index bd8e62d867118f01c68f2b65912ec6b7aeb8aba1..e270021ffef0c25bc4f6632f8a48b3728c470289 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/smocker/mocks.yaml +++ b/alfa-client/apps/alfa-e2e/src/fixtures/smocker/mocks.yaml @@ -20,4 +20,4 @@ response: status: 500 headers: - body: "Da ist etwas schiefgelaufen" \ No newline at end of file + body: 'Da ist etwas schiefgelaufen' diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/user-ea/user_emil.json b/alfa-client/apps/alfa-e2e/src/fixtures/user-ea/user_emil.json index 25431ebcc660b758080f578d88f29853e853fe00..35ddfcb5ea3ea84433614ad41f9d66445685e08f 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/user-ea/user_emil.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/user-ea/user_emil.json @@ -1,11 +1,11 @@ { - "id": "63284e54c39b316b2ad02e2a", - "name": "emil", - "password": "Y9nk43yrQ_zzIPpfFU-I", - "firstName": "Emil", - "lastName": "Ansprechpartner", - "fullName": "Emil Ansprechpartner", - "initials": "EA", - "dataTestId": "Emil_Ansprechpartner", - "clientRoles": ["EINHEITLICHER_ANSPRECHPARTNER"] -} \ No newline at end of file + "id": "63284e54c39b316b2ad02e2a", + "name": "emil", + "password": "Y9nk43yrQ_zzIPpfFU-I", + "firstName": "Emil", + "lastName": "Ansprechpartner", + "fullName": "Emil Ansprechpartner", + "initials": "EA", + "dataTestId": "Emil_Ansprechpartner", + "clientRoles": ["EINHEITLICHER_ANSPRECHPARTNER"] +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_dorothea.json b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_dorothea.json index 11aacfe7fa16de46359039d010d0d820cdc71c50..863f262b30c314076e82d96f6f1dd066352846a4 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_dorothea.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_dorothea.json @@ -1,12 +1,12 @@ { - "name": "dorothea", - "password": "Y9nk43yrQ_zzIPpfFU-I", - "firstName": "Dorothea", - "lastName": "Doe", - "fullName": "Dorothea Doe", - "email": "dorothea.doe@ozg-sh.de", - "initials": "DD", - "dataTestId": "Dorothea_Doe", - "clientRoles": ["VERWALTUNG_USER"], - "groups": ["E2E Tests"] + "name": "dorothea", + "password": "Y9nk43yrQ_zzIPpfFU-I", + "firstName": "Dorothea", + "lastName": "Doe", + "fullName": "Dorothea Doe", + "email": "dorothea.doe@ozg-sh.de", + "initials": "DD", + "dataTestId": "Dorothea_Doe", + "clientRoles": ["VERWALTUNG_USER"], + "groups": ["E2E Tests"] } diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_kfinder.json b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_kfinder.json index 3a7a5dcf387c718ca6e9f91ca3b0e834b8f06212..42d9541b25519fa3631f43fa87e5fd9c6db7a649 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_kfinder.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_kfinder.json @@ -1,6 +1,6 @@ { - "name": "kfinder", - "password": "Katrinfinder", - "groups": ["Abtl. 10.0.1 Versammlungsbehörde, Identitätsfeststellung, Fundbüro"], - "clientRoles": ["VERWALTUNG_USER"] -} \ No newline at end of file + "name": "kfinder", + "password": "Katrinfinder", + "groups": ["Abtl. 10.0.1 Versammlungsbehörde, Identitätsfeststellung, Fundbüro"], + "clientRoles": ["VERWALTUNG_USER"] +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_kordner.json b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_kordner.json index 79b8c6c09a07eaf851ae30f92489b3afd057f71b..1d4712f41667998235664cb0e81c034f20613721 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_kordner.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_kordner.json @@ -1,6 +1,6 @@ { - "name": "kordner", - "password": "Klausordner", - "groups": ["Abtl. 10.5.1.2 Allgemeine Gefahrenabwehr und sonstige Ordnungsrechtsangelegenheiten"], - "clientRoles": ["VERWALTUNG_USER"] -} \ No newline at end of file + "name": "kordner", + "password": "Klausordner", + "groups": ["Abtl. 10.5.1.2 Allgemeine Gefahrenabwehr und sonstige Ordnungsrechtsangelegenheiten"], + "clientRoles": ["VERWALTUNG_USER"] +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_ludwig.json b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_ludwig.json index 61f3444a7a900700464ef5a408deb5e613cfd06e..f51be25948df8bbd07d4e80554e51e3c70dff995 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_ludwig.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_ludwig.json @@ -1,12 +1,12 @@ { - "name": "ludwig", - "password": "Y9nk43yrQ_zzIPpfFU-I", - "firstName": "Ludwig", - "lastName": "Löscher", - "fullName": "Ludwig Löscher", - "email": "ludwig.loescher@ozg-sh.de", - "initials": "LL", - "dataTestId": "Ludwig_Loescher", - "clientRoles": ["VERWALTUNG_LOESCHEN"], - "groups": ["E2E Tests"] -} \ No newline at end of file + "name": "ludwig", + "password": "Y9nk43yrQ_zzIPpfFU-I", + "firstName": "Ludwig", + "lastName": "Löscher", + "fullName": "Ludwig Löscher", + "email": "ludwig.loescher@ozg-sh.de", + "initials": "LL", + "dataTestId": "Ludwig_Loescher", + "clientRoles": ["VERWALTUNG_LOESCHEN"], + "groups": ["E2E Tests"] +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_peter.json b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_peter.json index 0a4cb9f36db9525c34c0051fbd8c6e1b8923b46b..c5f1a2c5331d4aa8cde74997d33ea728b492fd11 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_peter.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_peter.json @@ -1,8 +1,8 @@ { - "id": "63284e55c39b316b2ad02e2c", - "name": "peter", - "password": "Y9nk43yrQ_zzIPpfFU-I", - "firstName": "Peter", - "lastName": "von der Post", - "clientRoles": ["VERWALTUNG_POSTSTELLE"] -} \ No newline at end of file + "id": "63284e55c39b316b2ad02e2c", + "name": "peter", + "password": "Y9nk43yrQ_zzIPpfFU-I", + "firstName": "Peter", + "lastName": "von der Post", + "clientRoles": ["VERWALTUNG_POSTSTELLE"] +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_richard.json b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_richard.json index c1fa331c717ea67ff70dbeb7c599b91526189c7e..7172c59a8109c486106b2718a75df696159e997c 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_richard.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_richard.json @@ -1,6 +1,6 @@ { - "name": "richard", - "firstName": "Richard", - "lastName": "Rollenlos", - "password": "Y9nk43yrQ_zzIPpfFU-I" -} \ No newline at end of file + "name": "richard", + "firstName": "Richard", + "lastName": "Rollenlos", + "password": "Y9nk43yrQ_zzIPpfFU-I" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_sabine.json b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_sabine.json index c608f053532e41204138be4cb64007efe5417a9e..dd4c850aebe502b12bc3a25001e4c94d454d1537 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_sabine.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_sabine.json @@ -1,12 +1,12 @@ { - "name": "sabine", - "password": "Y9nk43yrQ_zzIPpfFU-I", - "firstName": "Sabine", - "lastName": "Sach", - "fullName": "Sabine Sach", - "email": "sabine.sach@ozg-sh.de", - "initials": "SS", - "dataTestId": "Sabine_Sach", - "clientRoles": ["VERWALTUNG_USER"], - "groups": ["E2E Tests"] + "name": "sabine", + "password": "Y9nk43yrQ_zzIPpfFU-I", + "firstName": "Sabine", + "lastName": "Sach", + "fullName": "Sabine Sach", + "email": "sabine.sach@ozg-sh.de", + "initials": "SS", + "dataTestId": "Sabine_Sach", + "clientRoles": ["VERWALTUNG_USER"], + "groups": ["E2E Tests"] } diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_zonk.json b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_zonk.json index 6b866ba46ddee69a3588ce6ef94bcf0492075a9b..e7181c55cb70df6bca11a86a5006a3aaf1245a6b 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_zonk.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/user-main/user_zonk.json @@ -1,8 +1,8 @@ { - "id": "63284e56c39b316b2ad02e30", - "name": "zonk", - "firstName": "Zacharias", - "lastName": "Zonk", - "password": "Y9nk43yrQ_zzIPpfFU-I", - "clientRoles": ["VERWALTUNG_USER"] -} \ No newline at end of file + "id": "63284e56c39b316b2ad02e30", + "name": "zonk", + "firstName": "Zacharias", + "lastName": "Zonk", + "password": "Y9nk43yrQ_zzIPpfFU-I", + "clientRoles": ["VERWALTUNG_USER"] +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_dorothea.json b/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_dorothea.json index 95d65b192d7e021e286a0d09198c1d5833f26d9d..8096db6473876aa483a407005abba0e60671ecef 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_dorothea.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_dorothea.json @@ -1,17 +1,17 @@ { - "_id": { - "$oid": "645e6fa20cfafc0fbbe6bf73" - }, - "createdAt": { - "$date": "2021-12-20T11:17:56.489Z" - }, - "deleted": false, - "keycloakUserId": "b5f84a21-cf2f-4d68-8717-f6f188d07201", - "firstName": "Dorothea", - "fullName": "Dorothea Doe", - "lastName": "Doe", - "lastSyncTimestamp": 1663585874687, - "organisationsEinheitIds": ["12345678"], - "roles": ["VERWALTUNG_USER"], - "username": "dorothea" + "_id": { + "$oid": "645e6fa20cfafc0fbbe6bf73" + }, + "createdAt": { + "$date": "2021-12-20T11:17:56.489Z" + }, + "deleted": false, + "keycloakUserId": "b5f84a21-cf2f-4d68-8717-f6f188d07201", + "firstName": "Dorothea", + "fullName": "Dorothea Doe", + "lastName": "Doe", + "lastSyncTimestamp": 1663585874687, + "organisationsEinheitIds": ["12345678"], + "roles": ["VERWALTUNG_USER"], + "username": "dorothea" } diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_emil.json b/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_emil.json index 069045234bdabbeb80080e2301beab46958c10e1..91348d19bf59d86fdeb3b6294e2f0c42f4fb6a91 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_emil.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_emil.json @@ -1,19 +1,17 @@ { - "_id": { - "$oid": "63284e54c39b316b2ad02e2a" - }, - "createdAt": { - "$date": "2022-08-25T08:29:45.025Z" - }, - "deleted": false, - "keycloakUserId": "108ee867-7290-466d-813f-ab1dc95d3691", - "firstName": "Emil", - "fullName": "Emil Ansprechpartner", - "lastName": "Ansprechpartner", - "lastSyncTimestamp": 1663585874687, - "organisationsEinheitIds": [], - "roles": [ - "EINHEITLICHER_ANSPRECHPARTNER" - ], - "username": "emil" - } \ No newline at end of file + "_id": { + "$oid": "63284e54c39b316b2ad02e2a" + }, + "createdAt": { + "$date": "2022-08-25T08:29:45.025Z" + }, + "deleted": false, + "keycloakUserId": "108ee867-7290-466d-813f-ab1dc95d3691", + "firstName": "Emil", + "fullName": "Emil Ansprechpartner", + "lastName": "Ansprechpartner", + "lastSyncTimestamp": 1663585874687, + "organisationsEinheitIds": [], + "roles": ["EINHEITLICHER_ANSPRECHPARTNER"], + "username": "emil" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_peter.json b/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_peter.json index 540acf41530c21b619ffa8e2761a3c8b31ecad3a..ed0a8166933ed3e17130361c44c508817a916584 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_peter.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_peter.json @@ -1,19 +1,17 @@ { - "_id": { - "$oid": "63284e55c39b316b2ad02e2c" - }, - "createdAt": { - "$date": "2022-02-18T09:21:24.340Z" - }, - "deleted": false, - "keycloakUserId": "63d42f8f-303b-4560-9b11-e9211b0ae87e", - "firstName": "Peter", - "fullName": "Peter von der Post", - "lastName": "von der Post", - "lastSyncTimestamp": 1663585874687, - "organisationsEinheitIds": [], - "roles": [ - "VERWALTUNG_POSTSTELLE" - ], - "username": "peter" - } \ No newline at end of file + "_id": { + "$oid": "63284e55c39b316b2ad02e2c" + }, + "createdAt": { + "$date": "2022-02-18T09:21:24.340Z" + }, + "deleted": false, + "keycloakUserId": "63d42f8f-303b-4560-9b11-e9211b0ae87e", + "firstName": "Peter", + "fullName": "Peter von der Post", + "lastName": "von der Post", + "lastSyncTimestamp": 1663585874687, + "organisationsEinheitIds": [], + "roles": ["VERWALTUNG_POSTSTELLE"], + "username": "peter" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_sabine.json b/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_sabine.json index 05cacad8008bf0ddd6e7daccbe4ee94008912baf..6b441c951d331e975c8d85bbadd76b2beeb8fc98 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_sabine.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/usermanager/usermanager_user_sabine.json @@ -1,22 +1,18 @@ { - "_id": { - "$oid": "63284e55c39b316b2ad02e2d" - }, - "createdAt": { - "$date": "2021-12-20T11:17:56.489Z" - }, - "deleted": false, - "email": "susanne.fischer.dataport+sabine@gmail.com", - "keycloakUserId": "2ccf0c13-da74-4516-ae3d-f46d30e8ec0c", - "firstName": "Sabine", - "fullName": "Sabine Sach", - "lastName": "Sach", - "lastSyncTimestamp": 1663585874687, - "organisationsEinheitIds": [ - "12345678" - ], - "roles": [ - "VERWALTUNG_USER" - ], - "username": "sabine" - } \ No newline at end of file + "_id": { + "$oid": "63284e55c39b316b2ad02e2d" + }, + "createdAt": { + "$date": "2021-12-20T11:17:56.489Z" + }, + "deleted": false, + "email": "susanne.fischer.dataport+sabine@gmail.com", + "keycloakUserId": "2ccf0c13-da74-4516-ae3d-f46d30e8ec0c", + "firstName": "Sabine", + "fullName": "Sabine Sach", + "lastName": "Sach", + "lastSyncTimestamp": 1663585874687, + "organisationsEinheitIds": ["12345678"], + "roles": ["VERWALTUNG_USER"], + "username": "sabine" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/util/object_id_collection.json b/alfa-client/apps/alfa-e2e/src/fixtures/util/object_id_collection.json index a1d126c417691d0371a2878140c64423882b2217..df26b74ad65b874bf021fcd5ce6d7cbf005a5491 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/util/object_id_collection.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/util/object_id_collection.json @@ -1,19 +1,19 @@ [ - "60d9fa33290e586b59a6b311", - "602566a807bb665df9a86e87", - "602566a207bb665df9a86e86", - "6287e73f93b7c34e3ce08a4f", - "6287e7497433b51bfc87cfe8", - "6287e7507433b51bfc87cfe9", - "63f36a253b699e31515bcfac", - "63ef6a343b699e31515bcfa5", - "63ef5dc73b699e31515bcfa2", - "63ef541b0b962e161eac58c0", - "63ef54020b962e161eac58bd", - "63f89809c3da394fab1ca99b", - "63f891a1c3da394fab1ca994", - "63f89142c3da394fab1ca98d", - "63f881fac3da394fab1ca985", - "63f8812ac3da394fab1ca97e", - "63f87a08d51f927a669b3807" + "60d9fa33290e586b59a6b311", + "602566a807bb665df9a86e87", + "602566a207bb665df9a86e86", + "6287e73f93b7c34e3ce08a4f", + "6287e7497433b51bfc87cfe8", + "6287e7507433b51bfc87cfe9", + "63f36a253b699e31515bcfac", + "63ef6a343b699e31515bcfa5", + "63ef5dc73b699e31515bcfa2", + "63ef541b0b962e161eac58c0", + "63ef54020b962e161eac58bd", + "63f89809c3da394fab1ca99b", + "63f891a1c3da394fab1ca994", + "63f89142c3da394fab1ca98d", + "63f881fac3da394fab1ca985", + "63f8812ac3da394fab1ca97e", + "63f87a08d51f927a669b3807" ] diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/vorgang/vorgang-attached-item.json b/alfa-client/apps/alfa-e2e/src/fixtures/vorgang/vorgang-attached-item.json index 50dd96dd38e5148faa317450ab3397f4f3bd8a8e..db04e9b2a253ce6f857c04dfbac50d6452b7dd3b 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/vorgang/vorgang-attached-item.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/vorgang/vorgang-attached-item.json @@ -1,14 +1,14 @@ { - "_id": { - "$oid": "602566a807bb665df9a86111" - }, - "version": 0, - "client": "OzgCloud_NachrichtenManager", - "vorgangId": "602566a807bb665df9a86111", - "itemName": "PostfachMail", - "item": { - "createdAt": "2020-12-02T14:58:43.790Z[UTC]", - "vorgangId": "602566a807bb665df9a86111" - }, - "_class" : "VorgangAttachedItem" -} \ No newline at end of file + "_id": { + "$oid": "602566a807bb665df9a86111" + }, + "version": 0, + "client": "OzgCloud_NachrichtenManager", + "vorgangId": "602566a807bb665df9a86111", + "itemName": "PostfachMail", + "item": { + "createdAt": "2020-12-02T14:58:43.790Z[UTC]", + "vorgangId": "602566a807bb665df9a86111" + }, + "_class": "VorgangAttachedItem" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/vorgang/vorgang.json b/alfa-client/apps/alfa-e2e/src/fixtures/vorgang/vorgang.json index 2de28060fa02949617eb1cda08335a4ebbb74357..de76807af6b0db9cb04680c2b4c0c88ae19beb7c 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/vorgang/vorgang.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/vorgang/vorgang.json @@ -1,95 +1,101 @@ { - "_id": { - "$oid": "602566a807bb665df9a86111" - }, - "version": 0, - "createdAt": { - "$date": "2021-02-11T17:17:28.000Z" - }, - "aktenzeichen": "AKT_ENZ_EIC_HEN", - "nummer": "VOR_GANG_NUM_MER", - "name": "Vorgang", - "status": "NEU", - "inCreation": false, - "header": { - "serviceKonto": { - "type": "OSI", - "postfachAddresses": [{ - "type": 1, - "identifier": { - "postfachId": "04d39269-81c5-4838-8b73-08d9567f06d7" - } - }] - } - }, - "eingangs": [ - { - "_id": "21c64d65-ee8e-4f29-90c7-eca24d9d1111", - "header": { - "requestId": "20201202575230443111", - "createdAt": { - "$date": "2020-12-02T14:58:43.790Z" - }, - "formId": "eStrassengefaelle/eUeberarbeitung", - "formName": "Überarbeitung Straßengefälle nach §12", - "sender": "afm.schleswig-holstein.de", - "customer": "Einheitlicher Ansprechpartner", - "customerId": "ea-sh", - "client": "Schleswig-Holstein", - "clientId": "land" - }, - "antragsteller": { - "anrede": "Herr", - "nachname": "Testermann", - "vorname": "Max", - "geburtsdatum": "1995-03-21", - "geburtsort": "Flensburg", - "geburtsname": "Max Testermann", - "email": "e2e-test@ozg-sh.de", - "telefon": "+ 49 3X4 434X", - "strasse": "testpipelineStrasse", - "hausnummer": "22a", - "plz": "66X00", - "ort": "Schleswig Holstein", - "postfachId" : "04d39269-81c5-4838-8b73-08d9567f06d7" - }, - "zustaendigeStelle": { - "email": "e2e-zustaendigestelle@ozg-sh.de", - "organisationseinheitenId": "12345678" - }, - "formData": { - "ort": "Überörtlingen", - "sh_hausnummer": "12 a", - "sh_strasse": "Fallstraße", - "bezFlurstuek": ["1bd2d9b1e-1210-11ec-82a8-0242ac130003", "2bd2d9b1e-1210-11ec-82a8-0242ac130003"], - "empfangendestelle" : { - "telefaxnummer" : "+49 431 988-6161111", - "emailadresse" : "e2e-formdata-email@ozg-sh.de", - "strasse" : "Reventlouallee", - "od_zustellung_nb" : "afmsh:9068873_AusnahmeLKWFahrverbot", - "kontaktsystem_kennung" : "afmsh:9068873_AusnahmeLKWFahrverbot", - "OrganisationseinheitenAuswahl" : "9068873", - "OrganisationseinheitenID" : "9068873", - "ort" : "Kiel", - "postleitzahl" : "24105", - "kontaktsystem_kennungzusatz" : "alle", - "od_kennung" : "afmsh:9068873_AusnahmeLKWFahrverbot", - "od_vorhanden" : "true", - "od_typid" : "233034600", - "demailadresse" : "e2e-formdata-demail@ozg-sh.de", - "hausnummer" : "6", "telefonnummer" : "+49 431 988-8650", - "OrganisationseinheitenBEZEICHNUNG" : "Einheitlicher Ansprechpartner Schleswig-Holstein", - "ortID" : "9006402", - "_kopControlData" : { - "metaData" : "true" - } - } - }, - "attachments": [], - "representations": [], - "numberOfAttachments": 0, - "numberOfRepresentations": 0 - } - ], - "_class": "Vorgang" -} \ No newline at end of file + "_id": { + "$oid": "602566a807bb665df9a86111" + }, + "version": 0, + "createdAt": { + "$date": "2021-02-11T17:17:28.000Z" + }, + "aktenzeichen": "AKT_ENZ_EIC_HEN", + "nummer": "VOR_GANG_NUM_MER", + "name": "Vorgang", + "status": "NEU", + "inCreation": false, + "header": { + "serviceKonto": { + "type": "OSI", + "postfachAddresses": [ + { + "type": 1, + "identifier": { + "postfachId": "04d39269-81c5-4838-8b73-08d9567f06d7" + } + } + ] + } + }, + "eingangs": [ + { + "_id": "21c64d65-ee8e-4f29-90c7-eca24d9d1111", + "header": { + "requestId": "20201202575230443111", + "createdAt": { + "$date": "2020-12-02T14:58:43.790Z" + }, + "formId": "eStrassengefaelle/eUeberarbeitung", + "formName": "Überarbeitung Straßengefälle nach §12", + "sender": "afm.schleswig-holstein.de", + "customer": "Einheitlicher Ansprechpartner", + "customerId": "ea-sh", + "client": "Schleswig-Holstein", + "clientId": "land" + }, + "antragsteller": { + "anrede": "Herr", + "nachname": "Testermann", + "vorname": "Max", + "geburtsdatum": "1995-03-21", + "geburtsort": "Flensburg", + "geburtsname": "Max Testermann", + "email": "e2e-test@ozg-sh.de", + "telefon": "+ 49 3X4 434X", + "strasse": "testpipelineStrasse", + "hausnummer": "22a", + "plz": "66X00", + "ort": "Schleswig Holstein", + "postfachId": "04d39269-81c5-4838-8b73-08d9567f06d7" + }, + "zustaendigeStelle": { + "email": "e2e-zustaendigestelle@ozg-sh.de", + "organisationseinheitenId": "12345678" + }, + "formData": { + "ort": "Überörtlingen", + "sh_hausnummer": "12 a", + "sh_strasse": "Fallstraße", + "bezFlurstuek": [ + "1bd2d9b1e-1210-11ec-82a8-0242ac130003", + "2bd2d9b1e-1210-11ec-82a8-0242ac130003" + ], + "empfangendestelle": { + "telefaxnummer": "+49 431 988-6161111", + "emailadresse": "e2e-formdata-email@ozg-sh.de", + "strasse": "Reventlouallee", + "od_zustellung_nb": "afmsh:9068873_AusnahmeLKWFahrverbot", + "kontaktsystem_kennung": "afmsh:9068873_AusnahmeLKWFahrverbot", + "OrganisationseinheitenAuswahl": "9068873", + "OrganisationseinheitenID": "9068873", + "ort": "Kiel", + "postleitzahl": "24105", + "kontaktsystem_kennungzusatz": "alle", + "od_kennung": "afmsh:9068873_AusnahmeLKWFahrverbot", + "od_vorhanden": "true", + "od_typid": "233034600", + "demailadresse": "e2e-formdata-demail@ozg-sh.de", + "hausnummer": "6", + "telefonnummer": "+49 431 988-8650", + "OrganisationseinheitenBEZEICHNUNG": "Einheitlicher Ansprechpartner Schleswig-Holstein", + "ortID": "9006402", + "_kopControlData": { + "metaData": "true" + } + } + }, + "attachments": [], + "representations": [], + "numberOfAttachments": 0, + "numberOfRepresentations": 0 + } + ], + "_class": "Vorgang" +} diff --git a/alfa-client/apps/alfa-e2e/src/fixtures/wiedervorlage/wiedervorlage.json b/alfa-client/apps/alfa-e2e/src/fixtures/wiedervorlage/wiedervorlage.json index 70bf44468acee58e5d87ae4b5dd4c31dede7e894..733031afddd716535e4a7d8ff29e956e91921bdd 100644 --- a/alfa-client/apps/alfa-e2e/src/fixtures/wiedervorlage/wiedervorlage.json +++ b/alfa-client/apps/alfa-e2e/src/fixtures/wiedervorlage/wiedervorlage.json @@ -1,10 +1,10 @@ { - "version": 0, - "vorgangId": "602566a807bb665df9a86111", - "createdAt": "2021-03-17T08:43:52.000Z[UTC]", - "createdBy": "SetInCode", - "betreff": "Wiedervorlage", - "beschreibung": "Dies ist ein Test", - "frist": "2020-01-01", - "done": false -} \ No newline at end of file + "version": 0, + "vorgangId": "602566a807bb665df9a86111", + "createdAt": "2021-03-17T08:43:52.000Z[UTC]", + "createdBy": "SetInCode", + "betreff": "Wiedervorlage", + "beschreibung": "Dies ist ein Test", + "frist": "2020-01-01", + "done": false +} diff --git a/alfa-client/apps/alfa-e2e/src/model/app.ts b/alfa-client/apps/alfa-e2e/src/model/app.ts index eafeb6c1fee4c874038f041e94e57bdba411d260..f1d3b803032cb4355e644612dc97e5ec538a7ec1 100644 --- a/alfa-client/apps/alfa-e2e/src/model/app.ts +++ b/alfa-client/apps/alfa-e2e/src/model/app.ts @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class App { - title: string -} \ No newline at end of file + title: string; +} diff --git a/alfa-client/apps/alfa-e2e/src/model/binary-file.ts b/alfa-client/apps/alfa-e2e/src/model/binary-file.ts index c3b35bd420899360b8acc905f67bf512b022022f..2b0e3fc80fa57e316ecc5c4ada64e0bd6d627540 100644 --- a/alfa-client/apps/alfa-e2e/src/model/binary-file.ts +++ b/alfa-client/apps/alfa-e2e/src/model/binary-file.ts @@ -24,54 +24,53 @@ import { ClientE2E, DateE2E, ObjectIdE2E } from './util'; export enum BinaryFileSnackbarMessageE2E { - ATTACHMENT_NOT_ADDED = 'Anhänge größer {size} können nicht hinzugefügt werden.' + ATTACHMENT_NOT_ADDED = 'Anhänge größer {size} können nicht hinzugefügt werden.', } export enum BinaryFileFieldE2E { - WIEDERVORLAGE_ATTACHMENT = 'wiedervorlageAttachment', - POSTFACH_NACHRICHT_ATTACHMENT = 'PostfachNachrichtAttachment', - VORGANG_ATTACHMENT = 'vorgangAttachment' + WIEDERVORLAGE_ATTACHMENT = 'wiedervorlageAttachment', + POSTFACH_NACHRICHT_ATTACHMENT = 'PostfachNachrichtAttachment', + VORGANG_ATTACHMENT = 'vorgangAttachment', } export class FileDataE2E { - _id: string; - vendorId: string; - name: string; - size: number; - contentType: string; - content: BinaryBase64E2E;//TODO Entfernen -> content wird jetzt im GridFs gespeichert + _id: string; + vendorId: string; + name: string; + size: number; + contentType: string; + content: BinaryBase64E2E; //TODO Entfernen -> content wird jetzt im GridFs gespeichert } export interface GridFsFileDataE2E { - file: GridFsFileE2E - chunks: GridFsChunkE2E[] + file: GridFsFileE2E; + chunks: GridFsChunkE2E[]; } export interface GridFsFileE2E { - _id: ObjectIdE2E, - filename: string, - length: number, - chunkSize: number, - uploadDate: DateE2E, - metadata: GridFsFileMetadataE2E + _id: ObjectIdE2E; + filename: string; + length: number; + chunkSize: number; + uploadDate: DateE2E; + metadata: GridFsFileMetadataE2E; } export interface GridFsFileMetadataE2E { - vorgangId: string, - client: ClientE2E, - fieldName: BinaryFileFieldE2E, - name: string, - createdBy: string + vorgangId: string; + client: ClientE2E; + fieldName: BinaryFileFieldE2E; + name: string; + createdBy: string; } export interface GridFsChunkE2E { - _id: ObjectIdE2E, - files_id: ObjectIdE2E, - n: number, - data: BinaryBase64E2E + _id: ObjectIdE2E; + files_id: ObjectIdE2E; + n: number; + data: BinaryBase64E2E; } - export class BinaryBase64E2E { - $binary: { base64: string }; -} \ No newline at end of file + $binary: { base64: string }; +} diff --git a/alfa-client/apps/alfa-e2e/src/model/command.ts b/alfa-client/apps/alfa-e2e/src/model/command.ts index 18556df32ad6bbdeee543c2ab915e73fb4b4ce15..acd160995e1bd16bc44116bd41f0e0977cb05e0c 100644 --- a/alfa-client/apps/alfa-e2e/src/model/command.ts +++ b/alfa-client/apps/alfa-e2e/src/model/command.ts @@ -24,28 +24,28 @@ import { DateE2E } from './util'; export enum CommandOrderE2E { - ASSIGN_USER = 'ASSIGN_USER', - CREATE_ATTACHED_ITEM = 'CREATE_ATTACHED_ITEM', - FORWARD_VORGANG = 'REDIRECT_VORGANG',//TODO Rename Order - FORWARD_SUCCESSFUL = 'FORWARD_SUCCESSFULL', //TODO Rename Order - FORWARD_FAILED = 'FORWARD_FAILED', - PATCH_ATTACHED_ITEM = 'PATCH_ATTACHED_ITEM', - RECEIVE_POSTFACH_NACHRICHT = 'RECEIVE_POSTFACH_NACHRICHT', - RESEND_POSTFACH_NACHRICHT = 'RESEND_POSTFACH_MAIL', - SEND_POSTFACH_MAIL = 'SEND_POSTFACH_MAIL', - SEND_POSTFACH_NACHRICHT = 'SEND_POSTFACH_NACHRICHT', - UPDATE_ATTACHED_ITEM = 'UPDATE_ATTACHED_ITEM' + ASSIGN_USER = 'ASSIGN_USER', + CREATE_ATTACHED_ITEM = 'CREATE_ATTACHED_ITEM', + FORWARD_VORGANG = 'REDIRECT_VORGANG', //TODO Rename Order + FORWARD_SUCCESSFUL = 'FORWARD_SUCCESSFULL', //TODO Rename Order + FORWARD_FAILED = 'FORWARD_FAILED', + PATCH_ATTACHED_ITEM = 'PATCH_ATTACHED_ITEM', + RECEIVE_POSTFACH_NACHRICHT = 'RECEIVE_POSTFACH_NACHRICHT', + RESEND_POSTFACH_NACHRICHT = 'RESEND_POSTFACH_MAIL', + SEND_POSTFACH_MAIL = 'SEND_POSTFACH_MAIL', + SEND_POSTFACH_NACHRICHT = 'SEND_POSTFACH_NACHRICHT', + UPDATE_ATTACHED_ITEM = 'UPDATE_ATTACHED_ITEM', } export class CommandE2E { - vorgangId: string; - createdAt: DateE2E; - createdBy: string; - createdByName: string; - status: string; - relationId: string; - relationVersion: number; - order: CommandOrderE2E; - body?: any; - bodyObject: any; - finishedAt: DateE2E; -} \ No newline at end of file + vorgangId: string; + createdAt: DateE2E; + createdBy: string; + createdByName: string; + status: string; + relationId: string; + relationVersion: number; + order: CommandOrderE2E; + body?: any; + bodyObject: any; + finishedAt: DateE2E; +} diff --git a/alfa-client/apps/alfa-e2e/src/model/historie.ts b/alfa-client/apps/alfa-e2e/src/model/historie.ts index 2b7107073d2c379abf22fd931f1d0024e3fc1f7a..32c7933764d7661336372f872661b1bd498ac2a8 100644 --- a/alfa-client/apps/alfa-e2e/src/model/historie.ts +++ b/alfa-client/apps/alfa-e2e/src/model/historie.ts @@ -24,29 +24,31 @@ import { PostfachE2E } from './postfach-nachricht'; export enum HistorieHeadlineE2E { - ASSIGN_USER = 'den Vorgang zugewiesen.', - CREATE_WIEDERVORLAGE = 'eine Wiedervorlage hinzugefügt.', - CREATE_KOMMENTAR = 'ein Kommentar hinzugefügt', - EDIT_WIEDERVORLAGE = 'eine Wiedervorlage bearbeitet.', - EDIT_KOMMENTAR = 'ein Kommentar bearbeitet.', - FORWARD_VORGANG = ' den Vorgang weitergeleitet', - FORWARD_SUCCESSFUL = 'die Weiterleitung bestätigt.', - FORWARD_FAILED = 'die Weiterleitung widerrufen.', - SEND_POSTFACH_NACHRICHT = 'eine Nachricht geschrieben', - RECEIVE_POSTFACH_NACHRICHT = 'eine Nachricht des Antragstellers empfangen.', - RESEND_POSTFACH_NACHRICHT = 'eine Nachricht erneut versendet.', - WIEDERVORLAGE_ERLEDIGEN = 'eine Wiedervorlage als erledigt markiert.', - WIEDERVORLAGE_WIEDEREROEFFNEN = 'eine Wiedervorlage als offen markiert.', + ASSIGN_USER = 'den Vorgang zugewiesen.', + CREATE_WIEDERVORLAGE = 'eine Wiedervorlage hinzugefügt.', + CREATE_KOMMENTAR = 'ein Kommentar hinzugefügt', + EDIT_WIEDERVORLAGE = 'eine Wiedervorlage bearbeitet.', + EDIT_KOMMENTAR = 'ein Kommentar bearbeitet.', + FORWARD_VORGANG = ' den Vorgang weitergeleitet', + FORWARD_SUCCESSFUL = 'die Weiterleitung bestätigt.', + FORWARD_FAILED = 'die Weiterleitung widerrufen.', + SEND_POSTFACH_NACHRICHT = 'eine Nachricht geschrieben', + RECEIVE_POSTFACH_NACHRICHT = 'eine Nachricht des Antragstellers empfangen.', + RESEND_POSTFACH_NACHRICHT = 'eine Nachricht erneut versendet.', + WIEDERVORLAGE_ERLEDIGEN = 'eine Wiedervorlage als erledigt markiert.', + WIEDERVORLAGE_WIEDEREROEFFNEN = 'eine Wiedervorlage als offen markiert.', + AKTENZEICHEN_GEAENDERT = 'das Aktenzeichen geändert', + AKTENZEICHEN_GELOESCHT = 'das Aktenzeichen gelöscht', } export class HistorieE2E { - headline: HistorieHeadlineE2E; - body: PostfachE2E; + headline: HistorieHeadlineE2E; + body: PostfachE2E; } export enum HistorieAttachmentE2E { - SINGLE_TEXT = 'Es existiert ein Anhang zu diesem Eintrag.', - MULTIPLE_TEXT = 'Es existieren {countAttachments} Anhänge zu diesem Eintrag.' + SINGLE_TEXT = 'Es existiert ein Anhang zu diesem Eintrag.', + MULTIPLE_TEXT = 'Es existieren {countAttachments} Anhänge zu diesem Eintrag.', } -export const SYSTEM_USER_NAME = 'Die Anwendung'; \ No newline at end of file +export const SYSTEM_USER_NAME = 'Die Anwendung'; diff --git a/alfa-client/apps/alfa-e2e/src/model/kommentar.ts b/alfa-client/apps/alfa-e2e/src/model/kommentar.ts index 00727666e1af40d7ab10af1c574dff4057b26a2a..9186ad551d729790ab091c6996d0d83ed21e3448 100644 --- a/alfa-client/apps/alfa-e2e/src/model/kommentar.ts +++ b/alfa-client/apps/alfa-e2e/src/model/kommentar.ts @@ -24,7 +24,7 @@ import { DateE2E } from './util'; export class KommentarE2E { - createdAt: DateE2E; - createdBy: string; - text: string; -} \ No newline at end of file + createdAt: DateE2E; + createdBy: string; + text: string; +} diff --git a/alfa-client/apps/alfa-e2e/src/model/loesch-anforderung.ts b/alfa-client/apps/alfa-e2e/src/model/loesch-anforderung.ts index 7dffa51bd589c6a890a299d549363adf6ec454d1..427354e69a96962c5fa5133b472004a7875e2269 100644 --- a/alfa-client/apps/alfa-e2e/src/model/loesch-anforderung.ts +++ b/alfa-client/apps/alfa-e2e/src/model/loesch-anforderung.ts @@ -24,6 +24,6 @@ import { VorgangStatusE2E } from './vorgang'; export class LoeschAnforderungE2E { - requestedBy: string; - prevStatus: VorgangStatusE2E; -} \ No newline at end of file + requestedBy: string; + prevStatus: VorgangStatusE2E; +} diff --git a/alfa-client/apps/alfa-e2e/src/model/postfach-nachricht.ts b/alfa-client/apps/alfa-e2e/src/model/postfach-nachricht.ts index c1222cb974e96f1451b3350fef9545cb2a27f8b8..a987ce80329531a2f3da8626dadf45a158aaef90 100644 --- a/alfa-client/apps/alfa-e2e/src/model/postfach-nachricht.ts +++ b/alfa-client/apps/alfa-e2e/src/model/postfach-nachricht.ts @@ -22,13 +22,13 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum PostfachReplyOptionE2E { - FORBIDDEN = 'FORBIDDEN' + FORBIDDEN = 'FORBIDDEN', } export class PostfachE2E { - subject: string; - mailBody: string; - replyOption: PostfachReplyOptionE2E; - attachments: string[] | string; - class: string; -} \ No newline at end of file + subject: string; + mailBody: string; + replyOption: PostfachReplyOptionE2E; + attachments: string[] | string; + class: string; +} diff --git a/alfa-client/apps/alfa-e2e/src/model/user.ts b/alfa-client/apps/alfa-e2e/src/model/user.ts index 00449d176aea80698344e14bb1c1db83d20bd373..63a64a6f8371e62e2ce152c9cac268449376276e 100644 --- a/alfa-client/apps/alfa-e2e/src/model/user.ts +++ b/alfa-client/apps/alfa-e2e/src/model/user.ts @@ -22,13 +22,13 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export interface UserE2E { - uuid: string; - id: string; - name: string; - password: string; - firstName: string; - lastName: string; - fullName: string; - initials: string; - dataTestId: string; -} \ No newline at end of file + uuid: string; + id: string; + name: string; + password: string; + firstName: string; + lastName: string; + fullName: string; + initials: string; + dataTestId: string; +} diff --git a/alfa-client/apps/alfa-e2e/src/model/usermanager.ts b/alfa-client/apps/alfa-e2e/src/model/usermanager.ts index 8effc31da1e11440a9fb74481f256f50b7a2c966..a834b2438ef5f63973969f5b984989995d6ec493 100644 --- a/alfa-client/apps/alfa-e2e/src/model/usermanager.ts +++ b/alfa-client/apps/alfa-e2e/src/model/usermanager.ts @@ -24,12 +24,12 @@ import { DateE2E, ObjectIdE2E } from './util'; export interface UsermanagerUserE2E { - _id: ObjectIdE2E; - createdAt: DateE2E; - deleted: boolean; - keycloakUserId: string; - firstName: string; - lastName: string; - fullName: string; - username: string; -} \ No newline at end of file + _id: ObjectIdE2E; + createdAt: DateE2E; + deleted: boolean; + keycloakUserId: string; + firstName: string; + lastName: string; + fullName: string; + username: string; +} diff --git a/alfa-client/apps/alfa-e2e/src/model/util.ts b/alfa-client/apps/alfa-e2e/src/model/util.ts index bcef9b96d5db8e77c86f5a07bdd4611b2bee3c68..a04059914babc599eb3ba242faa5f580497c385b 100644 --- a/alfa-client/apps/alfa-e2e/src/model/util.ts +++ b/alfa-client/apps/alfa-e2e/src/model/util.ts @@ -22,32 +22,32 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export class DateE2E { - $date: string; + $date: string; } export class ObjectIdE2E { - $oid: string; + $oid: string; } export declare type ResourceUriE2E = string; export interface ResourceE2E { - _links; + _links; } export enum HttpMethodE2E { - POST = 'POST', - PUT = 'PUT', - PATCH = 'PATCH', - DELETE = 'DELETE', - GET = 'GET' + POST = 'POST', + PUT = 'PUT', + PATCH = 'PATCH', + DELETE = 'DELETE', + GET = 'GET', } export enum MessageCodeE2E { - RESOURCE_NOT_FOUND = 'resource.not_found', - SERVICE_UNAVAILABLE = 'generale.service_unavailable' + RESOURCE_NOT_FOUND = 'resource.not_found', + SERVICE_UNAVAILABLE = 'generale.service_unavailable', } export enum ClientE2E { - EINGANG_ADAPTER = 'eingangAdapter' -} \ No newline at end of file + EINGANG_ADAPTER = 'eingangAdapter', +} diff --git a/alfa-client/apps/alfa-e2e/src/model/vorgang-attached-item.ts b/alfa-client/apps/alfa-e2e/src/model/vorgang-attached-item.ts index f4f284aff0f94e21acb50b7d7042d43d1cc6de10..bef95bcbdc231077dbe183971db325ebf2f4f0c6 100644 --- a/alfa-client/apps/alfa-e2e/src/model/vorgang-attached-item.ts +++ b/alfa-client/apps/alfa-e2e/src/model/vorgang-attached-item.ts @@ -27,65 +27,65 @@ import { ObjectIdE2E } from './util'; import { WiedervorlageE2E } from './wiedervorlage'; export enum VorgangAttachedItemClientE2E { - ALFA = 'Alfa', - OZGCLOUD_NACHRICHTEN_MANAGER = 'OzgCloud_NachrichtenManager' + ALFA = 'Alfa', + OZGCLOUD_NACHRICHTEN_MANAGER = 'OzgCloud_NachrichtenManager', } export enum VorgangAttachedItemNameE2E { - POSTFACH_NACHRICHT = 'PostfachMail', - WIEDERVORLAGE = 'Wiedervorlage', - KOMMENTAR = 'Kommentar', - LOESCH_ANFORDERUNG = 'LoeschAnforderung', + POSTFACH_NACHRICHT = 'PostfachMail', + WIEDERVORLAGE = 'Wiedervorlage', + KOMMENTAR = 'Kommentar', + LOESCH_ANFORDERUNG = 'LoeschAnforderung', } export class VorgangAttachedItemE2E { - _id: ObjectIdE2E; - version: number; - client: VorgangAttachedItemClientE2E; - vorgangId: string; - itemName: VorgangAttachedItemNameE2E; - item: PostfachMailItemE2E | WiedervorlageE2E | LoeschAnforderungE2E | KommentarE2E; - deleted: boolean; - _class: string; + _id: ObjectIdE2E; + version: number; + client: VorgangAttachedItemClientE2E; + vorgangId: string; + itemName: VorgangAttachedItemNameE2E; + item: PostfachMailItemE2E | WiedervorlageE2E | LoeschAnforderungE2E | KommentarE2E; + deleted: boolean; + _class: string; } //PostfachMail export class PostfachMailItemE2E { - postfachId: string; - createdAt: Date; - mailBody: string; - createdBy: string; - subject: string; - vorgangId: string; - replyOption: ReplyOptionE2E; - direction: DirectionE2E; - sentAt: Date | string; - sentSuccessful: boolean; - messageCode: PostfachNachrichtMessageCodeE2E; - attachments: string[]; + postfachId: string; + createdAt: Date; + mailBody: string; + createdBy: string; + subject: string; + vorgangId: string; + replyOption: ReplyOptionE2E; + direction: DirectionE2E; + sentAt: Date | string; + sentSuccessful: boolean; + messageCode: PostfachNachrichtMessageCodeE2E; + attachments: string[]; } export enum ReplyOptionE2E { - POSSIBLE = 'POSSIBLE', - FORBIDDEN = 'FORBIDDEN' + POSSIBLE = 'POSSIBLE', + FORBIDDEN = 'FORBIDDEN', } export enum DirectionE2E { - IN = 'IN', - OUT = 'OUT' + IN = 'IN', + OUT = 'OUT', } export enum PostfachNachrichtMessageCodeE2E { - PROCESSING_FAILED = 'postfachnachricht.server.processing_failed', - CONNECTION_FAILED = 'postfachnachricht.server.connection_failed' + PROCESSING_FAILED = 'postfachnachricht.server.processing_failed', + CONNECTION_FAILED = 'postfachnachricht.server.connection_failed', } export enum PostfachNachrichtMessageCodeMessagesE2E { - CONNECTION_FAILED = 'Verbindungsfehler: Die Verbindung zum Zielserver des Osi-Postfachs ist nicht zustandegekommen.', - PROCESSING_FAILED = 'Fehlerhafte Verarbeitung: Die Nachricht wurde an das Osi-Postfach geschickt, konnte dort aber nicht richtig verarbeitet werden.' + CONNECTION_FAILED = 'Verbindungsfehler: Die Verbindung zum Zielserver des Osi-Postfachs ist nicht zustandegekommen.', + PROCESSING_FAILED = 'Fehlerhafte Verarbeitung: Die Nachricht wurde an das Osi-Postfach geschickt, konnte dort aber nicht richtig verarbeitet werden.', } export enum PostfachNachrichtSnackbarMessageE2E { - SEND_SUCCESSFUL = 'Die Nachricht wurde erfolgreich versendet.', - ATTACHMENT_TO_LAREGE = 'Anhänge größer 3MB können nicht versendet werden.'//TODO: Umbenennen -} \ No newline at end of file + SEND_SUCCESSFUL = 'Die Nachricht wurde erfolgreich versendet.', + ATTACHMENT_TO_LAREGE = 'Anhänge größer 3MB können nicht versendet werden.', //TODO: Umbenennen +} diff --git a/alfa-client/apps/alfa-e2e/src/model/vorgang.ts b/alfa-client/apps/alfa-e2e/src/model/vorgang.ts index 370b009a015694090a003f7b59c93aa425f2e332..aca577c4cea54f5d30ca05ca61956be6cb82099b 100644 --- a/alfa-client/apps/alfa-e2e/src/model/vorgang.ts +++ b/alfa-client/apps/alfa-e2e/src/model/vorgang.ts @@ -27,137 +27,135 @@ import { DateE2E, ObjectIdE2E, ResourceUriE2E } from './util'; import { WiedervorlageE2E } from './wiedervorlage'; export enum ClientAttributeNameE2E { - NEXT_WIEDERVORLAGE_FRIST = 'nextWiedervorlageFrist', - HAS_POSTFACH_NACHRICHT = 'hasPostfachNachricht', - HAS_NEW_POSTFACH_NACHRICHT = 'hasNewPostfachNachricht' + NEXT_WIEDERVORLAGE_FRIST = 'nextWiedervorlageFrist', + HAS_POSTFACH_NACHRICHT = 'hasPostfachNachricht', + HAS_NEW_POSTFACH_NACHRICHT = 'hasNewPostfachNachricht', } export enum AccessPermissionE2E { - READ_ONLY = 'READ_ONLY', - READ_WRITE = 'READ_WRITE' + READ_ONLY = 'READ_ONLY', + READ_WRITE = 'READ_WRITE', } export interface ClientAttributeE2E { - access: AccessPermissionE2E, - value: string | number | boolean, - _class: string + access: AccessPermissionE2E; + value: string | number | boolean; + _class: string; } export interface ClientAttributesE2E { - [client: string]: { - [attributeName: string]: ClientAttributeE2E - } + [client: string]: { + [attributeName: string]: ClientAttributeE2E; + }; } export class VorgangE2E { - _id: ObjectIdE2E; - version: string; - createdAt: DateE2E; - name: string; - status: VorgangStatusE2E; - aktenzeichen: string; - nummer: string; - header: VorgangHeaderE2E; - eingangs: EingangE2E[]; - wiedervorlages: WiedervorlageE2E[]; - kommentars: KommentarE2E[]; - assignedTo: ResourceUriE2E; - clientAttributes: ClientAttributesE2E; + _id: ObjectIdE2E; + version: string; + createdAt: DateE2E; + name: string; + status: VorgangStatusE2E; + aktenzeichen: string; + nummer: string; + header: VorgangHeaderE2E; + eingangs: EingangE2E[]; + wiedervorlages: WiedervorlageE2E[]; + kommentars: KommentarE2E[]; + assignedTo: ResourceUriE2E; + clientAttributes: ClientAttributesE2E; } export class VorgangHeaderE2E { - serviceKonto: ServiceKontoE2E; + serviceKonto: ServiceKontoE2E; } export class ServiceKontoE2E { - type: string; - postfachAddress: PostfachAddressE2E[]; + type: string; + postfachAddress: PostfachAddressE2E[]; } export class PostfachAddressE2E { - type: number; - identifier: ReadonlyMap<string, object>; + type: number; + identifier: ReadonlyMap<string, object>; } export class EingangE2E { - header: EingangHeaderE2E; - antragsteller?: AntragstellerE2E; - zustaendigeStelle?: ZustaendigeStelleE2E; - attachments: AttachmentE2E[]; - representations: FileDataE2E[]; - numberOfAttachments: number; - numberOfRepresentations: number; - formData; + header: EingangHeaderE2E; + antragsteller?: AntragstellerE2E; + zustaendigeStelle?: ZustaendigeStelleE2E; + attachments: AttachmentE2E[]; + representations: FileDataE2E[]; + numberOfAttachments: number; + numberOfRepresentations: number; + formData; } export class EingangHeaderE2E { - requestId: string; - createdAt: DateE2E; - formId: string; - formEngineName: string; + requestId: string; + createdAt: DateE2E; + formId: string; + formEngineName: string; } - - export class AntragstellerE2E { - anrede: string; - nachname: string; - vorname: string; - geburtsort: string; - geburtsname: string; - postfachId: string; - geburtsdatum: string; - email: string; - telefon: string; - strasse: string; - hausnummer: string; - plz: string; - ort: string; + anrede: string; + nachname: string; + vorname: string; + geburtsort: string; + geburtsname: string; + postfachId: string; + geburtsdatum: string; + email: string; + telefon: string; + strasse: string; + hausnummer: string; + plz: string; + ort: string; } export class ZustaendigeStelleE2E { - organisationseinheitenId: string; + organisationseinheitenId: string; } export class AttachmentE2E { - name: string; - files: FileDataE2E[]; + name: string; + files: FileDataE2E[]; } export enum VorgangStatusE2E { - NEU = 'NEU', - ANGENOMMEN = 'ANGENOMMEN', - VERWORFEN = 'VERWORFEN', - IN_BEARBEITUNG = 'IN_BEARBEITUNG', - BESCHIEDEN = 'BESCHIEDEN', - ABGESCHLOSSEN = 'ABGESCHLOSSEN', - WEITERGELEITET = 'WEITERGELEITET', - ZU_LOESCHEN = 'ZU_LOESCHEN' + NEU = 'NEU', + ANGENOMMEN = 'ANGENOMMEN', + VERWORFEN = 'VERWORFEN', + IN_BEARBEITUNG = 'IN_BEARBEITUNG', + BESCHIEDEN = 'BESCHIEDEN', + ABGESCHLOSSEN = 'ABGESCHLOSSEN', + WEITERGELEITET = 'WEITERGELEITET', + ZU_LOESCHEN = 'ZU_LOESCHEN', } export const vorgangStatusLabelE2E = { - [VorgangStatusE2E.NEU]: 'Neu', - [VorgangStatusE2E.ANGENOMMEN]: 'Angenommen', - [VorgangStatusE2E.VERWORFEN]: 'Verworfen', - [VorgangStatusE2E.IN_BEARBEITUNG]: 'In Bearbeitung', - [VorgangStatusE2E.BESCHIEDEN]: 'Beschieden', - [VorgangStatusE2E.ABGESCHLOSSEN]: 'Abgeschlossen', - [VorgangStatusE2E.WEITERGELEITET]: 'Weitergeleitet', - [VorgangStatusE2E.ZU_LOESCHEN]: 'Zu Löschen', -} + [VorgangStatusE2E.NEU]: 'Neu', + [VorgangStatusE2E.ANGENOMMEN]: 'Angenommen', + [VorgangStatusE2E.VERWORFEN]: 'Verworfen', + [VorgangStatusE2E.IN_BEARBEITUNG]: 'In Bearbeitung', + [VorgangStatusE2E.BESCHIEDEN]: 'Beschieden', + [VorgangStatusE2E.ABGESCHLOSSEN]: 'Abgeschlossen', + [VorgangStatusE2E.WEITERGELEITET]: 'Weitergeleitet', + [VorgangStatusE2E.ZU_LOESCHEN]: 'Zu Löschen', +}; export enum VorgangMessagesE2E { - ANGENOMMEN = 'Der Vorgang wurde angenommen.', - VERWORFEN = 'Der Vorgang wurde verworfen.', - ZURUECKGEHOLT = 'Der Vorgang wurde zurückgeholt.', - BEARBEITET = 'Der Vorgang wurde in die Bearbeitung übernommen.', - BESCHIEDEN = 'Der Vorgang wurde beschieden.', - ZURUECKGESTELLT = 'Der Vorgang wurde zurückgestellt.', - ABGESCHLOSSEN = 'Der Vorgang wurde abgeschlossen.', - WIEDEREROEFFNET = 'Der Vorgang wurde wiedereröffnet.', - LOESCHEN_ANFORDERN = 'Für den Vorgang wurde eine Löschanforderung gestellt.', - ENDGUELTIG_LOESCHEN = 'Der Vorgang wurde gelöscht.', - WIEDERVORLAGE_BEARBEITEN_NICHT_MOEGLICH = 'Im Status "Zu löschen" ist die Bearbeitung von Wiedervorlagen nicht möglich.' -} - -export const NO_AKTENZEICHEN: string = 'kein Aktenzeichen zugewiesen'; \ No newline at end of file + ANGENOMMEN = 'Der Vorgang wurde angenommen.', + VERWORFEN = 'Der Vorgang wurde verworfen.', + ZURUECKGEHOLT = 'Der Vorgang wurde zurückgeholt.', + BEARBEITET = 'Der Vorgang wurde in die Bearbeitung übernommen.', + BESCHIEDEN = 'Der Vorgang wurde beschieden.', + ZURUECKGESTELLT = 'Der Vorgang wurde zurückgestellt.', + ABGESCHLOSSEN = 'Der Vorgang wurde abgeschlossen.', + WIEDEREROEFFNET = 'Der Vorgang wurde wiedereröffnet.', + LOESCHEN_ANFORDERN = 'Für den Vorgang wurde eine Löschanforderung gestellt.', + ENDGUELTIG_LOESCHEN = 'Der Vorgang wurde gelöscht.', + WIEDERVORLAGE_BEARBEITEN_NICHT_MOEGLICH = 'Im Status "Zu löschen" ist die Bearbeitung von Wiedervorlagen nicht möglich.', +} + +export const NO_AKTENZEICHEN: string = 'kein Aktenzeichen zugewiesen'; diff --git a/alfa-client/apps/alfa-e2e/src/model/wiedervorlage.ts b/alfa-client/apps/alfa-e2e/src/model/wiedervorlage.ts index 58e4f4c7b325679721f5979e79acb3ad547c08b8..0dc6329e6b56f15348da5bcc238d2b12912ea334 100644 --- a/alfa-client/apps/alfa-e2e/src/model/wiedervorlage.ts +++ b/alfa-client/apps/alfa-e2e/src/model/wiedervorlage.ts @@ -24,14 +24,14 @@ import { DateE2E } from './util'; export class WiedervorlageE2E { - _id: string; - version: string; - vorgangId: string; - createdAt: DateE2E; - createdBy: string; - betreff: string; - beschreibung: string; - frist: string; - done: boolean; - attachments: string[]; -} \ No newline at end of file + _id: string; + version: string; + vorgangId: string; + createdAt: DateE2E; + createdBy: string; + betreff: string; + beschreibung: string; + frist: string; + done: boolean; + attachments: string[]; +} diff --git a/alfa-client/apps/alfa-e2e/src/page-objects/header.po.ts b/alfa-client/apps/alfa-e2e/src/page-objects/header.po.ts index 09bb350d00e2d9ec8d9e8a1ee6889276a531b4b5..89b163cc3bbcb961063794ab11b4cba82933e55a 100644 --- a/alfa-client/apps/alfa-e2e/src/page-objects/header.po.ts +++ b/alfa-client/apps/alfa-e2e/src/page-objects/header.po.ts @@ -27,36 +27,36 @@ import { UserSettingsE2EComponent } from '../components/user-settings/user-setti import { VorgangSearchE2EComponent } from '../components/vorgang/vorgang-search.e2e.component'; export class HeaderE2EComponent { - - private readonly locatorLogo: string = 'alfa-logo'; - private readonly locatorRoot: string = 'header'; - - private readonly helpMenu: HelpMenuE2EComponent = new HelpMenuE2EComponent(); - private readonly userSettings: UserSettingsE2EComponent = new UserSettingsE2EComponent(); - private readonly currentUserProfile: CurrentUserProfileE2EComponent = new CurrentUserProfileE2EComponent(); - private readonly vorgangSearch: VorgangSearchE2EComponent = new VorgangSearchE2EComponent(); - - public getRoot() { - return cy.getTestElement(this.locatorRoot); - } - - public getLogo() { - return cy.getTestElement(this.locatorLogo); - } - - public getVorgangSearch(): VorgangSearchE2EComponent { - return this.vorgangSearch; - } - - public getHelpMenu(): HelpMenuE2EComponent { - return this.helpMenu; - } - - public getUserSettings(): UserSettingsE2EComponent { - return this.userSettings; - } - - public getCurrentUserProfile(): CurrentUserProfileE2EComponent { - return this.currentUserProfile; - } -} \ No newline at end of file + private readonly locatorLogo: string = 'alfa-logo'; + private readonly locatorRoot: string = 'header'; + + private readonly helpMenu: HelpMenuE2EComponent = new HelpMenuE2EComponent(); + private readonly userSettings: UserSettingsE2EComponent = new UserSettingsE2EComponent(); + private readonly currentUserProfile: CurrentUserProfileE2EComponent = + new CurrentUserProfileE2EComponent(); + private readonly vorgangSearch: VorgangSearchE2EComponent = new VorgangSearchE2EComponent(); + + public getRoot() { + return cy.getTestElement(this.locatorRoot); + } + + public getLogo() { + return cy.getTestElement(this.locatorLogo); + } + + public getVorgangSearch(): VorgangSearchE2EComponent { + return this.vorgangSearch; + } + + public getHelpMenu(): HelpMenuE2EComponent { + return this.helpMenu; + } + + public getUserSettings(): UserSettingsE2EComponent { + return this.userSettings; + } + + public getCurrentUserProfile(): CurrentUserProfileE2EComponent { + return this.currentUserProfile; + } +} diff --git a/alfa-client/apps/alfa-e2e/src/page-objects/main.po.ts b/alfa-client/apps/alfa-e2e/src/page-objects/main.po.ts index 4af95b9d93ea3a5890c8734ffad12239159c809c..9bd72f35304a2af24f75b5f12f4d173ef0495b7c 100644 --- a/alfa-client/apps/alfa-e2e/src/page-objects/main.po.ts +++ b/alfa-client/apps/alfa-e2e/src/page-objects/main.po.ts @@ -25,7 +25,10 @@ import { BasicDialogE2EComponent } from '../components/basic-dialog/basic-dialog import { BuildInfoE2EComponent } from '../components/buildinfo/buildinfo.e2e.component'; import { HintE2EComponent } from '../components/hint/hint.component.e2e'; import { NavigationE2EComponent } from '../components/navigation/navigation.e2e.component'; -import { ConnectionTimeoutRetryDialogE2EComponent, ConnectionTimeoutRetryFailDialogE2EComponent } from '../components/ui/connection-timeout-retry-dialog.e2e.component'; +import { + ConnectionTimeoutRetryDialogE2EComponent, + ConnectionTimeoutRetryFailDialogE2EComponent, +} from '../components/ui/connection-timeout-retry-dialog.e2e.component'; import { InternalServerErrorDialogE2EComponent } from '../components/ui/internal-server-error-diaog.e2e.component'; import { SnackBarE2EComponent } from '../components/ui/snackbar.e2e.component'; import { VorgangListE2EComponent } from '../components/vorgang/vorgang-list.e2e.component'; @@ -33,67 +36,70 @@ import { VorgangViewsE2EComponent } from '../components/vorgang/vorgang-views.e2 import { HeaderE2EComponent } from './header.po'; export class MainPage { - private readonly buildInfo: BuildInfoE2EComponent = new BuildInfoE2EComponent(); - private readonly header: HeaderE2EComponent = new HeaderE2EComponent(); - private readonly navigation: NavigationE2EComponent = new NavigationE2EComponent(); - private readonly views: VorgangViewsE2EComponent = new VorgangViewsE2EComponent(); - private readonly snackBar: SnackBarE2EComponent = new SnackBarE2EComponent(); - private readonly vorgangList: VorgangListE2EComponent = new VorgangListE2EComponent(); - private readonly internalServerErrorDialog: InternalServerErrorDialogE2EComponent = new InternalServerErrorDialogE2EComponent(); - private readonly connectionTimeoutRetryDialog: ConnectionTimeoutRetryDialogE2EComponent = new ConnectionTimeoutRetryDialogE2EComponent(); - private readonly connectionTimeoutRetryFailDialog: ConnectionTimeoutRetryFailDialogE2EComponent = new ConnectionTimeoutRetryFailDialogE2EComponent(); - private readonly basicDialog: BasicDialogE2EComponent = new BasicDialogE2EComponent(); - private readonly hint: HintE2EComponent = new HintE2EComponent(); + private readonly buildInfo: BuildInfoE2EComponent = new BuildInfoE2EComponent(); + private readonly header: HeaderE2EComponent = new HeaderE2EComponent(); + private readonly navigation: NavigationE2EComponent = new NavigationE2EComponent(); + private readonly views: VorgangViewsE2EComponent = new VorgangViewsE2EComponent(); + private readonly snackBar: SnackBarE2EComponent = new SnackBarE2EComponent(); + private readonly vorgangList: VorgangListE2EComponent = new VorgangListE2EComponent(); + private readonly internalServerErrorDialog: InternalServerErrorDialogE2EComponent = + new InternalServerErrorDialogE2EComponent(); + private readonly connectionTimeoutRetryDialog: ConnectionTimeoutRetryDialogE2EComponent = + new ConnectionTimeoutRetryDialogE2EComponent(); + private readonly connectionTimeoutRetryFailDialog: ConnectionTimeoutRetryFailDialogE2EComponent = + new ConnectionTimeoutRetryFailDialogE2EComponent(); + private readonly basicDialog: BasicDialogE2EComponent = new BasicDialogE2EComponent(); + private readonly hint: HintE2EComponent = new HintE2EComponent(); - public getBuildInfo(): BuildInfoE2EComponent { - return this.buildInfo; - } + public getBuildInfo(): BuildInfoE2EComponent { + return this.buildInfo; + } - public getHeader(): HeaderE2EComponent { - return this.header; - } + public getHeader(): HeaderE2EComponent { + return this.header; + } - public getNavigation(): NavigationE2EComponent { - return this.navigation; - } + public getNavigation(): NavigationE2EComponent { + return this.navigation; + } - public getViews(): VorgangViewsE2EComponent { - return this.views; - } + public getViews(): VorgangViewsE2EComponent { + return this.views; + } - public getSnackBar(): SnackBarE2EComponent { - return this.snackBar; - } + public getSnackBar(): SnackBarE2EComponent { + return this.snackBar; + } - public getVorgangList(): VorgangListE2EComponent { - return this.vorgangList; - } + public getVorgangList(): VorgangListE2EComponent { + return this.vorgangList; + } - public getInternalServerErrorDialog(): InternalServerErrorDialogE2EComponent { - return this.internalServerErrorDialog; - } + public getInternalServerErrorDialog(): InternalServerErrorDialogE2EComponent { + return this.internalServerErrorDialog; + } - public getConnectionTimeoutRetryDialog(): ConnectionTimeoutRetryDialogE2EComponent { - return this.connectionTimeoutRetryDialog; - } + public getConnectionTimeoutRetryDialog(): ConnectionTimeoutRetryDialogE2EComponent { + return this.connectionTimeoutRetryDialog; + } - public getConnectionTimeoutRetryFailDialog(): ConnectionTimeoutRetryFailDialogE2EComponent { - return this.connectionTimeoutRetryFailDialog; - } + public getConnectionTimeoutRetryFailDialog(): ConnectionTimeoutRetryFailDialogE2EComponent { + return this.connectionTimeoutRetryFailDialog; + } - public getBasicDialog(): BasicDialogE2EComponent { - return this.basicDialog; - } + public getBasicDialog(): BasicDialogE2EComponent { + return this.basicDialog; + } - public getHint(): HintE2EComponent { - return this.hint; - } + public getHint(): HintE2EComponent { + return this.hint; + } } export function waitForSpinnerToDisappear(): boolean { - return cy.getTestElementWithClass('spinner').should('not.exist'); + return cy.getTestElementWithClass('spinner').should('not.exist'); } export function waitforSpinnerToAppear(): void { - // exist(cy.getTestElementWithClass('spinner')); -} \ No newline at end of file + // exist(cy.getTestElementWithClass('spinner')); +} diff --git a/alfa-client/apps/alfa-e2e/src/page-objects/postfach-mail.component.po.ts b/alfa-client/apps/alfa-e2e/src/page-objects/postfach-mail.component.po.ts index a7d10ebb4e964c7385f8371e1f0ee99f62890ff9..8d072a9c8dc43fe7ff5a8a8263e1bdb32ced7e03 100644 --- a/alfa-client/apps/alfa-e2e/src/page-objects/postfach-mail.component.po.ts +++ b/alfa-client/apps/alfa-e2e/src/page-objects/postfach-mail.component.po.ts @@ -26,30 +26,29 @@ import { PostfachMailSubnavigation } from '../components/postfach/postfach-mail- import { PostfachMailListItem } from '../components/postfach/postfach-mail.e2e.component'; export class PostfachMailPage { + private readonly breadcrump: string = 'postfach-breadcrump'; + private readonly root: string = 'postfach-mail-list'; + private readonly downloadButton: string = 'postfach-pdf-export-button'; - private readonly breadcrump: string = 'postfach-breadcrump'; - private readonly root: string = 'postfach-mail-list'; - private readonly downloadButton: string = 'postfach-pdf-export-button'; + private readonly subnavigation: PostfachMailSubnavigation = new PostfachMailSubnavigation(); - private readonly subnavigation: PostfachMailSubnavigation = new PostfachMailSubnavigation(); + getRoot() { + return cy.getTestElement(this.root); + } - getRoot() { - return cy.getTestElement(this.root); - } + getSubnavigation(): PostfachMailSubnavigation { + return this.subnavigation; + } - getSubnavigation(): PostfachMailSubnavigation { - return this.subnavigation; - } + getBreadcrump() { + return cy.getTestElement(this.breadcrump); + } - getBreadcrump() { - return cy.getTestElement(this.breadcrump); - } + getListItem(subject: string): PostfachMailListItem { + return new PostfachMailListItem(subject); + } - getListItem(subject: string): PostfachMailListItem { - return new PostfachMailListItem(subject); - } - - getDownloadButton() { - return cy.getTestElement(this.downloadButton); - } -} \ No newline at end of file + getDownloadButton() { + return cy.getTestElement(this.downloadButton); + } +} diff --git a/alfa-client/apps/alfa-e2e/src/page-objects/vorgang.po.ts b/alfa-client/apps/alfa-e2e/src/page-objects/vorgang.po.ts index 9406612dae20020e11acc418258c02b17a936b79..f99a9e9f9954ffc714f3cbf377c33e6cbc00bbfc 100644 --- a/alfa-client/apps/alfa-e2e/src/page-objects/vorgang.po.ts +++ b/alfa-client/apps/alfa-e2e/src/page-objects/vorgang.po.ts @@ -26,6 +26,7 @@ import { KommentareInVorgangE2EComponent } from '../components/kommentar/komment import { PostfachMailFormularE2EComponent } from '../components/postfach/postfach-mail-formular.e2e.component'; import { PostfachMailE2EComponent } from '../components/postfach/postfach-mail.e2e.component'; import { FixedDialogE2EComponent } from '../components/ui/fixed-dialog.e2e.component'; +import { VorgangAktenzeichenEditE2EComponent } from '../components/vorgang/vorgang-aktenzeichen-edit.e2e.component'; import { AntragstellerE2EComponent } from '../components/vorgang/vorgang-antragsteller.e2e.component'; import { VorgangDetailHeaderE2EComponent } from '../components/vorgang/vorgang-detail-header.e2e.component'; import { VorgangFormularButtonsE2EComponent } from '../components/vorgang/vorgang-formular-buttons.e2e.components'; @@ -36,82 +37,98 @@ import { VorgangSubnavigationE2EComponent } from '../components/vorgang/vorgang- import { WiedervorlagenInVorgangE2EComponent } from '../components/wiedervorlage/wiedervorlagen-in-vorgang.e2e.component'; export class VorgangPage { - private readonly subnavigation: VorgangSubnavigationE2EComponent = new VorgangSubnavigationE2EComponent(); - private readonly vorgangDetailHeader: VorgangDetailHeaderE2EComponent = new VorgangDetailHeaderE2EComponent(); - private readonly formularDatenContainer: VorgangFormularDatenE2EComponent = new VorgangFormularDatenE2EComponent(); - private readonly formularButtons: VorgangFormularButtonsE2EComponent = new VorgangFormularButtonsE2EComponent(); - private readonly moreMenu: VorgangMoreMenuE2EComponent = new VorgangMoreMenuE2EComponent(); - - private readonly wiedervorlagen: WiedervorlagenInVorgangE2EComponent = new WiedervorlagenInVorgangE2EComponent(); - private readonly forwardingContainer: VorgangForwardingE2EComponent = new VorgangForwardingE2EComponent(); - private readonly attachmentContainer: AttachmentContainerE2EComponent = new AttachmentContainerE2EComponent(); - private readonly kommentarContainer: KommentareInVorgangE2EComponent = new KommentareInVorgangE2EComponent(); - private readonly postfachMailContainer: PostfachMailE2EComponent = new PostfachMailE2EComponent(); - private readonly antragstellerContainer: AntragstellerE2EComponent = new AntragstellerE2EComponent(); - - private readonly fixedDialog: FixedDialogE2EComponent = new FixedDialogE2EComponent(); - private readonly postfachMailFormular: PostfachMailFormularE2EComponent = new PostfachMailFormularE2EComponent(); - - private readonly locatorSpinner: string = 'spinner'; - private readonly locatorProgressBar: string = 'progress-bar'; - - public getKommentarContainer(): KommentareInVorgangE2EComponent { - return this.kommentarContainer; - } - - public getForwardingContainer(): VorgangForwardingE2EComponent { - return this.forwardingContainer; - } - - public getSubnavigation(): VorgangSubnavigationE2EComponent { - return this.subnavigation; - } - - public getFormularDatenContainer(): VorgangFormularDatenE2EComponent { - return this.formularDatenContainer; - } - - public getFormularButtons(): VorgangFormularButtonsE2EComponent { - return this.formularButtons; - } - - public getMoreMenu(): VorgangMoreMenuE2EComponent { - return this.moreMenu; - } - - public getAttachmentContainer(): AttachmentContainerE2EComponent { - return this.attachmentContainer; - } - - public getVorgangDetailHeader(): VorgangDetailHeaderE2EComponent { - return this.vorgangDetailHeader; - } - - public getWiedervorlagenContainer(): WiedervorlagenInVorgangE2EComponent { - return this.wiedervorlagen; - } - - public getPostfachMailcontainer(): PostfachMailE2EComponent { - return this.postfachMailContainer; - } - - public getPostfachMailFormular(): PostfachMailFormularE2EComponent { - return this.postfachMailFormular; - } - - public getAntragstellerContainer(): AntragstellerE2EComponent { - return this.antragstellerContainer; - } - - public getProgressBar() { - return cy.getTestElement(this.locatorProgressBar); - } - - public getSpinner() { - return cy.getTestElementWithClass(this.locatorSpinner); - } - - public getFixedDialog(): FixedDialogE2EComponent { - return this.fixedDialog; - } -} \ No newline at end of file + private readonly subnavigation: VorgangSubnavigationE2EComponent = + new VorgangSubnavigationE2EComponent(); + private readonly vorgangDetailHeader: VorgangDetailHeaderE2EComponent = + new VorgangDetailHeaderE2EComponent(); + private readonly formularDatenContainer: VorgangFormularDatenE2EComponent = + new VorgangFormularDatenE2EComponent(); + private readonly formularButtons: VorgangFormularButtonsE2EComponent = + new VorgangFormularButtonsE2EComponent(); + private readonly moreMenu: VorgangMoreMenuE2EComponent = new VorgangMoreMenuE2EComponent(); + private readonly aktenzeichenEditor: VorgangAktenzeichenEditE2EComponent = + new VorgangAktenzeichenEditE2EComponent(); + + private readonly wiedervorlagen: WiedervorlagenInVorgangE2EComponent = + new WiedervorlagenInVorgangE2EComponent(); + private readonly forwardingContainer: VorgangForwardingE2EComponent = + new VorgangForwardingE2EComponent(); + private readonly attachmentContainer: AttachmentContainerE2EComponent = + new AttachmentContainerE2EComponent(); + private readonly kommentarContainer: KommentareInVorgangE2EComponent = + new KommentareInVorgangE2EComponent(); + private readonly postfachMailContainer: PostfachMailE2EComponent = new PostfachMailE2EComponent(); + private readonly antragstellerContainer: AntragstellerE2EComponent = + new AntragstellerE2EComponent(); + + private readonly fixedDialog: FixedDialogE2EComponent = new FixedDialogE2EComponent(); + private readonly postfachMailFormular: PostfachMailFormularE2EComponent = + new PostfachMailFormularE2EComponent(); + + private readonly locatorSpinner: string = 'spinner'; + private readonly locatorProgressBar: string = 'progress-bar'; + + public getKommentarContainer(): KommentareInVorgangE2EComponent { + return this.kommentarContainer; + } + + public getForwardingContainer(): VorgangForwardingE2EComponent { + return this.forwardingContainer; + } + + public getSubnavigation(): VorgangSubnavigationE2EComponent { + return this.subnavigation; + } + + public getFormularDatenContainer(): VorgangFormularDatenE2EComponent { + return this.formularDatenContainer; + } + + public getFormularButtons(): VorgangFormularButtonsE2EComponent { + return this.formularButtons; + } + + public getMoreMenu(): VorgangMoreMenuE2EComponent { + return this.moreMenu; + } + + public getAktenzeichenEditor(): VorgangAktenzeichenEditE2EComponent { + return this.aktenzeichenEditor; + } + + public getAttachmentContainer(): AttachmentContainerE2EComponent { + return this.attachmentContainer; + } + + public getVorgangDetailHeader(): VorgangDetailHeaderE2EComponent { + return this.vorgangDetailHeader; + } + + public getWiedervorlagenContainer(): WiedervorlagenInVorgangE2EComponent { + return this.wiedervorlagen; + } + + public getPostfachMailcontainer(): PostfachMailE2EComponent { + return this.postfachMailContainer; + } + + public getPostfachMailFormular(): PostfachMailFormularE2EComponent { + return this.postfachMailFormular; + } + + public getAntragstellerContainer(): AntragstellerE2EComponent { + return this.antragstellerContainer; + } + + public getProgressBar() { + return cy.getTestElement(this.locatorProgressBar); + } + + public getSpinner() { + return cy.getTestElementWithClass(this.locatorSpinner); + } + + public getFixedDialog(): FixedDialogE2EComponent { + return this.fixedDialog; + } +} diff --git a/alfa-client/apps/alfa-e2e/src/page-objects/wiedervorlage.po.ts b/alfa-client/apps/alfa-e2e/src/page-objects/wiedervorlage.po.ts index 8ff9b87f51410740046979ae283eaaf9bdec24e1..23e3bdc77fa25a04875d6b99e907524489c156aa 100644 --- a/alfa-client/apps/alfa-e2e/src/page-objects/wiedervorlage.po.ts +++ b/alfa-client/apps/alfa-e2e/src/page-objects/wiedervorlage.po.ts @@ -25,19 +25,21 @@ import { WiedervorlageE2EComponent } from '../components/wiedervorlage/wiedervor import { WiedervorlageSubnavigationE2EComponent } from '../components/wiedervorlage/wiedervorlage-subnavigation'; export class WiedervorlagePage { - private readonly subnavigation: WiedervorlageSubnavigationE2EComponent = new WiedervorlageSubnavigationE2EComponent(); - private readonly wiedervorlageContainer: WiedervorlageE2EComponent = new WiedervorlageE2EComponent(); - private readonly locatorWiedervorlagePage: string = 'wiedervorlage-page'; + private readonly subnavigation: WiedervorlageSubnavigationE2EComponent = + new WiedervorlageSubnavigationE2EComponent(); + private readonly wiedervorlageContainer: WiedervorlageE2EComponent = + new WiedervorlageE2EComponent(); + private readonly locatorWiedervorlagePage: string = 'wiedervorlage-page'; - public getRoot() { - return cy.getTestElement(this.locatorWiedervorlagePage); - } + public getRoot() { + return cy.getTestElement(this.locatorWiedervorlagePage); + } - public getSubnavigation(): WiedervorlageSubnavigationE2EComponent { - return this.subnavigation; - } + public getSubnavigation(): WiedervorlageSubnavigationE2EComponent { + return this.subnavigation; + } - public getWiedervorlageContainer(): WiedervorlageE2EComponent { - return this.wiedervorlageContainer; - } + public getWiedervorlageContainer(): WiedervorlageE2EComponent { + return this.wiedervorlageContainer; + } } diff --git a/alfa-client/apps/alfa-e2e/src/support/angular.util.ts b/alfa-client/apps/alfa-e2e/src/support/angular.util.ts index 62fff78dbf333e590f749cf0f51524b60e6fafc9..4cfea18d440c803df4eb711ab82f0b7a808b9e9f 100644 --- a/alfa-client/apps/alfa-e2e/src/support/angular.util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/angular.util.ts @@ -26,55 +26,55 @@ import { containClass, mouseEnter, notContainClass } from './cypress.util'; export const TOGGLE_ELEMENT: string = 'mat-slide-toggle'; enum AngularClassesE2E { - MAT_CHECKED = 'mat-mdc-slide-toggle-checked', - MAT_BUTTONG_TOGGLE_CHECKED = 'mat-button-toggle-checked', - MAT_FOCUSED = 'mat-focused', - CDK_KEYBOARD_FOCUSED = 'cdk-keyboard-focused', - MAT_BADGE_HIDDEN = 'mat-badge-hidden' + MAT_CHECKED = 'mat-mdc-slide-toggle-checked', + MAT_BUTTONG_TOGGLE_CHECKED = 'mat-button-toggle-checked', + MAT_FOCUSED = 'mat-focused', + CDK_KEYBOARD_FOCUSED = 'cdk-keyboard-focused', + MAT_BADGE_HIDDEN = 'mat-badge-hidden', } enum AngularElementE2E { - MAT_FORM_FIELD = 'mat-form-field' + MAT_FORM_FIELD = 'mat-form-field', } export function hasTooltip(element: any, value: string) { - mouseEnter(element); - // element.get('mat-tooltip-component').contains(value); - element.get(`div[title="${value}"]`); + mouseEnter(element); + // element.get('mat-tooltip-component').contains(value); + element.get(`div[title="${value}"]`); } export function isChecked(element: any) { - containClass(element, AngularClassesE2E.MAT_CHECKED); + containClass(element, AngularClassesE2E.MAT_CHECKED); } export function isNotChecked(element: any) { - notContainClass(element, AngularClassesE2E.MAT_CHECKED); + notContainClass(element, AngularClassesE2E.MAT_CHECKED); } export function isButtonToggleChecked(element: any) { - containClass(element, AngularClassesE2E.MAT_BUTTONG_TOGGLE_CHECKED); + containClass(element, AngularClassesE2E.MAT_BUTTONG_TOGGLE_CHECKED); } export function isButtonToggleNotChecked(element: any) { - notContainClass(element, AngularClassesE2E.MAT_BUTTONG_TOGGLE_CHECKED); + notContainClass(element, AngularClassesE2E.MAT_BUTTONG_TOGGLE_CHECKED); } export function getFormField(element: any) { - return element.find(AngularElementE2E.MAT_FORM_FIELD); + return element.find(AngularElementE2E.MAT_FORM_FIELD); } export function isMatFocused(element: any) { - containClass(element, AngularClassesE2E.MAT_FOCUSED); + containClass(element, AngularClassesE2E.MAT_FOCUSED); } export function isKeyboardFocused(element: any) { - containClass(element, AngularClassesE2E.CDK_KEYBOARD_FOCUSED); + containClass(element, AngularClassesE2E.CDK_KEYBOARD_FOCUSED); } export function expectIconWithoutBadge(element: any): void { - containClass(element, AngularClassesE2E.MAT_BADGE_HIDDEN) + containClass(element, AngularClassesE2E.MAT_BADGE_HIDDEN); } export function expectIconWithBadge(element: any): void { - notContainClass(element, AngularClassesE2E.MAT_BADGE_HIDDEN) + notContainClass(element, AngularClassesE2E.MAT_BADGE_HIDDEN); } diff --git a/alfa-client/apps/alfa-e2e/src/support/app-util.ts b/alfa-client/apps/alfa-e2e/src/support/app-util.ts index 6c2b77a6f0859fec1ffe2b72a806e10eb2b361f7..d5a480c1461cc95c689024f65cdbeacf9777a02c 100644 --- a/alfa-client/apps/alfa-e2e/src/support/app-util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/app-util.ts @@ -27,5 +27,5 @@ import { App } from '../model/app'; const appFixture: App = require('../fixtures/main.json'); export function getApp(): App { - return appFixture; -} \ No newline at end of file + return appFixture; +} diff --git a/alfa-client/apps/alfa-e2e/src/support/binary-file-util.ts b/alfa-client/apps/alfa-e2e/src/support/binary-file-util.ts index 92bafc677492ed674078633fa28a4257d30f7f41..5bc8f9bd966c60d4baece9bcddafee3544334595 100644 --- a/alfa-client/apps/alfa-e2e/src/support/binary-file-util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/binary-file-util.ts @@ -39,29 +39,29 @@ const pdfFile = require('../fixtures/grid-fs/pdf/file.json'); const pdfChunk = require('../fixtures/grid-fs/pdf/chunk.json'); export function createXmlRepresentation(): FileDataE2E { - return xmlRepresentation; + return xmlRepresentation; } export function createJpgAttachment(): FileDataE2E { - return jpgAttachment; + return jpgAttachment; } export function createPdfAttachment(): FileDataE2E { - return pdfAttachment; + return pdfAttachment; } export function createXmlGridFsData(): GridFsFileDataE2E { - return { file: xmlFile, chunks: [xmlChunk] }; + return { file: xmlFile, chunks: [xmlChunk] }; } export function createJpgGridFsData(): GridFsFileDataE2E { - return { file: jpgFile, chunks: [jpgChunk] }; + return { file: jpgFile, chunks: [jpgChunk] }; } export function createPdfGridFsData(): GridFsFileDataE2E { - return { file: pdfFile, chunks: [pdfChunk] }; + return { file: pdfFile, chunks: [pdfChunk] }; } export function initGridFs(gridFsData: GridFsFileDataE2E[]): void { - initGridFsData(gridFsData); -} \ No newline at end of file + initGridFsData(gridFsData); +} diff --git a/alfa-client/apps/alfa-e2e/src/support/command-util.ts b/alfa-client/apps/alfa-e2e/src/support/command-util.ts index f7ef896b3eac6dae35a87597d64178944a7ac614..32011c762244e01ee88c844132c41580167c36b0 100644 --- a/alfa-client/apps/alfa-e2e/src/support/command-util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/command-util.ts @@ -28,22 +28,26 @@ import { getUserSabineInternalId } from './user-util'; const commandFixture: CommandE2E = require('../fixtures/command/command.json'); export function createCommand(): CommandE2E { - return { ...commandFixture, createdBy: getUserSabineInternalId() }; + return { ...commandFixture, createdBy: getUserSabineInternalId() }; } -export function buildCommand(order: CommandOrderE2E, vorgangId: string, relationId: string): CommandE2E { - return { - ...createCommand(), - vorgangId, - relationId, - order - }; +export function buildCommand( + order: CommandOrderE2E, + vorgangId: string, + relationId: string, +): CommandE2E { + return { + ...createCommand(), + vorgangId, + relationId, + order, + }; } export function initCommand(command: CommandE2E): void { - initCommands([command]); + initCommands([command]); } export function initCommands(commands: CommandE2E[]): void { - initCommandData(commands); -} \ No newline at end of file + initCommandData(commands); +} diff --git a/alfa-client/apps/alfa-e2e/src/support/commands.ts b/alfa-client/apps/alfa-e2e/src/support/commands.ts index 6dbcd93923749ba5a76cad0ab5a68df6151b0889..77cfdd7f9670cc0fe2a96a3d16e45644d8d63667 100644 --- a/alfa-client/apps/alfa-e2e/src/support/commands.ts +++ b/alfa-client/apps/alfa-e2e/src/support/commands.ts @@ -1,4 +1,3 @@ - /* * Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den * Ministerpräsidenten des Landes Schleswig-Holstein @@ -23,12 +22,12 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ enum HttpMethod { - POST = 'POST', - GET = 'GET' + POST = 'POST', + GET = 'GET', } interface HttpHeader { - [headerKey: string]: string + [headerKey: string]: string; } const DATA_TEST_ID: string = 'data-test-id'; @@ -38,202 +37,205 @@ const ACCES_TOKEN: string = 'access_token'; const ID_TOKEN: string = 'id_token'; enum Header { - CONTENT_TYPE = 'Content-Type', - AUTHORIZATION = 'Authorization' + CONTENT_TYPE = 'Content-Type', + AUTHORIZATION = 'Authorization', } const CYPRESS_CONFIG_BASE_URL: unknown = 'baseUrl'; enum CypressEnv { - KEYCLOAK_CLIENT = 'keycloakClient', - KEYCLOAK_REALM = 'keycloakRealm', - KEYCLOAK_URL = 'keycloakUrl', - SEARCH = 'search' + KEYCLOAK_CLIENT = 'keycloakClient', + KEYCLOAK_REALM = 'keycloakRealm', + KEYCLOAK_URL = 'keycloakUrl', + SEARCH = 'search', } const CONTENT_TYPE_HEADER_VALUE: string = 'application/x-www-form-urlencoded'; interface SearchIndex { - vorgangId: string, - vorgangName: string, - vorgangNummer: string, - createdAt: string, - antragstellerName: string, - antragstellerVorname: string, - status: string, - organisationseinheitenId: string, - aktenzeichen: string, - assignedTo: string, - _class: string + vorgangId: string; + vorgangName: string; + vorgangNummer: string; + createdAt: string; + antragstellerName: string; + antragstellerVorname: string; + status: string; + organisationseinheitenId: string; + aktenzeichen: string; + assignedTo: string; + _class: string; } const SEARCH_INDEX_CLASS: string = 'de.ozgcloud.vorgang.common.search.IndexedVorgang'; declare namespace Cypress { - interface Chainable<Subject> { - getTestElementWithOid(oid: string, ...args); - getTestElement(selector: string, ...args); - getTestElementWithClass(selector: string, ...args); - findTestElementWithClass(selector: string, ...args); - findElement(selector: string); - login(user, password); - logout(); - getUserInfo(); - addVorgangToSearchIndex(vorgang); - removeAllDocumentsFromSearchIndex(); - } + interface Chainable<Subject> { + getTestElementWithOid(oid: string, ...args); + getTestElement(selector: string, ...args); + getTestElementWithClass(selector: string, ...args); + findTestElementWithClass(selector: string, ...args); + findElement(selector: string); + login(user, password); + logout(); + getUserInfo(); + addVorgangToSearchIndex(vorgang); + removeAllDocumentsFromSearchIndex(); + } } - Cypress.Commands.add('getTestElement', (selector, ...args) => { - return cy.get(`[${DATA_TEST_ID}~="${selector}"]`, ...args) -}) + return cy.get(`[${DATA_TEST_ID}~="${selector}"]`, ...args); +}); Cypress.Commands.add('getTestElementWithClass', (selector, ...args) => { - return cy.get(`[${DATA_TEST_CLASS}="${selector}"]`, ...args) -}) + return cy.get(`[${DATA_TEST_CLASS}="${selector}"]`, ...args); +}); Cypress.Commands.add('getTestElementWithOid', (oid, ...args) => { - return cy.getTestElement(oid, ...args) -}) + return cy.getTestElement(oid, ...args); +}); -Cypress.Commands.add('findTestElementWithClass', { prevSubject: true }, (subject: any, selector) => { - return subject.find(`[${DATA_TEST_CLASS}="${selector}"]`) -}) +Cypress.Commands.add( + 'findTestElementWithClass', + { prevSubject: true }, + (subject: any, selector) => { + return subject.find(`[${DATA_TEST_CLASS}="${selector}"]`); + }, +); Cypress.Commands.add('findElement', { prevSubject: true }, (subject: any, selector) => { - return subject.find(selector); -}) + return subject.find(selector); +}); Cypress.Commands.add('login', (user: string, password: string) => { - cy.session(user, () => { - cy.request(buildLoginRequest(user, password)).then(response => handleLoginResponse(response)); - }); -}) + cy.session(user, () => { + cy.request(buildLoginRequest(user, password)).then((response) => handleLoginResponse(response)); + }); +}); function buildLoginRequest(user: string, password: string): any { - return { - method: HttpMethod.POST, - followRedirect: false, - url: `${getKeycloakBaseRealmUrl()}/token`, - headers: { - [Header.CONTENT_TYPE]: CONTENT_TYPE_HEADER_VALUE - }, - body: buildLoginRequestBody(user, password) - } + return { + method: HttpMethod.POST, + followRedirect: false, + url: `${getKeycloakBaseRealmUrl()}/token`, + headers: { + [Header.CONTENT_TYPE]: CONTENT_TYPE_HEADER_VALUE, + }, + body: buildLoginRequestBody(user, password), + }; } function buildLoginRequestBody(user: string, password: string): any { - return { - client_id: Cypress.env(CypressEnv.KEYCLOAK_CLIENT), - username: user, - password: password, - grant_type: 'password', - redirect_uri: Cypress.config(CYPRESS_CONFIG_BASE_URL), - response_mode: 'fragment', - response_type: 'code', - scope: 'openid' - } + return { + client_id: Cypress.env(CypressEnv.KEYCLOAK_CLIENT), + username: user, + password: password, + grant_type: 'password', + redirect_uri: Cypress.config(CYPRESS_CONFIG_BASE_URL), + response_mode: 'fragment', + response_type: 'code', + scope: 'openid', + }; } function handleLoginResponse(response): void { - const authorization: any = `bearer ${response.body.access_token}`; - cy.visit('', authorization); + const authorization: any = `bearer ${response.body.access_token}`; + cy.visit('', authorization); - window.sessionStorage.setItem(ACCES_TOKEN, response.body.access_token); - window.sessionStorage.setItem(ID_TOKEN, response.body.id_token); + window.sessionStorage.setItem(ACCES_TOKEN, response.body.access_token); + window.sessionStorage.setItem(ID_TOKEN, response.body.id_token); - cy.setCookie('XSRF-TOKEN', response.body.session_state); + cy.setCookie('XSRF-TOKEN', response.body.session_state); } Cypress.Commands.add('getUserInfo', () => { - return cy.request({ - method: HttpMethod.GET, - url: `${getKeycloakBaseRealmUrl()}/userinfo`, - headers: { - [Header.AUTHORIZATION]: `bearer ${window.sessionStorage.getItem(ACCES_TOKEN)}` - } - }); -}) + return cy.request({ + method: HttpMethod.GET, + url: `${getKeycloakBaseRealmUrl()}/userinfo`, + headers: { + [Header.AUTHORIZATION]: `bearer ${window.sessionStorage.getItem(ACCES_TOKEN)}`, + }, + }); +}); Cypress.Commands.add('logout', () => { - cy.request({ - method: HttpMethod.GET, - url: `${getKeycloakBaseRealmUrl()}/logout`, - headers: { - [Header.CONTENT_TYPE]: CONTENT_TYPE_HEADER_VALUE - }, - body: { - refresh_token: window.sessionStorage.getItem(ID_TOKEN) - }, - failOnStatusCode: false - }).then(() => { - window.sessionStorage.clear(); - - cy.visit(''); - }); -}) + cy.request({ + method: HttpMethod.GET, + url: `${getKeycloakBaseRealmUrl()}/logout`, + headers: { + [Header.CONTENT_TYPE]: CONTENT_TYPE_HEADER_VALUE, + }, + body: { + refresh_token: window.sessionStorage.getItem(ID_TOKEN), + }, + failOnStatusCode: false, + }).then(() => { + window.sessionStorage.clear(); + + cy.visit(''); + }); +}); function getKeycloakBaseRealmUrl(): string { - return `${Cypress.env(CypressEnv.KEYCLOAK_URL)}realms/${Cypress.env(CypressEnv.KEYCLOAK_REALM)}/protocol/openid-connect`; + return `${Cypress.env(CypressEnv.KEYCLOAK_URL)}realms/${Cypress.env(CypressEnv.KEYCLOAK_REALM)}/protocol/openid-connect`; } Cypress.Commands.add('addVorgangToSearchIndex', (vorgang) => { - cy.request({ - method: HttpMethod.POST, - url: `${buildSearchIndexPostUrl()}/_doc/${vorgang._id.$oid}`, - headers: buildAuthorizationHeader(), - body: buildSearchIndexBody(vorgang) - }); -}) + cy.request({ + method: HttpMethod.POST, + url: `${buildSearchIndexPostUrl()}/_doc/${vorgang._id.$oid}`, + headers: buildAuthorizationHeader(), + body: buildSearchIndexBody(vorgang), + }); +}); function buildSearchIndexBody(vorgang: any): SearchIndex { - return { - vorgangId: vorgang._id.$oid, - vorgangName: vorgang.name, - vorgangNummer: vorgang.nummer, - createdAt: vorgang.createdAt.$date, - antragstellerName: vorgang.eingangs[0].antragsteller.nachname, - antragstellerVorname: vorgang.eingangs[0].antragsteller.vorname, - status: vorgang.status, - organisationseinheitenId: vorgang.eingangs[0].zustaendigeStelle.organisationseinheitenId, - aktenzeichen: vorgang.aktenzeichen, - assignedTo: vorgang.assignedTo, - _class: SEARCH_INDEX_CLASS, - }; + return { + vorgangId: vorgang._id.$oid, + vorgangName: vorgang.name, + vorgangNummer: vorgang.nummer, + createdAt: vorgang.createdAt.$date, + antragstellerName: vorgang.eingangs[0].antragsteller.nachname, + antragstellerVorname: vorgang.eingangs[0].antragsteller.vorname, + status: vorgang.status, + organisationseinheitenId: vorgang.eingangs[0].zustaendigeStelle.organisationseinheitenId, + aktenzeichen: vorgang.aktenzeichen, + assignedTo: vorgang.assignedTo, + _class: SEARCH_INDEX_CLASS, + }; } Cypress.Commands.add('removeAllDocumentsFromSearchIndex', () => { - cy.request({ - method: HttpMethod.POST, - url: `${buildSearchIndexPostUrl()}/_delete_by_query`, - headers: buildAuthorizationHeader(), - body: buildSearchIndexRemoveAllBody() - }); -}) + cy.request({ + method: HttpMethod.POST, + url: `${buildSearchIndexPostUrl()}/_delete_by_query`, + headers: buildAuthorizationHeader(), + body: buildSearchIndexRemoveAllBody(), + }); +}); function buildSearchIndexPostUrl(): string { - const searchEnv: string = getSearchEnv(); - return `${searchEnv['url']}/${searchEnv['index']}`; + const searchEnv: string = getSearchEnv(); + return `${searchEnv['url']}/${searchEnv['index']}`; } function buildAuthorizationHeader(): HttpHeader { - return { [Header.AUTHORIZATION]: `Basic ${buildToken()}` }; + return { [Header.AUTHORIZATION]: `Basic ${buildToken()}` }; } function buildToken(): string { - const searchEnv: string = getSearchEnv(); - return btoa(`${searchEnv['user']}:${searchEnv['password']}`); + const searchEnv: string = getSearchEnv(); + return btoa(`${searchEnv['user']}:${searchEnv['password']}`); } function getSearchEnv(): string { - return Cypress.env(CypressEnv.SEARCH); + return Cypress.env(CypressEnv.SEARCH); } function buildSearchIndexRemoveAllBody(): any { - return { - 'query': { - 'match_all': {} - } - }; -} \ No newline at end of file + return { + query: { + match_all: {}, + }, + }; +} diff --git a/alfa-client/apps/alfa-e2e/src/support/cypress-helper.ts b/alfa-client/apps/alfa-e2e/src/support/cypress-helper.ts index 7a926edfbbaf1a0b45979a7d5bd8527ff3d2a3af..9fe9c92d8102f2c3a7efdbe364e7b1f23decf331 100644 --- a/alfa-client/apps/alfa-e2e/src/support/cypress-helper.ts +++ b/alfa-client/apps/alfa-e2e/src/support/cypress-helper.ts @@ -29,158 +29,168 @@ import { VorgangE2E } from '../model/vorgang'; import { VorgangAttachedItemE2E } from '../model/vorgang-attached-item'; enum CypressTasks { - DROP_COLLECTIONS = 'dropCollections', - DROP_USER_MANAGER_COLLECTIONS = 'dropUserManagerCollections', - INIT_COMMAND_DATA = 'initCommandData', - INIT_GRID_FS_FILE_DATA = 'initGridFsFileData', - INIT_GRID_FS_CHUNK_DATA = 'initGridFsChunkData', - INIT_VORGANG_DATA = 'initVorgangData', - INIT_VORGANG_ATTACHED_ITEM_DATA = 'initVorgangAttachedItemData', - INIT_USERMANAGER_DATA = 'initUsermanagerData', - COUNT_FILES = 'countFiles', - DELETE_FOLDER = 'deleteFolder' + DROP_COLLECTIONS = 'dropCollections', + DROP_USER_MANAGER_COLLECTIONS = 'dropUserManagerCollections', + INIT_COMMAND_DATA = 'initCommandData', + INIT_GRID_FS_FILE_DATA = 'initGridFsFileData', + INIT_GRID_FS_CHUNK_DATA = 'initGridFsChunkData', + INIT_VORGANG_DATA = 'initVorgangData', + INIT_VORGANG_ATTACHED_ITEM_DATA = 'initVorgangAttachedItemData', + INIT_USERMANAGER_DATA = 'initUsermanagerData', + COUNT_FILES = 'countFiles', + DELETE_FOLDER = 'deleteFolder', } enum MongoCollections { - COMMAND = 'command', - FS_CHUNKS = 'fs.chunks', - FS_FILES = 'fs.files', - VORGANG = 'vorgang', - VORGANG_ATTACHED_ITEM = 'vorgangAttachedItem', - USER = "User" + COMMAND = 'command', + FS_CHUNKS = 'fs.chunks', + FS_FILES = 'fs.files', + VORGANG = 'vorgang', + VORGANG_ATTACHED_ITEM = 'vorgangAttachedItem', + USER = 'User', } const DOWNLOAD_FOLDER: string = 'cypress/downloads'; export function login(userJsonPath: string): void { - cy.fixture(userJsonPath).then(user => { - cy.login(user.name, user.password); - }) + cy.fixture(userJsonPath).then((user) => { + cy.login(user.name, user.password); + }); } export function visitUrl(url: string): void { - cy.visit(url); + cy.visit(url); } export function initCommandData(data: CommandE2E[]): void { - cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.COMMAND]); - cy.task(CypressTasks.INIT_COMMAND_DATA, { collection: MongoCollections.COMMAND, data }); + cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.COMMAND]); + cy.task(CypressTasks.INIT_COMMAND_DATA, { collection: MongoCollections.COMMAND, data }); } export function initGridFsData(data: GridFsFileDataE2E[]): void { - const files: GridFsFileE2E[] = []; - let chunks: GridFsChunkE2E[] = []; + const files: GridFsFileE2E[] = []; + let chunks: GridFsChunkE2E[] = []; - data.forEach(singleData => { - files.push(singleData.file); - chunks = chunks.concat(singleData.chunks); - }) + data.forEach((singleData) => { + files.push(singleData.file); + chunks = chunks.concat(singleData.chunks); + }); - initGridFsFileData(files); - initGridFsChunkData(chunks); + initGridFsFileData(files); + initGridFsChunkData(chunks); } function initGridFsFileData(data: GridFsFileE2E[]): void { - cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.FS_FILES]); - cy.task(CypressTasks.INIT_GRID_FS_FILE_DATA, { collection: MongoCollections.FS_FILES, data }); + cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.FS_FILES]); + cy.task(CypressTasks.INIT_GRID_FS_FILE_DATA, { collection: MongoCollections.FS_FILES, data }); } function initGridFsChunkData(data: GridFsChunkE2E[]): void { - cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.FS_CHUNKS]); - cy.task(CypressTasks.INIT_GRID_FS_CHUNK_DATA, { collection: MongoCollections.FS_CHUNKS, data }); + cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.FS_CHUNKS]); + cy.task(CypressTasks.INIT_GRID_FS_CHUNK_DATA, { collection: MongoCollections.FS_CHUNKS, data }); } export function initVorgangAttachedItemData(data: VorgangAttachedItemE2E[]): void { - cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.VORGANG_ATTACHED_ITEM]); - cy.task(CypressTasks.INIT_VORGANG_ATTACHED_ITEM_DATA, { collection: MongoCollections.VORGANG_ATTACHED_ITEM, data }); + cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.VORGANG_ATTACHED_ITEM]); + cy.task(CypressTasks.INIT_VORGANG_ATTACHED_ITEM_DATA, { + collection: MongoCollections.VORGANG_ATTACHED_ITEM, + data, + }); } export function initVorgangData(data: VorgangE2E[]): void { - cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.VORGANG]); - cy.task(CypressTasks.INIT_VORGANG_DATA, { collection: MongoCollections.VORGANG, data }); + cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.VORGANG]); + cy.task(CypressTasks.INIT_VORGANG_DATA, { collection: MongoCollections.VORGANG, data }); } export function initSearchIndexData(vorgaenge: VorgangE2E[]): void { - vorgaenge.forEach(vorgang => cy.addVorgangToSearchIndex(vorgang)) + vorgaenge.forEach((vorgang) => cy.addVorgangToSearchIndex(vorgang)); } -export function dropSearchIndex(){ - cy.removeAllDocumentsFromSearchIndex(); +export function dropSearchIndex() { + cy.removeAllDocumentsFromSearchIndex(); } export function initUsermanagerData(data: UsermanagerUserE2E[]): void { - cy.task(CypressTasks.DROP_USER_MANAGER_COLLECTIONS, [MongoCollections.USER]); - cy.task(CypressTasks.INIT_USERMANAGER_DATA, { collection: MongoCollections.USER, data }); + cy.task(CypressTasks.DROP_USER_MANAGER_COLLECTIONS, [MongoCollections.USER]); + cy.task(CypressTasks.INIT_USERMANAGER_DATA, { collection: MongoCollections.USER, data }); } export function dropCollections() { - cy.task(CypressTasks.DROP_COLLECTIONS, [MongoCollections.COMMAND, MongoCollections.VORGANG, MongoCollections.VORGANG_ATTACHED_ITEM, MongoCollections.FS_FILES, MongoCollections.FS_CHUNKS]); - cy.task(CypressTasks.DROP_USER_MANAGER_COLLECTIONS, [MongoCollections.USER]); + cy.task(CypressTasks.DROP_COLLECTIONS, [ + MongoCollections.COMMAND, + MongoCollections.VORGANG, + MongoCollections.VORGANG_ATTACHED_ITEM, + MongoCollections.FS_FILES, + MongoCollections.FS_CHUNKS, + ]); + cy.task(CypressTasks.DROP_USER_MANAGER_COLLECTIONS, [MongoCollections.USER]); } export function countDownloadFiles(): Cypress.Chainable<number> { - return cy.task(CypressTasks.COUNT_FILES, DOWNLOAD_FOLDER); + return cy.task(CypressTasks.COUNT_FILES, DOWNLOAD_FOLDER); } export function deleteDownloadFolder(): void { - cy.task(CypressTasks.DELETE_FOLDER, DOWNLOAD_FOLDER); + cy.task(CypressTasks.DELETE_FOLDER, DOWNLOAD_FOLDER); } export function scrollToWindowBottom(): void { - cy.window().scrollTo('bottom'); + cy.window().scrollTo('bottom'); } export function intercept(method: string, url: string): Cypress.Chainable<null> { - return cy.intercept(method, url); + return cy.intercept(method, url); } -export function interceptWithResponse(method, url: RouteMatcher, response: RouteHandler): Cypress.Chainable<null> { - return cy.intercept(method, url, response); +export function interceptWithResponse( + method, + url: RouteMatcher, + response: RouteHandler, +): Cypress.Chainable<null> { + return cy.intercept(method, url, response); } export function waitOfInterceptor(interceptor: string): Cypress.Chainable<Interception> { - return cy.wait('@' + interceptor); + return cy.wait('@' + interceptor); } export function getTestElement(value: string) { - return cy.getTestElement(value); + return cy.getTestElement(value); } export function getElement(value: string) { - return cy.get(value); + return cy.get(value); } export function urlShouldInclude(text: string) { - return cy.url().should('include', text); + return cy.url().should('include', text); } //TODO: anders loesen -> bad practice export function wait(ms: number): void { - cy.wait(ms); + cy.wait(ms); } // export function reload(): void { - cy.reload(); + cy.reload(); } export function readFileFromDownloads(fileName: string) { - return cy.readFile(`${DOWNLOAD_FOLDER}/${fileName}`); + return cy.readFile(`${DOWNLOAD_FOLDER}/${fileName}`); } export function pressTab(): void { - cy.realPress('Tab'); + cy.realPress('Tab'); } - //Config export function getBaseUrl(): string { - return Cypress.config().baseUrl; + return Cypress.config().baseUrl; } - - //Env export function getCypressEnv(value: string) { - return Cypress.env(value); -} \ No newline at end of file + return Cypress.env(value); +} diff --git a/alfa-client/apps/alfa-e2e/src/support/cypress-tasks.ts b/alfa-client/apps/alfa-e2e/src/support/cypress-tasks.ts index b8a1bac27dbf39c722b3c2e268d4ef58780c6e54..cff6fc057d5541894186b255e02f55a1205aad9b 100644 --- a/alfa-client/apps/alfa-e2e/src/support/cypress-tasks.ts +++ b/alfa-client/apps/alfa-e2e/src/support/cypress-tasks.ts @@ -5,329 +5,336 @@ const fs = require('fs'); const Binary = require('mongodb').Binary; module.exports = (on: any, config: any) => { - on('task', { - initCommandData({collection, data}) { - console.log('initCommandData'); - insertIntoDatabase(config, collection, parseCommandData(data)); - return 0; - }, - initGridFsFileData({collection, data}) { - console.log('initGridFsFileData'); - insertIntoDatabase(config, collection, parseGridFsFileData(data)); - return 0; - }, - initGridFsChunkData({collection, data}) { - console.log('initGridFsChunkData'); - insertIntoDatabase(config, collection, parseGridFsChunkData(data)); - return 0; - }, - initVorgangData({collection, data}) { - console.log('initVorgangData'); - insertIntoDatabase(config, collection, parseVorgangData(data)); - return 0; - }, - initVorgangAttachedItemData({collection, data}) { - console.log('initVorgangAttachedItemData'); - insertIntoDatabase(config, collection, parseVorgangAttachedItemData(data)); - return 0; - }, - initUsermanagerData({collection, data}) { - console.log('initUsermanagerData'); - insertIntoUserManagerDatabase(config, collection, parseUserData(data)); - return 0; - }, - dropCollections(collections) { - console.log('dropCollections: ', collections); - dropCollectionsFromDatabase(config, collections); - return 0; - }, - dropUserManagerCollections(collections) { - console.log('dropUserManagerCollections: ', collections); - dropUserManagerCollectionsFromDatabase(config, collections); - return 0; - }, - countFiles(folderName:string) { - console.log('counting files in folder %s', folderName); - return countFiles(folderName); - }, - deleteFolder(folderName:string) { - console.log('deleting folder %s', folderName); - deleteFolder(folderName); - return 0; - }, - }); - - // Workaround für Angular 13 und Cypress mit Webpack 4, - // Siehe https://github.com/cypress-io/cypress/issues/19066#issuecomment-1012055705 - // Entfernen, sobald Cypress Webpack 5 nutzt - https://github.com/cypress-io/cypress/issues/19555 - // Ursache: Angular linker needed to link partial-ivy code, - // see https://angular.io/guide/creating-libraries#consuming-partial-ivy-code-outside-the-angular-cli - // Fehlerbild: - // - Anwendung läuft im Browser, aber nicht in Cypress. - // - Fehlermeldung in Cypress: The injectable 'SystemDateTimeProvider' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available. - // Lösung: - // - NPM-Paket identifizieren, dass "SystemDateTimeProvider" enthält. - // - NPM-Paket im "test" Attribut unten hinzufügen. - const webpackPreprocessor = require('@cypress/webpack-batteries-included-preprocessor'); - const webpackOptions = webpackPreprocessor.defaultOptions.webpackOptions; - - webpackOptions.module.rules.unshift({ - test: /[/\\](@angular|@ngxp|angular-oauth2-oidc)[/\\].+\.m?js$/, - resolve: { - fullySpecified: false, - }, - use: { - loader: 'babel-loader', - options: { - plugins: ['@angular/compiler-cli/linker/babel'], - compact: false, - cacheDirectory: true - } - } - }); - - on('file:preprocessor', webpackPreprocessor({ - webpackOptions: webpackOptions, - typescript: require.resolve('typescript') - })); - - return config; - // Ende - Workaround für Angular 13 und Cypress mit Webpack 4 -} + on('task', { + initCommandData({ collection, data }) { + console.log('initCommandData'); + insertIntoDatabase(config, collection, parseCommandData(data)); + return 0; + }, + initGridFsFileData({ collection, data }) { + console.log('initGridFsFileData'); + insertIntoDatabase(config, collection, parseGridFsFileData(data)); + return 0; + }, + initGridFsChunkData({ collection, data }) { + console.log('initGridFsChunkData'); + insertIntoDatabase(config, collection, parseGridFsChunkData(data)); + return 0; + }, + initVorgangData({ collection, data }) { + console.log('initVorgangData'); + insertIntoDatabase(config, collection, parseVorgangData(data)); + return 0; + }, + initVorgangAttachedItemData({ collection, data }) { + console.log('initVorgangAttachedItemData'); + insertIntoDatabase(config, collection, parseVorgangAttachedItemData(data)); + return 0; + }, + initUsermanagerData({ collection, data }) { + console.log('initUsermanagerData'); + insertIntoUserManagerDatabase(config, collection, parseUserData(data)); + return 0; + }, + dropCollections(collections) { + console.log('dropCollections: ', collections); + dropCollectionsFromDatabase(config, collections); + return 0; + }, + dropUserManagerCollections(collections) { + console.log('dropUserManagerCollections: ', collections); + dropUserManagerCollectionsFromDatabase(config, collections); + return 0; + }, + countFiles(folderName: string) { + console.log('counting files in folder %s', folderName); + return countFiles(folderName); + }, + deleteFolder(folderName: string) { + console.log('deleting folder %s', folderName); + deleteFolder(folderName); + return 0; + }, + }); + + // Workaround für Angular 13 und Cypress mit Webpack 4, + // Siehe https://github.com/cypress-io/cypress/issues/19066#issuecomment-1012055705 + // Entfernen, sobald Cypress Webpack 5 nutzt - https://github.com/cypress-io/cypress/issues/19555 + // Ursache: Angular linker needed to link partial-ivy code, + // see https://angular.io/guide/creating-libraries#consuming-partial-ivy-code-outside-the-angular-cli + // Fehlerbild: + // - Anwendung läuft im Browser, aber nicht in Cypress. + // - Fehlermeldung in Cypress: The injectable 'SystemDateTimeProvider' needs to be compiled using the JIT compiler, but '@angular/compiler' is not available. + // Lösung: + // - NPM-Paket identifizieren, dass "SystemDateTimeProvider" enthält. + // - NPM-Paket im "test" Attribut unten hinzufügen. + const webpackPreprocessor = require('@cypress/webpack-batteries-included-preprocessor'); + const webpackOptions = webpackPreprocessor.defaultOptions.webpackOptions; + + webpackOptions.module.rules.unshift({ + test: /[/\\](@angular|@ngxp|angular-oauth2-oidc)[/\\].+\.m?js$/, + resolve: { + fullySpecified: false, + }, + use: { + loader: 'babel-loader', + options: { + plugins: ['@angular/compiler-cli/linker/babel'], + compact: false, + cacheDirectory: true, + }, + }, + }); + + on( + 'file:preprocessor', + webpackPreprocessor({ + webpackOptions: webpackOptions, + typescript: require.resolve('typescript'), + }), + ); + + return config; + // Ende - Workaround für Angular 13 und Cypress mit Webpack 4 +}; function parseCommandData(commands) { - commands.forEach(command => parseCommand(command)) - return commands; + commands.forEach((command) => parseCommand(command)); + return commands; } function parseCommand(command) { - command.createdAt = createDate(command.createdAt); - if(command.finishedAt){ - command.finishedAt = createDate(command.finishedAt); - } - command.relationVersion = createNumberLong(command.relationVersion); + command.createdAt = createDate(command.createdAt); + if (command.finishedAt) { + command.finishedAt = createDate(command.finishedAt); + } + command.relationVersion = createNumberLong(command.relationVersion); } function parseGridFsFileData(gridFsFiles) { - gridFsFiles.forEach(gridFsFile => parseGridFsFile(gridFsFile)) - return gridFsFiles; + gridFsFiles.forEach((gridFsFile) => parseGridFsFile(gridFsFile)); + return gridFsFiles; } function parseGridFsFile(gridFsFile) { - gridFsFile._id = createObjectId(gridFsFile); - gridFsFile.length = createNumberLong(gridFsFile.length); - gridFsFile.uploadDate = createDate(gridFsFile.uploadDate); + gridFsFile._id = createObjectId(gridFsFile); + gridFsFile.length = createNumberLong(gridFsFile.length); + gridFsFile.uploadDate = createDate(gridFsFile.uploadDate); } function parseGridFsChunkData(gridFsChunks) { - gridFsChunks.forEach(gridFsChunk => parseGridFsChunk(gridFsChunk)); - return gridFsChunks; + gridFsChunks.forEach((gridFsChunk) => parseGridFsChunk(gridFsChunk)); + return gridFsChunks; } function parseGridFsChunk(gridFsChunk) { - gridFsChunk._id = createObjectId(gridFsChunk); - //TODO createObjectId nutzen, sobald diese umgestellt ist - gridFsChunk.files_id = new ObjectId(gridFsChunk.files_id.$oid); - gridFsChunk.data = createBinData(gridFsChunk.data); + gridFsChunk._id = createObjectId(gridFsChunk); + //TODO createObjectId nutzen, sobald diese umgestellt ist + gridFsChunk.files_id = new ObjectId(gridFsChunk.files_id.$oid); + gridFsChunk.data = createBinData(gridFsChunk.data); } function parseVorgangData(data) { - data.forEach(vorgang => parseVorgang(vorgang)); - return data; + data.forEach((vorgang) => parseVorgang(vorgang)); + return data; } function parseVorgang(vorgang) { - vorgang._id = createObjectId(vorgang); - vorgang.createdAt = createDate(vorgang.createdAt); + vorgang._id = createObjectId(vorgang); + vorgang.createdAt = createDate(vorgang.createdAt); - vorgang.eingangs.forEach(eingang => parseEingang(eingang)); + vorgang.eingangs.forEach((eingang) => parseEingang(eingang)); - if (vorgang.wiedervorlages) { - vorgang.wiedervorlages.forEach(wiedervorlage => parseWiedervorlage(wiedervorlage)); - } - if(vorgang.kommentars){ - vorgang.kommentars.forEach(kommentar => parseKommentar(kommentar)); - } + if (vorgang.wiedervorlages) { + vorgang.wiedervorlages.forEach((wiedervorlage) => parseWiedervorlage(wiedervorlage)); + } + if (vorgang.kommentars) { + vorgang.kommentars.forEach((kommentar) => parseKommentar(kommentar)); + } } function parseEingang(eingang) { - eingang.header.createdAt = createDate(eingang.header.createdAt); + eingang.header.createdAt = createDate(eingang.header.createdAt); - if (eingang.attachments) { - eingang.attachments.forEach(attachment => parseAttachment(attachment)); - } - if (eingang.representations) { - eingang.representations.forEach(representation => parseRepresentations(representation)); - } + if (eingang.attachments) { + eingang.attachments.forEach((attachment) => parseAttachment(attachment)); + } + if (eingang.representations) { + eingang.representations.forEach((representation) => parseRepresentations(representation)); + } } function parseAttachment(attachment) { - attachment.files[ 0 ].content = createBinData(''); + attachment.files[0].content = createBinData(''); } -function createBinData(encoded64Value){ - return Binary(Buffer.from(encoded64Value, 'base64'), 0); +function createBinData(encoded64Value) { + return Binary(Buffer.from(encoded64Value, 'base64'), 0); } function parseRepresentations(representation) { - representation.content = createBinary(representation); + representation.content = createBinary(representation); } //TODO Code entfernen und stattdessen createBinData(value) nutzen function createBinary(field) { - return Binary(field.content.$binary.base64, 'base64'); + return Binary(field.content.$binary.base64, 'base64'); } function parseWiedervorlage(wiedervorlage) { - wiedervorlage.frist = createDate(wiedervorlage.frist); - wiedervorlage.createdAt = createDate(wiedervorlage.createdAt); + wiedervorlage.frist = createDate(wiedervorlage.frist); + wiedervorlage.createdAt = createDate(wiedervorlage.createdAt); } function parseKommentar(kommentar) { - kommentar.createdAt = createDate(kommentar.createdAt); + kommentar.createdAt = createDate(kommentar.createdAt); } function createDate(field) { - return new Date(field.$date); + return new Date(field.$date); } -function parseVorgangAttachedItemData(vorgangAttachedItems){ - vorgangAttachedItems.forEach(vorgangAttachedItem => parseVorgangAttachedItem(vorgangAttachedItem)); - return vorgangAttachedItems; +function parseVorgangAttachedItemData(vorgangAttachedItems) { + vorgangAttachedItems.forEach((vorgangAttachedItem) => + parseVorgangAttachedItem(vorgangAttachedItem), + ); + return vorgangAttachedItems; } function parseVorgangAttachedItem(parseVorgangAttachedItem) { - parseVorgangAttachedItem._id = createObjectId(parseVorgangAttachedItem); - parseVorgangAttachedItem.version = createNumberLong(parseVorgangAttachedItem.version); + parseVorgangAttachedItem._id = createObjectId(parseVorgangAttachedItem); + parseVorgangAttachedItem.version = createNumberLong(parseVorgangAttachedItem.version); } function parseUserData(data) { - data.forEach(user => parseUser(user)); - return data; + data.forEach((user) => parseUser(user)); + return data; } function parseUser(user) { - user._id = createObjectId(user); - user.createdAt = createDate(user.createdAt); + user._id = createObjectId(user); + user.createdAt = createDate(user.createdAt); } //TOOD Beschraenkung auf _id aufheben function createObjectId(field) { - return new ObjectId(field._id.$oid); + return new ObjectId(field._id.$oid); } -function createNumberLong(numberValue){ - return Long.fromNumber(numberValue); +function createNumberLong(numberValue) { + return Long.fromNumber(numberValue); } function insertIntoDatabase(config, collection, data) { - insert(getDatabaseUrl(config), getDatabase(config), collection, data); + insert(getDatabaseUrl(config), getDatabase(config), collection, data); } -function insertIntoUserManagerDatabase(config, collection, data){ - insert(getUserManagerDatabaseUrl(config), getUserManagerDatabase(config), collection, data); +function insertIntoUserManagerDatabase(config, collection, data) { + insert(getUserManagerDatabaseUrl(config), getUserManagerDatabase(config), collection, data); } -function insert(databaseUrl, databaseName, collection, data){ - MongoClient.connect(databaseUrl, (error, connection) => { - console.log(`connect to ${databaseName} database with ${databaseUrl}`); - if (!error) { - console.log('success'); - var db = connection.db(databaseName); +function insert(databaseUrl, databaseName, collection, data) { + MongoClient.connect(databaseUrl, (error, connection) => { + console.log(`connect to ${databaseName} database with ${databaseUrl}`); + if (!error) { + console.log('success'); + var db = connection.db(databaseName); - db.collection(collection).drop(() => { - db.createCollection(collection, (error) => handleCreateCollection(db, connection, collection, data, error)); - }); - } else { - console.log('fail', error); - } - }); + db.collection(collection).drop(() => { + db.createCollection(collection, (error) => + handleCreateCollection(db, connection, collection, data, error), + ); + }); + } else { + console.log('fail', error); + } + }); } function handleCreateCollection(db, connection, collection, data, error) { - if (error) { - console.log(`Fehler beim Erstellen der Collection "${collection}": `, error); - } else { - console.log(`Collection ${collection} erfolgreich erstellt`); - insertManyToDatabase(db, connection, collection, data); - } + if (error) { + console.log(`Fehler beim Erstellen der Collection "${collection}": `, error); + } else { + console.log(`Collection ${collection} erfolgreich erstellt`); + insertManyToDatabase(db, connection, collection, data); + } } function insertManyToDatabase(db, connection, collection, data) { - db.collection(collection).insertMany(data, (error) => handleInsertMany(connection, error)); + db.collection(collection).insertMany(data, (error) => handleInsertMany(connection, error)); } function handleInsertMany(connection, error) { - if (error) { - console.log('Fehler beim Einlesen der Daten: ', error); - } else { - console.log('Die Daten wurden erfolgreich eingelesen.'); - } - connection.close(); + if (error) { + console.log('Fehler beim Einlesen der Daten: ', error); + } else { + console.log('Die Daten wurden erfolgreich eingelesen.'); + } + connection.close(); } function dropCollectionsFromDatabase(config, collections) { - dropCollections(getDatabaseUrl(config), getDatabase(config), collections); + dropCollections(getDatabaseUrl(config), getDatabase(config), collections); } -function getDatabaseUrl(config){ - return config.env.dbUrl; +function getDatabaseUrl(config) { + return config.env.dbUrl; } -function getDatabase(config){ - return config.env.database +function getDatabase(config) { + return config.env.database; } -function dropUserManagerCollectionsFromDatabase(config, collections){ - dropCollections(getUserManagerDatabaseUrl(config), getUserManagerDatabase(config), collections); +function dropUserManagerCollectionsFromDatabase(config, collections) { + dropCollections(getUserManagerDatabaseUrl(config), getUserManagerDatabase(config), collections); } -function getUserManagerDatabaseUrl(config){ - return config.env.userManager.dbUrl; +function getUserManagerDatabaseUrl(config) { + return config.env.userManager.dbUrl; } -function getUserManagerDatabase(config){ - return config.env.userManager.database; +function getUserManagerDatabase(config) { + return config.env.userManager.database; } -function dropCollections(databaseUrl, databaseName, collections){ - MongoClient.connect(databaseUrl, (error, connection) => { - if (!error) { - const db = connection.db(databaseName); - collections.forEach((oneCollection, index) => { - console.log('drop collection', oneCollection); - db.collection(oneCollection).drop(() => { - //CHECKME Ist die Abfrage notwendig? - if(index == collections.length){ - console.log('close connection'); - connection.close(); - } - }); - }); - } - }); +function dropCollections(databaseUrl, databaseName, collections) { + MongoClient.connect(databaseUrl, (error, connection) => { + if (!error) { + const db = connection.db(databaseName); + collections.forEach((oneCollection, index) => { + console.log('drop collection', oneCollection); + db.collection(oneCollection).drop(() => { + //CHECKME Ist die Abfrage notwendig? + if (index == collections.length) { + console.log('close connection'); + connection.close(); + } + }); + }); + } + }); } -function countFiles(folderName:string): Promise<number> { - return new Promise((resolve, reject) => { - fs.readdir(folderName, (err, files) => { - if (err) { - console.error(err) - return reject(err) - } - resolve(files.length) - }) - }) +function countFiles(folderName: string): Promise<number> { + return new Promise((resolve, reject) => { + fs.readdir(folderName, (err, files) => { + if (err) { + console.error(err); + return reject(err); + } + resolve(files.length); + }); + }); } -function deleteFolder(folderName:string): void { - new Promise((resolve, reject) => { - rmdir(folderName, { maxRetries: 10, recursive: true }, (err) => { - if (err) { - console.error(err) - return reject(err) - } - resolve(null) - }) - }) -} \ No newline at end of file +function deleteFolder(folderName: string): void { + new Promise((resolve, reject) => { + rmdir(folderName, { maxRetries: 10, recursive: true }, (err) => { + if (err) { + console.error(err); + return reject(err); + } + resolve(null); + }); + }); +} diff --git a/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts b/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts index 19c0f9759b1a432221edd6b5c5433449703030a9..935ac6d7042933627651ef0d7aa425ff9ab7b183 100644 --- a/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/cypress.util.ts @@ -25,88 +25,92 @@ //TODO Naming der Methoden geradeziehen export function containClass(element: any, cssClass: string): void { - element.should('have.class', cssClass); + element.should('have.class', cssClass); } export function notContainClass(element: any, cssClass: string): void { - element.should('not.have.class', cssClass); + element.should('not.have.class', cssClass); } export function exist(element: any): void { - element.should('exist'); + element.should('exist'); } export function notExist(element: any): void { - element.should('not.exist'); + element.should('not.exist'); } export function haveText(element: any, text: string): void { - element.should('have.text', text); + element.should('have.text', text); } export function haveValue(element: any, value: string): void { - element.should('have.value', value); + element.should('have.value', value); } export function haveFocus(element: any): void { - element.should('have.focus'); + element.should('have.focus'); } export function mouseEnter(element: any): void { - element.trigger('mouseenter'); + element.trigger('mouseenter'); } export function mouseOver(element: any): void { - element.trigger('mouseover'); + element.trigger('mouseover'); } export function contains(element: any, containing: string): void { - element.should('exist').contains(containing); + element.should('exist').contains(containing); } export function notContains(element: any, containing: string): void { - element.contains(containing).should('not.exist'); + element.contains(containing).should('not.exist'); } export function haveLength(element: any, length: number): void { - element.should('have.length', length); + element.should('have.length', length); } //TODO: "first()" rausnehmen -> im html eine entprechende data-test-id ansprechen?! | trennen in "get" und "verify" export function shouldFirstContains(element: any, containing: string) { - element.first().should('exist').contains(containing); + element.first().should('exist').contains(containing); } -export function shouldHaveAttributeBeGreaterThan(element: any, attributeName: string, value: number) { - element.first().should('exist').invoke(attributeName).should('be.gt', value); +export function shouldHaveAttributeBeGreaterThan( + element: any, + attributeName: string, + value: number, +) { + element.first().should('exist').invoke(attributeName).should('be.gt', value); } export function shouldHaveAttributeBeLowerThan(element: any, attributeName: string, value: number) { - element.first().should('exist').invoke(attributeName).should('be.gt', value); + element.first().should('exist').invoke(attributeName).should('be.gt', value); } // export function visible(element: any) { - element.should('be.visible'); + element.should('be.visible'); } export function notBeVisible(element: any) { - element.should('not.be.visible'); + element.should('not.be.visible'); } export function enter(element: any): void { - element.clear().type(CypressKeyboardActions.ENTER) + element.clear().type(CypressKeyboardActions.ENTER); } export function enterWith(element: any, value: any): void { - element.clear().type(value + CypressKeyboardActions.ENTER) + element.clear().type(value + CypressKeyboardActions.ENTER); } export function backspaceOn(element: any): void { - element.type(CypressKeyboardActions.BACKSPACE); + element.type(CypressKeyboardActions.BACKSPACE); } enum CypressKeyboardActions { - ENTER = '{enter}', - BACKSPACE = '{backspace}' -} \ No newline at end of file + ENTER = '{enter}', + BACKSPACE = '{backspace}', +} diff --git a/alfa-client/apps/alfa-e2e/src/support/data.util.ts b/alfa-client/apps/alfa-e2e/src/support/data.util.ts index 591a7b7e11e920ca97a1e79270cd24755bd76d60..fdf79eab0c0bfb17063f9e49fe4f0a06956c3d5c 100644 --- a/alfa-client/apps/alfa-e2e/src/support/data.util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/data.util.ts @@ -30,8 +30,8 @@ export const TEST_FILE_WITH_CONTENT: string = 'fileWithContent.txt'; export const TEST_FILE_WITHOUT_CONTENT: string = 'fileWithoutContent.txt'; //TODO hat aktuell kein contentType -> Datei mit contentType anlegen export const TEST_FILE_WITH_CONTENT_4_MB: string = 'upload-me.withContent4MB'; -export const TEST_FILE_WITH_CONTENT_46MB: string = '41MB.zip' +export const TEST_FILE_WITH_CONTENT_46MB: string = '41MB.zip'; export const ORGANISATIONSEINHEITEN_ID_FOR_KORDNER = '10363455'; export const ORGANISATIONSEINHEITEN_ID_FOR_KFINDER = '9030229'; -export const ORGANISATIONSEINHEITEN_ID_FOR_BEATE = '12345678'; \ No newline at end of file +export const ORGANISATIONSEINHEITEN_ID_FOR_BEATE = '12345678'; diff --git a/alfa-client/apps/alfa-e2e/src/support/e2e.ts b/alfa-client/apps/alfa-e2e/src/support/e2e.ts index dfe690bf49b054326bcc103a14ee37e6f209efdb..2841a98738f11402021c07fe15d6e1103c5987ee 100644 --- a/alfa-client/apps/alfa-e2e/src/support/e2e.ts +++ b/alfa-client/apps/alfa-e2e/src/support/e2e.ts @@ -44,25 +44,25 @@ import './commands'; import './file-upload'; Cypress.on('command:start', ({ attributes }) => { - if (attributes.type === 'parent') { - Cypress.log({ - name: `${new Date().toISOString()} - ${attributes.name}`, - }); - } + if (attributes.type === 'parent') { + Cypress.log({ + name: `${new Date().toISOString()} - ${attributes.name}`, + }); + } }); Cypress.on('after:screenshot', ({ testFailure, takenAt }) => { - if (testFailure) { - console.log(`Error at: ${takenAt}`); - } + if (testFailure) { + console.log(`Error at: ${takenAt}`); + } }); Cypress.on('fail', (err) => { - console.error(err); - err.message = new Date().toISOString() + '\n' + err.message; - throw err; + console.error(err); + err.message = new Date().toISOString() + '\n' + err.message; + throw err; }); Cypress.Keyboard.defaults({ - keystrokeDelay: 30, + keystrokeDelay: 30, }); diff --git a/alfa-client/apps/alfa-e2e/src/support/file-upload.ts b/alfa-client/apps/alfa-e2e/src/support/file-upload.ts index 523486606c762d8f2044a7527a79e7ed55fdf805..ef89055ace7dd89a6f2be242f8930fdadd34c913 100644 --- a/alfa-client/apps/alfa-e2e/src/support/file-upload.ts +++ b/alfa-client/apps/alfa-e2e/src/support/file-upload.ts @@ -24,9 +24,9 @@ import 'cypress-file-upload'; export function uploadFile(inputElement: any, fileName: string): void { - inputElement.attachFile(fileName); + inputElement.attachFile(fileName); } export function uploadEmptyFile(inputElement: any, fileName: string): void { - inputElement.attachFile(fileName, { allowEmpty: true }); -} \ No newline at end of file + inputElement.attachFile(fileName, { allowEmpty: true }); +} diff --git a/alfa-client/apps/alfa-e2e/src/support/kommentar.util.ts b/alfa-client/apps/alfa-e2e/src/support/kommentar.util.ts index fb3554a7f4243ddbffc928cf5dfd13af14ba547a..286db723f2156b7d1f3e49f4f71e4e1a9a9b70d0 100644 --- a/alfa-client/apps/alfa-e2e/src/support/kommentar.util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/kommentar.util.ts @@ -22,28 +22,35 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { KommentarE2E } from '../model/kommentar'; -import { VorgangAttachedItemClientE2E, VorgangAttachedItemE2E, VorgangAttachedItemNameE2E } from '../model/vorgang-attached-item'; +import { + VorgangAttachedItemClientE2E, + VorgangAttachedItemE2E, + VorgangAttachedItemNameE2E, +} from '../model/vorgang-attached-item'; import { getUserSabineInternalId } from './user-util'; import { VORGANG_ATTACHED_ITEM_CLASS } from './vorgang-attached-item-util'; const kommentarFixture: KommentarE2E = require('../fixtures/kommentar/kommentar.json'); export function createKommentar(): KommentarE2E { - return { ...kommentarFixture, createdBy: getUserSabineInternalId() }; + return { ...kommentarFixture, createdBy: getUserSabineInternalId() }; } -export function createKommentarAttachedItem(_id: string, vorgangId: string): VorgangAttachedItemE2E { - return { - _id: { $oid: _id }, - version: 0, - vorgangId, - client: VorgangAttachedItemClientE2E.ALFA, - itemName: VorgangAttachedItemNameE2E.KOMMENTAR, - item: { - ...createKommentar(), - vorgangId - }, - deleted: false, - _class: VORGANG_ATTACHED_ITEM_CLASS - }; -} \ No newline at end of file +export function createKommentarAttachedItem( + _id: string, + vorgangId: string, +): VorgangAttachedItemE2E { + return { + _id: { $oid: _id }, + version: 0, + vorgangId, + client: VorgangAttachedItemClientE2E.ALFA, + itemName: VorgangAttachedItemNameE2E.KOMMENTAR, + item: { + ...createKommentar(), + vorgangId, + }, + deleted: false, + _class: VORGANG_ATTACHED_ITEM_CLASS, + }; +} diff --git a/alfa-client/apps/alfa-e2e/src/support/linkrels.ts b/alfa-client/apps/alfa-e2e/src/support/linkrels.ts index 27c6327aa7e1e4992fa41039088ff31ce97352c9..15604b383ada5c5b0ed0ced6ec43286bd326c19d 100644 --- a/alfa-client/apps/alfa-e2e/src/support/linkrels.ts +++ b/alfa-client/apps/alfa-e2e/src/support/linkrels.ts @@ -22,6 +22,6 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum LinkRelE2E { - POSTFACH_NACHRICHTEN = 'postfachMails', //TODO rename - POSTFACH_NACHRICHTEN_ATTACHMENTS = 'attachments' -} \ No newline at end of file + POSTFACH_NACHRICHTEN = 'postfachMails', //TODO rename + POSTFACH_NACHRICHTEN_ATTACHMENTS = 'attachments', +} diff --git a/alfa-client/apps/alfa-e2e/src/support/loesch-anforderung.util.ts b/alfa-client/apps/alfa-e2e/src/support/loesch-anforderung.util.ts index 5d53dcee08619e95a0762e63996f77a083db42e1..7fb92fae5f5296053c66bed3c2609ad867bfb448 100644 --- a/alfa-client/apps/alfa-e2e/src/support/loesch-anforderung.util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/loesch-anforderung.util.ts @@ -26,5 +26,5 @@ import { LoeschAnforderungE2E } from '../model/loesch-anforderung'; const loeschAnforderungFixture: LoeschAnforderungE2E = require('../fixtures/loesch-anforderung/loesch-anforderung.json'); export function createLoeschAnforderung(): LoeschAnforderungE2E { - return loeschAnforderungFixture; -} \ No newline at end of file + return loeschAnforderungFixture; +} diff --git a/alfa-client/apps/alfa-e2e/src/support/messages.ts b/alfa-client/apps/alfa-e2e/src/support/messages.ts index 8d4b602556363061f9ecf097ada4d5d4eeddd0e7..fe92afc1423d81bc94a5100f2461abef58d32ebe 100644 --- a/alfa-client/apps/alfa-e2e/src/support/messages.ts +++ b/alfa-client/apps/alfa-e2e/src/support/messages.ts @@ -22,14 +22,14 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum MessagesE2E { - HTTP_STATUS_FORBIDDEN = 'Die Aktion konnte wegen fehlender Berechtigungen nicht durchgeführt werden', - HTTP_SERVER_ERROR_DIALOG_HEADER = 'Es ist ein Fehler aufgetreten ...', - HTTP_SERVER_ERROR = 'Wir sind nicht ganz sicher, was schiefgelaufen ist. Der Fehler wurde unserem Support gemeldet. Bitte starten sie die Anwendung neu.', + HTTP_STATUS_FORBIDDEN = 'Die Aktion konnte wegen fehlender Berechtigungen nicht durchgeführt werden', + HTTP_SERVER_ERROR_DIALOG_HEADER = 'Es ist ein Fehler aufgetreten ...', + HTTP_SERVER_ERROR = 'Wir sind nicht ganz sicher, was schiefgelaufen ist. Der Fehler wurde unserem Support gemeldet. Bitte starten sie die Anwendung neu.', - WIEDERVORLAGE_ANGELEGT = 'Die Wiedervorlage "%s" wurde angelegt', - WIEDERVORLAGE_GESPEICHERT = 'Die Wiedervorlage "%s" wurde gespeichert', + WIEDERVORLAGE_ANGELEGT = 'Die Wiedervorlage "%s" wurde angelegt', + WIEDERVORLAGE_GESPEICHERT = 'Die Wiedervorlage "%s" wurde gespeichert', - USER_PROFILE_SERVICE_UNAVAILABLE = 'Die Benutzerdaten konnten nicht geladen werden', - USER_PROFILE_RESOURCE_NOT_FOUND = 'Der zugewiesene Bearbeiter konnte nicht gefunden werden', - USER_PROFILE_UNASSIGNED = 'Kein Bearbeiter zugewiesen' -} \ No newline at end of file + USER_PROFILE_SERVICE_UNAVAILABLE = 'Die Benutzerdaten konnten nicht geladen werden', + USER_PROFILE_RESOURCE_NOT_FOUND = 'Der zugewiesene Bearbeiter konnte nicht gefunden werden', + USER_PROFILE_UNASSIGNED = 'Kein Bearbeiter zugewiesen', +} diff --git a/alfa-client/apps/alfa-e2e/src/support/postfach-util.ts b/alfa-client/apps/alfa-e2e/src/support/postfach-util.ts index 5486e90d3e816e83e3e7edf5ec96283d7fe9e527..f9686c25ae89cd4740c69ab3e00a8d611ae013ac 100644 --- a/alfa-client/apps/alfa-e2e/src/support/postfach-util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/postfach-util.ts @@ -28,9 +28,9 @@ import { buildUrl } from './tech.util'; const postfachNachricht: PostfachE2E = require('../fixtures/postfach/postfach-nachricht-reply-item.json'); export function createPostfachUriByVorgangId(id: string): string { - return `/vorgang/${encodeUrlForEmbedding(buildUrl(id, 'vorgangs'))}/postfach`; + return `/vorgang/${encodeUrlForEmbedding(buildUrl(id, 'vorgangs'))}/postfach`; } export function createPostfachNachricht() { - return { ...postfachNachricht, class: 'class de.ozgcloud.alfa.postfach.PostfachMail' }; -} \ No newline at end of file + return { ...postfachNachricht, class: 'class de.ozgcloud.alfa.postfach.PostfachMail' }; +} diff --git a/alfa-client/apps/alfa-e2e/src/support/tech.util.ts b/alfa-client/apps/alfa-e2e/src/support/tech.util.ts index f8fcc0bfe39b31c84546cc045d4ccde00e60de3c..968dc38227aad3425764cf895d902cb6887c6758 100644 --- a/alfa-client/apps/alfa-e2e/src/support/tech.util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/tech.util.ts @@ -26,72 +26,71 @@ import { ResourceE2E } from '../model/util'; import { getBaseUrl } from './cypress-helper'; export function formatDateLocal(date: Date | string, pattern: string): string { - return formatDate(date, pattern, 'de'); + return formatDate(date, pattern, 'de'); } export function removeLinkFromResource(obj: ResourceE2E, linkRel: string): ResourceE2E { - delete obj._links[linkRel]; - return obj; + delete obj._links[linkRel]; + return obj; } export function generateIds(toGenerate: number): string[] { - let ids: string[] = []; + let ids: string[] = []; - for (let i = 0; i < toGenerate; i++) { - let id; - do { - id = generate12ByteId(); - if (!ids.includes(id)) { - ids[i] = id; - } - } - while (!ids.includes(id)); - } - return ids; + for (let i = 0; i < toGenerate; i++) { + let id; + do { + id = generate12ByteId(); + if (!ids.includes(id)) { + ids[i] = id; + } + } while (!ids.includes(id)); + } + return ids; } export function generate12ByteId(): string { - let outString: string = ''; - let inOptions: string = 'abcdefghijklmnopqrstuvwxyz0123456789'; + let outString: string = ''; + let inOptions: string = 'abcdefghijklmnopqrstuvwxyz0123456789'; - for (let i = 0; i < 12; i++) { - outString += inOptions.charAt(Math.floor(Math.random() * inOptions.length)); - } - return outString; + for (let i = 0; i < 12; i++) { + outString += inOptions.charAt(Math.floor(Math.random() * inOptions.length)); + } + return outString; } export function buildUrl(id: string, pathPrefix: string) { - return `${getBaseUrl()}/api/${pathPrefix}/${id}` + return `${getBaseUrl()}/api/${pathPrefix}/${id}`; } export function convertToDataTestId(value: string): string { - if (value == null || value == undefined) { - return null; - } - value = replaceAllWhitespaces(value, '_'); - return simpleTransliteration(value); + if (value == null || value == undefined) { + return null; + } + value = replaceAllWhitespaces(value, '_'); + return simpleTransliteration(value); } export function replaceAllWhitespaces(value: string, replaceWith: string): string { - return value.replace(/ /g, replaceWith); + return value.replace(/ /g, replaceWith); } export function simpleTransliteration(value: string) { - return value.normalize('NFKD').replace(/[^-A-Za-z0-9_]/g, ''); + return value.normalize('NFKD').replace(/[^-A-Za-z0-9_]/g, ''); } export function createDateToday(): string { - return formatDateLocal(new Date(), 'yyyy-MM-dd'); + return formatDateLocal(new Date(), 'yyyy-MM-dd'); } export function createDateInThePast(): string { - const today = new Date(); - today.setFullYear(today.getFullYear() - 1); - return formatDateLocal(today, 'yyyy-MM-dd'); + const today = new Date(); + today.setFullYear(today.getFullYear() - 1); + return formatDateLocal(today, 'yyyy-MM-dd'); } export function createDateInTheFuture(): string { - const today = new Date(); - today.setFullYear(today.getFullYear() + 1); - return formatDateLocal(today, 'yyyy-MM-dd'); -} \ No newline at end of file + const today = new Date(); + today.setFullYear(today.getFullYear() + 1); + return formatDateLocal(today, 'yyyy-MM-dd'); +} diff --git a/alfa-client/apps/alfa-e2e/src/support/user-util.ts b/alfa-client/apps/alfa-e2e/src/support/user-util.ts index c47fe58593b45d6a252c51198830b5ebf6c46a71..3686a9fc14801a9752f4b7aa3baef64efd5f0410 100644 --- a/alfa-client/apps/alfa-e2e/src/support/user-util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/user-util.ts @@ -34,106 +34,110 @@ const userManagerEmilFixture: UsermanagerUserE2E = require('../fixtures/usermana const userManagerDorotheaFixture: UsermanagerUserE2E = require('../fixtures/usermanager/usermanager_user_dorothea.json'); export function initUsermanagerUsers(users: UsermanagerUserE2E[]) { - initUsermanagerData(users); + initUsermanagerData(users); } export function getUserSabine(): UserE2E { - return sabineFixture; + return sabineFixture; } export function getUserDorothea(): UserE2E { - return dorotheaFixture; + return dorotheaFixture; } export function getUserManagerUserSabine(): UsermanagerUserE2E { - return withIdsFromCypressEnv(userManagerSabineFixture); + return withIdsFromCypressEnv(userManagerSabineFixture); } export function getUserManagerUserPeter(): UsermanagerUserE2E { - return withIdsFromCypressEnv(userManagerPeterFixture); + return withIdsFromCypressEnv(userManagerPeterFixture); } export function getUserManagerUserEmil(): UsermanagerUserE2E { - return withIdsFromCypressEnv(userManagerEmilFixture); + return withIdsFromCypressEnv(userManagerEmilFixture); } export function getUserManagerUserDorothea(): UsermanagerUserE2E { - return withIdsFromCypressEnv(userManagerDorotheaFixture); + return withIdsFromCypressEnv(userManagerDorotheaFixture); } export function getUserSabineInternalId(): string { - return getUserManagerUserSabine()._id.$oid; + return getUserManagerUserSabine()._id.$oid; } function withIdsFromCypressEnv(user: UsermanagerUserE2E): UsermanagerUserE2E { - user._id = { $oid: getUserInternalIdFromCypressEnv(user.username) }; - user.keycloakUserId = getKeycloakUserIdFromCypressEnv(user.username); - return user; + user._id = { $oid: getUserInternalIdFromCypressEnv(user.username) }; + user.keycloakUserId = getKeycloakUserIdFromCypressEnv(user.username); + return user; } function getUserInternalIdFromCypressEnv(username: string): string { - return getCypressEnv(`${username}InternalId`); + return getCypressEnv(`${username}InternalId`); } function getKeycloakUserIdFromCypressEnv(username: string): string { - return getCypressEnv(`${username}Uuid`); + return getCypressEnv(`${username}Uuid`); } enum DatabaseUser { - EMIL = 'user-ea/user_emil.json', - KFINDER = 'user-main/user_kfinder.json', - KORDNER = 'user-main/user_kordner.json', - LUDWIG = 'user-main/user_ludwig.json', - PETER = 'user-main/user_peter.json', - RICHARD = 'user-main/user_richard.json', - SABINE = 'user-main/user_sabine.json', - ZONK = 'user-main/user_zonk.json' + EMIL = 'user-ea/user_emil.json', + KFINDER = 'user-main/user_kfinder.json', + KORDNER = 'user-main/user_kordner.json', + LUDWIG = 'user-main/user_ludwig.json', + PETER = 'user-main/user_peter.json', + RICHARD = 'user-main/user_richard.json', + SABINE = 'user-main/user_sabine.json', + ZONK = 'user-main/user_zonk.json', } export function loginAsEmil(): void { - login(DatabaseUser.EMIL); + login(DatabaseUser.EMIL); } export function loginAsKfinder(): void { - login(DatabaseUser.KFINDER); + login(DatabaseUser.KFINDER); } export function loginAsKordner(): void { - login(DatabaseUser.KORDNER); + login(DatabaseUser.KORDNER); } export function loginAsPeter(): void { - login(DatabaseUser.PETER); + login(DatabaseUser.PETER); } export function loginAsRichard(): void { - login(DatabaseUser.RICHARD); + login(DatabaseUser.RICHARD); } export function loginAsSabine(): void { - login(DatabaseUser.SABINE); + login(DatabaseUser.SABINE); } export function loginAsZonk(): void { - login(DatabaseUser.ZONK); + login(DatabaseUser.ZONK); } export function loginAsLudwig(): void { - login(DatabaseUser.LUDWIG); + login(DatabaseUser.LUDWIG); } export enum UserRoleE2E { - EINHEITLICHER_ANSPRECHPARTNER = 'EINHEITLICHER_ANSPRECHPARTNER', - VERWALTUNG_LOESCHEN = 'VERWALTUNG_LOESCHEN', - VERWALTUNG_POSTSTELLE = 'VERWALTUNG_POSTSTELLE', - VERWALTUNG_USER = 'VERWALTUNG_USER' + EINHEITLICHER_ANSPRECHPARTNER = 'EINHEITLICHER_ANSPRECHPARTNER', + VERWALTUNG_LOESCHEN = 'VERWALTUNG_LOESCHEN', + VERWALTUNG_POSTSTELLE = 'VERWALTUNG_POSTSTELLE', + VERWALTUNG_USER = 'VERWALTUNG_USER', } //TODO Cleanup export function loginByUi(user: UserE2E): void { - cy.visit('') - .get('#kc-login').should('exist') - .get('#username').type(user.name) - .get('#password').type(user.password) - .get('#kc-login').click(); -} \ No newline at end of file + cy.visit('') + .get('#kc-login') + .should('exist') + .get('#username') + .type(user.name) + .get('#password') + .type(user.password) + .get('#kc-login') + .click(); +} diff --git a/alfa-client/apps/alfa-e2e/src/support/vorgang-attached-item-util.ts b/alfa-client/apps/alfa-e2e/src/support/vorgang-attached-item-util.ts index c99aa57229dccf24f39937049eb6860817c8d292..e1fb505d3ba75576a0d20ac140188b019cc6d7b5 100644 --- a/alfa-client/apps/alfa-e2e/src/support/vorgang-attached-item-util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/vorgang-attached-item-util.ts @@ -21,14 +21,19 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { PostfachMailItemE2E, VorgangAttachedItemClientE2E, VorgangAttachedItemE2E, VorgangAttachedItemNameE2E } from '../model/vorgang-attached-item'; +import { + PostfachMailItemE2E, + VorgangAttachedItemClientE2E, + VorgangAttachedItemE2E, + VorgangAttachedItemNameE2E, +} from '../model/vorgang-attached-item'; import { initVorgangAttachedItemData } from './cypress-helper'; -import { createLoeschAnforderung } from "./loesch-anforderung.util"; +import { createLoeschAnforderung } from './loesch-anforderung.util'; export const VORGANG_ATTACHED_ITEM_CLASS: string = 'VorgangAttachedItem'; export function initVorgangAttachedItem(vorgangAttachedItems: VorgangAttachedItemE2E[]): void { - initVorgangAttachedItemData(vorgangAttachedItems); + initVorgangAttachedItemData(vorgangAttachedItems); } /**@deprecated */ @@ -36,23 +41,27 @@ const vorgangAttachedItemFixture: VorgangAttachedItemE2E = require('../fixtures/ /**@deprecated */ export function createVorgangAttachedItem(): VorgangAttachedItemE2E { - return vorgangAttachedItemFixture; + return vorgangAttachedItemFixture; } /**@deprecated */ -export function buildVorgangAttachedItem(_id: string, vorgangId: string, itemName: VorgangAttachedItemNameE2E): VorgangAttachedItemE2E { - return { - ...createVorgangAttachedItem(), - _id: { $oid: _id }, - version: 0, - vorgangId, - itemName, - item: { - ...createVorgangAttachedItem().item, - vorgangId - }, - deleted: false - }; +export function buildVorgangAttachedItem( + _id: string, + vorgangId: string, + itemName: VorgangAttachedItemNameE2E, +): VorgangAttachedItemE2E { + return { + ...createVorgangAttachedItem(), + _id: { $oid: _id }, + version: 0, + vorgangId, + itemName, + item: { + ...createVorgangAttachedItem().item, + vorgangId, + }, + deleted: false, + }; } //TODO in postfach-nachricht-util.ts verschieben @@ -60,34 +69,40 @@ export function buildVorgangAttachedItem(_id: string, vorgangId: string, itemNam const postfachNachrichtReplyItemFixture: PostfachMailItemE2E = require('../fixtures/postfach/postfach-nachricht-reply-item.json'); export function createPostfachNachrichtReplyItem(): PostfachMailItemE2E { - return postfachNachrichtReplyItemFixture; + return postfachNachrichtReplyItemFixture; } -export function createPostfachNachrichtAttachedItem(_id: string, vorgangId: string): VorgangAttachedItemE2E { - return { - _id: { $oid: _id }, - version: 0, - vorgangId, - client: VorgangAttachedItemClientE2E.OZGCLOUD_NACHRICHTEN_MANAGER, - itemName: VorgangAttachedItemNameE2E.POSTFACH_NACHRICHT, - item: { - ...createPostfachNachrichtReplyItem(), - vorgangId - }, - deleted: false, - _class: VORGANG_ATTACHED_ITEM_CLASS - }; +export function createPostfachNachrichtAttachedItem( + _id: string, + vorgangId: string, +): VorgangAttachedItemE2E { + return { + _id: { $oid: _id }, + version: 0, + vorgangId, + client: VorgangAttachedItemClientE2E.OZGCLOUD_NACHRICHTEN_MANAGER, + itemName: VorgangAttachedItemNameE2E.POSTFACH_NACHRICHT, + item: { + ...createPostfachNachrichtReplyItem(), + vorgangId, + }, + deleted: false, + _class: VORGANG_ATTACHED_ITEM_CLASS, + }; } -export function createLoeschAnforderungAttachedItem(_id: string, vorgangId: string): VorgangAttachedItemE2E { - return { - _id: { $oid: _id }, - version: 0, - vorgangId: vorgangId, - client: VorgangAttachedItemClientE2E.ALFA, - itemName: VorgangAttachedItemNameE2E.LOESCH_ANFORDERUNG, - item: createLoeschAnforderung(), - deleted: false, - _class: VORGANG_ATTACHED_ITEM_CLASS - }; -} \ No newline at end of file +export function createLoeschAnforderungAttachedItem( + _id: string, + vorgangId: string, +): VorgangAttachedItemE2E { + return { + _id: { $oid: _id }, + version: 0, + vorgangId: vorgangId, + client: VorgangAttachedItemClientE2E.ALFA, + itemName: VorgangAttachedItemNameE2E.LOESCH_ANFORDERUNG, + item: createLoeschAnforderung(), + deleted: false, + _class: VORGANG_ATTACHED_ITEM_CLASS, + }; +} diff --git a/alfa-client/apps/alfa-e2e/src/support/vorgang-util.ts b/alfa-client/apps/alfa-e2e/src/support/vorgang-util.ts index 91eac0b3180ba440ad1411fee228ee7259458b52..a854118dfe054a851641f0e44629982cbb0d6f87 100644 --- a/alfa-client/apps/alfa-e2e/src/support/vorgang-util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/vorgang-util.ts @@ -23,7 +23,15 @@ */ import { encodeUrlForEmbedding } from '@alfa-client/tech-shared'; import { isUndefined } from 'lodash-es'; -import { AccessPermissionE2E, AntragstellerE2E, ClientAttributeE2E, ClientAttributesE2E, EingangE2E, EingangHeaderE2E, VorgangE2E } from '../model/vorgang'; +import { + AccessPermissionE2E, + AntragstellerE2E, + ClientAttributeE2E, + ClientAttributesE2E, + EingangE2E, + EingangHeaderE2E, + VorgangE2E, +} from '../model/vorgang'; import { VorgangAttachedItemClientE2E } from '../model/vorgang-attached-item'; import { initSearchIndexData, initVorgangData } from './cypress-helper'; import { buildUrl } from './tech.util'; @@ -32,27 +40,27 @@ export const objectIds: string[] = require('../fixtures/util/object_id_collectio const vorgangFixture: VorgangE2E = require('../fixtures/vorgang/vorgang.json'); export function createVorgang(): VorgangE2E { - return vorgangFixture; + return vorgangFixture; } export function buildVorgang($oid: string, uiIdentifier: string): VorgangE2E { - return { - ...createVorgang(), - _id: { $oid }, - name: uiIdentifier - }; + return { + ...createVorgang(), + _id: { $oid }, + name: uiIdentifier, + }; } export function initSearchIndex(vorgaenge: VorgangE2E[]): void { - initSearchIndexData(vorgaenge); + initSearchIndexData(vorgaenge); } export function initVorgang(vorgang: VorgangE2E): void { - initVorgaenge([vorgang]); + initVorgaenge([vorgang]); } export function initVorgaenge(vorgaenge: VorgangE2E[]): void { - initVorgangData(vorgaenge); + initVorgangData(vorgaenge); } export const EingangE2ETestData: EingangE2E = createVorgang().eingangs[0]; @@ -60,42 +68,53 @@ export const AntragstellerE2ETestData: AntragstellerE2E = EingangE2ETestData.ant export const EingangHeaderE2ETestData: EingangHeaderE2E = EingangE2ETestData.header; export function createVorgangUriById(id: string): string { - return `/vorgang/${encodeUrlForEmbedding(buildUrl(id, 'vorgangs'))}`; + return `/vorgang/${encodeUrlForEmbedding(buildUrl(id, 'vorgangs'))}`; } export const VORGANG_LIST_PAGE_SIZE: number = 100; export const VORGANG_LIST_NEXT_FRIST_PARAM: string = 'nextFrist=exists'; export function buildVorgangListPageLink(page: number, assignedTo?: string): string { - let link: string = `vorgangs?page=${page - 1}&limit=100`; + let link: string = `vorgangs?page=${page - 1}&limit=100`; - if (isUndefined(assignedTo)) { - return link; - } + if (isUndefined(assignedTo)) { + return link; + } - return `${link}&assignedTo=${assignedTo}`; + return `${link}&assignedTo=${assignedTo}`; } //Client Attribute const CLIENT_ATTRIBUTE_CLASS: string = 'ClientAttribute'; -export function createAlfaClientAttributes(attributeName: string, clientAttribute: ClientAttributeE2E): ClientAttributesE2E { - return { [VorgangAttachedItemClientE2E.ALFA]: { [attributeName]: clientAttribute } } +export function createAlfaClientAttributes( + attributeName: string, + clientAttribute: ClientAttributeE2E, +): ClientAttributesE2E { + return { [VorgangAttachedItemClientE2E.ALFA]: { [attributeName]: clientAttribute } }; } export function createNextWiedervorlageFristClientAttribute(value: string): ClientAttributeE2E { - return createReadOnlyClientAttribute(value); + return createReadOnlyClientAttribute(value); } export function createHasPostfachNachrichtClientAttribute(value: boolean): ClientAttributeE2E { - return createReadOnlyClientAttribute(value); + return createReadOnlyClientAttribute(value); } export function createHasNewPostfachNachrichtClientAttribute(value: boolean): ClientAttributeE2E { - return <ClientAttributeE2E>{ access: AccessPermissionE2E.READ_WRITE, value, _class: CLIENT_ATTRIBUTE_CLASS }; + return <ClientAttributeE2E>{ + access: AccessPermissionE2E.READ_WRITE, + value, + _class: CLIENT_ATTRIBUTE_CLASS, + }; } function createReadOnlyClientAttribute(value: string | boolean): ClientAttributeE2E { - return <ClientAttributeE2E>{ access: AccessPermissionE2E.READ_ONLY, value, _class: CLIENT_ATTRIBUTE_CLASS }; -} \ No newline at end of file + return <ClientAttributeE2E>{ + access: AccessPermissionE2E.READ_ONLY, + value, + _class: CLIENT_ATTRIBUTE_CLASS, + }; +} diff --git a/alfa-client/apps/alfa-e2e/src/support/wiedervorlage-util.ts b/alfa-client/apps/alfa-e2e/src/support/wiedervorlage-util.ts index 49ee58d9d1445a9130298d83d5dddc88c58b4e6a..47a29cfe497105f972af45f482753cae04375db5 100644 --- a/alfa-client/apps/alfa-e2e/src/support/wiedervorlage-util.ts +++ b/alfa-client/apps/alfa-e2e/src/support/wiedervorlage-util.ts @@ -22,7 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { encodeUrlForEmbedding } from '@alfa-client/tech-shared'; -import { VorgangAttachedItemClientE2E, VorgangAttachedItemE2E, VorgangAttachedItemNameE2E } from '../model/vorgang-attached-item'; +import { + VorgangAttachedItemClientE2E, + VorgangAttachedItemE2E, + VorgangAttachedItemNameE2E, +} from '../model/vorgang-attached-item'; import { WiedervorlageE2E } from '../model/wiedervorlage'; import { buildUrl } from './tech.util'; import { VORGANG_ATTACHED_ITEM_CLASS } from './vorgang-attached-item-util'; @@ -34,45 +38,51 @@ const wiedervorlageFixture: WiedervorlageE2E = require('../fixtures/wiedervorlag /** @deprecated */ export function createWiedervorlage(): WiedervorlageE2E { - return wiedervorlageFixture; + return wiedervorlageFixture; } /** @deprecated */ export function buildWiedervorlage(_id: string, uiIdentifier: string): WiedervorlageE2E { - return { - ...wiedervorlageFixture, - _id, - betreff: uiIdentifier - }; + return { + ...wiedervorlageFixture, + _id, + betreff: uiIdentifier, + }; } export function createWiedervorlageNeuUriByVorgangId(id: string): string { - return `${createVorgangUriById(id)}/wiedervorlage/neu`; + return `${createVorgangUriById(id)}/wiedervorlage/neu`; } -export function createWiedervorlageUriByVorgangIdAndWiedervorlageId(vorgangId: string, wiedervorlageId: string): string { - return `${createVorgangUriById(vorgangId)}/wiedervorlage/${encodeUrlForEmbedding(buildUrl(wiedervorlageId, 'wiedervorlages'))}`; +export function createWiedervorlageUriByVorgangIdAndWiedervorlageId( + vorgangId: string, + wiedervorlageId: string, +): string { + return `${createVorgangUriById(vorgangId)}/wiedervorlage/${encodeUrlForEmbedding(buildUrl(wiedervorlageId, 'wiedervorlages'))}`; } const wiedervorlageItemFixture: WiedervorlageE2E = require('../fixtures/wiedervorlage/wiedervorlage.json'); //TODO rename to createWiedervorlage if deprecated function removed export function createWiedervorlageItem(betreff: string): WiedervorlageE2E { - return { ...wiedervorlageItemFixture, betreff, createdBy: getUserSabineInternalId() }; + return { ...wiedervorlageItemFixture, betreff, createdBy: getUserSabineInternalId() }; } -export function createWiedervorlageAttachedItem(_id: string, vorgangId: string): VorgangAttachedItemE2E { - return { - _id: { $oid: _id }, - version: 0, - vorgangId, - client: VorgangAttachedItemClientE2E.ALFA, - itemName: VorgangAttachedItemNameE2E.WIEDERVORLAGE, - item: { - ...createWiedervorlageItem('Wiedervorlage'), - vorgangId - }, - deleted: false, - _class: VORGANG_ATTACHED_ITEM_CLASS - }; -} \ No newline at end of file +export function createWiedervorlageAttachedItem( + _id: string, + vorgangId: string, +): VorgangAttachedItemE2E { + return { + _id: { $oid: _id }, + version: 0, + vorgangId, + client: VorgangAttachedItemClientE2E.ALFA, + itemName: VorgangAttachedItemNameE2E.WIEDERVORLAGE, + item: { + ...createWiedervorlageItem('Wiedervorlage'), + vorgangId, + }, + deleted: false, + _class: VORGANG_ATTACHED_ITEM_CLASS, + }; +} diff --git a/alfa-client/apps/alfa-e2e/tsconfig.json b/alfa-client/apps/alfa-e2e/tsconfig.json index 2cdee4db8b30c135503582f5274a1387ec8cd70c..4f096f42c2afb14bc8ac58cdc895a0588e06cfd3 100644 --- a/alfa-client/apps/alfa-e2e/tsconfig.json +++ b/alfa-client/apps/alfa-e2e/tsconfig.json @@ -1,28 +1,28 @@ { - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "sourceMap": false, - "outDir": "../dist/out-tsc", - "allowJs": true, - "types": ["cypress", "node"], - "forceConsistentCasingInFileNames": true, - "strict": false, - "noImplicitOverride": true, - "noPropertyAccessFromIndexSignature": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - }, - "include": [ - "src/**/*.ts", - "src/**/*.js", - "cypress.config.ts", - "cypress-ci-main-tests.config.ts", - "cypress-ci-einheitlicher-ansprechpartner.config.ts" - ], - "angularCompilerOptions": { - "enableI18nLegacyMessageIdFormat": false, - "strictInjectionParameters": true, - "strictInputAccessModifiers": true, - "strictTemplates": true - } + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "sourceMap": false, + "outDir": "../dist/out-tsc", + "allowJs": true, + "types": ["cypress", "node"], + "forceConsistentCasingInFileNames": true, + "strict": false, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "src/**/*.ts", + "src/**/*.js", + "cypress.config.ts", + "cypress-ci-main-tests.config.ts", + "cypress-ci-einheitlicher-ansprechpartner.config.ts" + ], + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } } diff --git a/alfa-client/apps/alfa/.eslintrc.json b/alfa-client/apps/alfa/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/apps/alfa/.eslintrc.json +++ b/alfa-client/apps/alfa/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/apps/alfa/jest.config.ts b/alfa-client/apps/alfa/jest.config.ts index 0ee824463f4caa778648551d7e277e33d8aa9a16..eab11b1b54696682675dc27269308658440e7c45 100644 --- a/alfa-client/apps/alfa/jest.config.ts +++ b/alfa-client/apps/alfa/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'alfa', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/apps/alfa', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'alfa', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/apps/alfa', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/apps/alfa/project.json b/alfa-client/apps/alfa/project.json index d13cedc3fb1efc3a39ab7bc7c73af41f48bf7388..38219d2a71f6ddbec5a7929c3d9204a9de32c666 100644 --- a/alfa-client/apps/alfa/project.json +++ b/alfa-client/apps/alfa/project.json @@ -1,124 +1,121 @@ { - "name": "alfa", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "application", - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "sourceRoot": "apps/alfa/src", - "prefix": "alfa", - "targets": { - "build": { - "executor": "@angular-devkit/build-angular:browser", - "options": { - "allowedCommonJsDependencies": ["file-saver"], - "outputPath": "dist/apps/alfa", - "index": "apps/alfa/src/index.html", - "main": "apps/alfa/src/main.ts", - "polyfills": "apps/alfa/src/polyfills.ts", - "tsConfig": "apps/alfa/tsconfig.app.json", - "assets": [ - "apps/alfa/src/assets", - "apps/alfa/src/silent-refresh.html", - { - "input": "apps/alfa/src/favicon", - "glob": "**/*", - "output": "" - }, - { - "input": "libs/ui/src/lib/assets", - "glob": "**/*", - "output": "assets/icons" - } - ], - "styles": ["apps/alfa/src/styles/main.scss"], - "scripts": [], - "stylePreprocessorOptions": { - "includePaths": [ - "apps/alfa/src/styles/abstracts", - "apps/alfa/src/styles/material", - "node_modules/@angular", - "node_modules/include-media", - "node_modules/typeface-roboto" - ] - }, - "vendorChunk": true, - "extractLicenses": false, - "buildOptimizer": false, - "sourceMap": true, - "optimization": false, - "namedChunks": true - }, - "configurations": { - "production": { - "fileReplacements": [ - { - "replace": "apps/alfa/src/environments/environment.ts", - "with": "apps/alfa/src/environments/environment.prod.ts" - } - ], - "optimization": true, - "outputHashing": "all", - "sourceMap": false, - "namedChunks": false, - "extractLicenses": true, - "vendorChunk": false, - "buildOptimizer": true, - "budgets": [ - { - "type": "initial", - "maximumWarning": "2mb", - "maximumError": "5mb" - }, - { - "type": "anyComponentStyle", - "maximumWarning": "6kb", - "maximumError": "10kb" - } - ] - } - }, - "outputs": ["{options.outputPath}"] - }, - "serve": { - "executor": "@angular-devkit/build-angular:dev-server", - "options": { - "browserTarget": "alfa:build", - "proxyConfig": "proxy.conf.mjs" - }, - "configurations": { - "production": { - "browserTarget": "alfa:build:production" - } - } - }, - "extract-i18n": { - "executor": "@angular-devkit/build-angular:extract-i18n", - "options": { - "browserTarget": "alfa:build" - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "apps/alfa/src/**/*.ts", - "apps/alfa/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "apps/alfa/tsconfig.spec.json", - "jestConfig": "apps/alfa/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/apps/alfa"] - } - }, - "tags": [] + "name": "alfa", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "application", + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "sourceRoot": "apps/alfa/src", + "prefix": "alfa", + "targets": { + "build": { + "executor": "@angular-devkit/build-angular:browser", + "options": { + "allowedCommonJsDependencies": ["file-saver"], + "outputPath": "dist/apps/alfa", + "index": "apps/alfa/src/index.html", + "main": "apps/alfa/src/main.ts", + "polyfills": "apps/alfa/src/polyfills.ts", + "tsConfig": "apps/alfa/tsconfig.app.json", + "assets": [ + "apps/alfa/src/assets", + "apps/alfa/src/silent-refresh.html", + { + "input": "apps/alfa/src/favicon", + "glob": "**/*", + "output": "" + }, + { + "input": "libs/ui/src/lib/assets", + "glob": "**/*", + "output": "assets/icons" + } + ], + "styles": ["apps/alfa/src/styles/main.scss"], + "scripts": [], + "stylePreprocessorOptions": { + "includePaths": [ + "apps/alfa/src/styles/abstracts", + "apps/alfa/src/styles/material", + "node_modules/@angular", + "node_modules/include-media", + "node_modules/typeface-roboto" + ] + }, + "vendorChunk": true, + "extractLicenses": false, + "buildOptimizer": false, + "sourceMap": true, + "optimization": false, + "namedChunks": true + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "apps/alfa/src/environments/environment.ts", + "with": "apps/alfa/src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "namedChunks": false, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true, + "budgets": [ + { + "type": "initial", + "maximumWarning": "2mb", + "maximumError": "5mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "6kb", + "maximumError": "10kb" + } + ] + } + }, + "outputs": ["{options.outputPath}"] + }, + "serve": { + "executor": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "alfa:build", + "proxyConfig": "proxy.conf.mjs" + }, + "configurations": { + "production": { + "browserTarget": "alfa:build:production" + } + } + }, + "extract-i18n": { + "executor": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "alfa:build" + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["apps/alfa/src/**/*.ts", "apps/alfa/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "apps/alfa/tsconfig.spec.json", + "jestConfig": "apps/alfa/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/apps/alfa"] + } + }, + "tags": [] } diff --git a/alfa-client/apps/alfa/src/app/app.component.html b/alfa-client/apps/alfa/src/app/app.component.html index 19274543c522ce96599998cf15b177b30c4612d7..795e8eedc68e3886316b6317435415fa73c44876 100644 --- a/alfa-client/apps/alfa/src/app/app.component.html +++ b/alfa-client/apps/alfa/src/app/app.component.html @@ -24,15 +24,19 @@ --> <ng-container *ngIf="apiRoot$ | async as apiRoot"> - <ozgcloud-spinner [stateResource]="apiRoot"> - <alfa-header-container [apiRootStateResource]="apiRoot"></alfa-header-container> + <ozgcloud-spinner [stateResource]="apiRoot"> + <alfa-header-container [apiRootStateResource]="apiRoot"></alfa-header-container> - <div class="container"> - <main class="mat-app-background"><router-outlet></router-outlet></main> + <div class="container"> + <main class="mat-app-background"><router-outlet></router-outlet></main> - <section class="mat-app-background right-nav"> - <alfa-build-info *ngIf="apiRoot.resource" [apiRoot]="apiRoot.resource" data-test-id="build-info"></alfa-build-info> - </section> - </div> - </ozgcloud-spinner> + <section class="mat-app-background right-nav"> + <alfa-build-info + *ngIf="apiRoot.resource" + [apiRoot]="apiRoot.resource" + data-test-id="build-info" + ></alfa-build-info> + </section> + </div> + </ozgcloud-spinner> </ng-container> diff --git a/alfa-client/apps/alfa/src/app/app.component.scss b/alfa-client/apps/alfa/src/app/app.component.scss index 1ebfa234f6bc360bdf66124f9678766a2b1cacfe..5c499a2b70b35c18334696fd0862a60276f9895f 100644 --- a/alfa-client/apps/alfa/src/app/app.component.scss +++ b/alfa-client/apps/alfa/src/app/app.component.scss @@ -26,40 +26,40 @@ @import 'variables'; :host { - display: flex; - flex-direction: column; - height: 100vh; + display: flex; + flex-direction: column; + height: 100vh; } .container { - display: flex; - position: relative; - justify-content: space-between; - align-items: flex-start; - flex-grow: 1; - margin-top: $header-height; - border-left: 1rem solid $background; + display: flex; + position: relative; + justify-content: space-between; + align-items: flex-start; + flex-grow: 1; + margin-top: $header-height; + border-left: 1rem solid $background; } main { - position: relative; - flex-grow: 1; - max-width: calc(100vw - 2.25rem); - background-color: #fff; + position: relative; + flex-grow: 1; + max-width: calc(100vw - 2.25rem); + background-color: #fff; } .right-nav { - flex-shrink: 0; - position: sticky; - right: 0; - top: $header-height; - width: 1.25rem; - z-index: 1; - height: calc(100vh - $header-height); + flex-shrink: 0; + position: sticky; + right: 0; + top: $header-height; + width: 1.25rem; + z-index: 1; + height: calc(100vh - $header-height); } :host-context(.dark) { - .container { - border-color: $dark-background; - } + .container { + border-color: $dark-background; + } } diff --git a/alfa-client/apps/alfa/src/app/app.component.spec.ts b/alfa-client/apps/alfa/src/app/app.component.spec.ts index 03072f098f89bfaa5da2227b736754f6f5911f2f..5bf3f422b0147d964b21fd1f8f585b20c69f2e06 100644 --- a/alfa-client/apps/alfa/src/app/app.component.spec.ts +++ b/alfa-client/apps/alfa/src/app/app.component.spec.ts @@ -46,393 +46,388 @@ import * as VorgangNavigationUtil from 'libs/vorgang-shared/src/lib/vorgang-navi registerLocaleData(localeDe); describe('AppComponent', () => { - let component: AppComponent; - let fixture: ComponentFixture<AppComponent>; - - const envConfig = { authServer: 'http://' }; - const apiRootFacade = mock(ApiRootFacade); - const iconService = mock(IconService); - - const login = Promise.resolve(); - const authService = { ...mock(OAuthService), loadDiscoveryDocumentAndLogin: () => login, events: of(<OAuthEvent>{}) }; - - const navigationService = mock(NavigationService); - - const buildInfo: string = getDataTestIdOf('build-info'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - RouterTestingModule - ], - declarations: [ - AppComponent, - MockComponent(SpinnerComponent), - MockComponent(HeaderContainerComponent), - MockComponent(BuildInfoComponent) - ], - providers: [ - { - provide: ENVIRONMENT_CONFIG, - useValue: envConfig - }, - { - provide: ApiRootFacade, - useValue: apiRootFacade - }, - { - provide: OAuthService, - useValue: authService - }, - { - provide: IconService, - useValue: iconService - }, - { - provide: NavigationService, - useValue: navigationService - } - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(AppComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create the app', () => { - expect(component).toBeTruthy(); - }); - - it(`should call iconService registerIcons`, () => { - expect(iconService.registerIcons).toHaveBeenCalled(); - }); - - describe('buildInfo', () => { - - it('FIXME(Von der Reihenfolge abhaengig) should NOT be rendered if api root not loaded', () => { - // apiRootFacade.getApiRoot.mockReturnValue(of(createEmptyStateResource())); - // apiRootFacade.getApiRoot.mockReturnValue(apiRootSubj); - // fixture.detectChanges(); - // apiRootSubj.next(createEmptyStateResource()); - // component.ngOnInit(); - // fixture.detectChanges(); - // await login; - // console.info('Should NOT be rendered...'); - - notExistsAsHtmlElement(fixture, buildInfo); - }) + let component: AppComponent; + let fixture: ComponentFixture<AppComponent>; + + const envConfig = { authServer: 'http://' }; + const apiRootFacade = mock(ApiRootFacade); + const iconService = mock(IconService); + + const login = Promise.resolve(); + const authService = { + ...mock(OAuthService), + loadDiscoveryDocumentAndLogin: () => login, + events: of(<OAuthEvent>{}), + }; + + const navigationService = mock(NavigationService); + + const buildInfo: string = getDataTestIdOf('build-info'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [RouterTestingModule], + declarations: [ + AppComponent, + MockComponent(SpinnerComponent), + MockComponent(HeaderContainerComponent), + MockComponent(BuildInfoComponent), + ], + providers: [ + { + provide: ENVIRONMENT_CONFIG, + useValue: envConfig, + }, + { + provide: ApiRootFacade, + useValue: apiRootFacade, + }, + { + provide: OAuthService, + useValue: authService, + }, + { + provide: IconService, + useValue: iconService, + }, + { + provide: NavigationService, + useValue: navigationService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AppComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create the app', () => { + expect(component).toBeTruthy(); + }); + + it(`should call iconService registerIcons`, () => { + expect(iconService.registerIcons).toHaveBeenCalled(); + }); + + describe('buildInfo', () => { + it('FIXME(Von der Reihenfolge abhaengig) should NOT be rendered if api root not loaded', () => { + // apiRootFacade.getApiRoot.mockReturnValue(of(createEmptyStateResource())); + // apiRootFacade.getApiRoot.mockReturnValue(apiRootSubj); + // fixture.detectChanges(); + // apiRootSubj.next(createEmptyStateResource()); + // component.ngOnInit(); + // fixture.detectChanges(); + // await login; + // console.info('Should NOT be rendered...'); + + notExistsAsHtmlElement(fixture, buildInfo); + }); + + it.skip('should be rendered', async () => { + apiRootFacade.getApiRoot.mockReturnValue(of(createStateResource(createApiRootResource()))); + // fixture.detectChanges(); + // apiRootSubj.next(createStateResource(createApiRootResource())); + component.ngOnInit(); + // fixture.detectChanges(); + await login; + + // console.info('Should be rendered...'); + + const header = fixture.nativeElement.querySelector(buildInfo); + expect(header).toBeInstanceOf(HTMLElement); + }); + }); + + describe('ngOnInit', () => { + it('should call proceedWithLogin', () => { + component.proceedWithLogin = jest.fn(); + + component.ngOnInit(); + + expect(component.proceedWithLogin).toHaveBeenCalled(); + }); + + it('should call listenToOAuthEvents', () => { + component.listenToOAuthEvents = jest.fn(); - it.skip('should be rendered', async () => { - apiRootFacade.getApiRoot.mockReturnValue(of(createStateResource(createApiRootResource()))); - // fixture.detectChanges(); - // apiRootSubj.next(createStateResource(createApiRootResource())); - component.ngOnInit(); - // fixture.detectChanges(); - await login; + component.ngOnInit(); + + expect(component.listenToOAuthEvents).toHaveBeenCalled(); + }); + }); - // console.info('Should be rendered...'); + describe('proceedWithLogin', () => { + it('should configure oAuthService', () => { + const configuration: AuthConfig = {}; + component.buildConfiguration = jest.fn().mockReturnValue(configuration); - const header = fixture.nativeElement.querySelector(buildInfo); - expect(header).toBeInstanceOf(HTMLElement); - }) - }) + component.proceedWithLogin(); + + expect(authService.configure).toHaveBeenCalledWith(configuration); + }); - describe('ngOnInit', () => { - it('should call proceedWithLogin', () => { - component.proceedWithLogin = jest.fn(); + it('should build configuration', () => { + component.buildConfiguration = jest.fn(); - component.ngOnInit(); + component.proceedWithLogin(); - expect(component.proceedWithLogin).toHaveBeenCalled(); - }) + expect(component.buildConfiguration).toHaveBeenCalled(); + }); - it('should call listenToOAuthEvents', () => { - component.listenToOAuthEvents = jest.fn(); + it('should setup automatic silent refresh', () => { + component.proceedWithLogin(); - component.ngOnInit(); + expect(authService.setupAutomaticSilentRefresh).toHaveBeenCalled(); + }); - expect(component.listenToOAuthEvents).toHaveBeenCalled(); - }) - }) + it('should call loadDiscoveryDocumentAndLogin', () => { + const spy = jest.spyOn(authService, 'loadDiscoveryDocumentAndLogin'); - describe('proceedWithLogin', () => { + component.proceedWithLogin(); - it('should configure oAuthService', () => { - const configuration: AuthConfig = {}; - component.buildConfiguration = jest.fn().mockReturnValue(configuration); + expect(spy).toHaveBeenCalled(); + }); + }); - component.proceedWithLogin(); + describe('listenToOAuthEvents', () => { + it('should call consideredAsLoginEvent', () => { + component.consideredAsLoginEvent = jest.fn(); - expect(authService.configure).toHaveBeenCalledWith(configuration); - }) + component.listenToOAuthEvents(); - it('should build configuration', () => { - component.buildConfiguration = jest.fn(); + expect(component.consideredAsLoginEvent).toHaveBeenCalled(); + }); - component.proceedWithLogin(); + it('should call consideredAsPageReloadEvent', () => { + component.consideredAsPageReloadEvent = jest.fn(); - expect(component.buildConfiguration).toHaveBeenCalled(); - }) + component.listenToOAuthEvents(); - it('should setup automatic silent refresh', () => { - component.proceedWithLogin(); + expect(component.consideredAsPageReloadEvent).toHaveBeenCalled(); + }); - expect(authService.setupAutomaticSilentRefresh).toHaveBeenCalled(); - }) + it('should call loadApiRootAndNavigate at event "token_received"', () => { + component.loadApiRootAndNavigate = jest.fn(); + authService.events = of({ type: 'token_received' }); - it('should call loadDiscoveryDocumentAndLogin', () => { - const spy = jest.spyOn(authService, 'loadDiscoveryDocumentAndLogin'); + component.listenToOAuthEvents(); - component.proceedWithLogin(); + expect(component.loadApiRootAndNavigate).toHaveBeenCalled(); + }); - expect(spy).toHaveBeenCalled(); - }) - }) + it('should call loadApiRootAndNavigate at event "discovery_document_loaded"', () => { + component.loadApiRootAndNavigate = jest.fn(); + authService.events = of({ type: 'discovery_document_loaded' }); + jest.spyOn(authService, 'hasValidAccessToken').mockReturnValue(true); + jest.spyOn(authService, 'hasValidIdToken').mockReturnValue(true); - describe('listenToOAuthEvents', () => { - it('should call consideredAsLoginEvent', () => { - component.consideredAsLoginEvent = jest.fn(); + component.listenToOAuthEvents(); - component.listenToOAuthEvents(); + expect(component.loadApiRootAndNavigate).toHaveBeenCalled(); + }); - expect(component.consideredAsLoginEvent).toHaveBeenCalled(); - }) + it('should not call loadApiRootAndNavigate at other event', () => { + component.loadApiRootAndNavigate = jest.fn(); + authService.events = of({ type: 'token_error' }); - it('should call consideredAsPageReloadEvent', () => { - component.consideredAsPageReloadEvent = jest.fn(); + component.listenToOAuthEvents(); - component.listenToOAuthEvents(); + expect(component.loadApiRootAndNavigate).not.toHaveBeenCalled(); + }); + }); - expect(component.consideredAsPageReloadEvent).toHaveBeenCalled(); + describe('consideredAsLoginEvent', () => { + it('should return true if event is "token_received"', () => { + const event: string = 'token_received'; - }) + const result: boolean = component.consideredAsLoginEvent(event); - it('should call loadApiRootAndNavigate at event "token_received"', () => { - component.loadApiRootAndNavigate = jest.fn(); - authService.events = of({type: 'token_received'}); + expect(result).toBeTruthy(); + }); - component.listenToOAuthEvents(); + it('should return false if event is not "token_received"', () => { + const event: string = 'something_else'; - expect(component.loadApiRootAndNavigate).toHaveBeenCalled(); - }) + const result: boolean = component.consideredAsLoginEvent(event); - it('should call loadApiRootAndNavigate at event "discovery_document_loaded"', () => { - component.loadApiRootAndNavigate = jest.fn(); - authService.events = of({type: 'discovery_document_loaded'}); - jest.spyOn(authService, 'hasValidAccessToken').mockReturnValue(true); - jest.spyOn(authService, 'hasValidIdToken').mockReturnValue(true); + expect(result).toBeFalsy(); + }); + }); - component.listenToOAuthEvents(); + describe('consideredAsPageReloadEvent', () => { + it('should return true if event is "discovery_document_loaded" and tokens are valid', () => { + component.hasValidToken = jest.fn().mockReturnValue(true); + const event: string = 'discovery_document_loaded'; - expect(component.loadApiRootAndNavigate).toHaveBeenCalled(); - }) + const result: boolean = component.consideredAsPageReloadEvent(event); - it('should not call loadApiRootAndNavigate at other event', () => { - component.loadApiRootAndNavigate = jest.fn(); - authService.events = of({type: 'token_error'}); + expect(result).toBeTruthy(); + }); - component.listenToOAuthEvents(); + it('should return false if event is "discovery_document_loaded" and tokens are invalid', () => { + component.hasValidToken = jest.fn().mockReturnValue(false); + const event: string = 'discovery_document_loaded'; - expect(component.loadApiRootAndNavigate).not.toHaveBeenCalled(); - }) - }) + const result: boolean = component.consideredAsPageReloadEvent(event); - describe('consideredAsLoginEvent', () => { - it('should return true if event is "token_received"', () => { - const event: string = 'token_received'; + expect(result).toBeFalsy(); + }); - const result: boolean = component.consideredAsLoginEvent(event); + it('should return false if event is not "discovery_document_loaded" and tokens are valid', () => { + component.hasValidToken = jest.fn().mockReturnValue(true); + const event: string = 'something_else'; - expect(result).toBeTruthy(); - }) + const result: boolean = component.consideredAsPageReloadEvent(event); - it('should return false if event is not "token_received"', () => { - const event: string = 'something_else'; + expect(result).toBeFalsy(); + }); - const result: boolean = component.consideredAsLoginEvent(event); + it('should return false if event is not "discovery_document_loaded" and tokens are invalid', () => { + component.hasValidToken = jest.fn().mockReturnValue(false); + const event: string = 'something_else'; - expect(result).toBeFalsy(); - }) - }) + const result: boolean = component.consideredAsPageReloadEvent(event); - describe('consideredAsPageReloadEvent', () => { - it('should return true if event is "discovery_document_loaded" and tokens are valid', () => { - component.hasValidToken = jest.fn().mockReturnValue(true); - const event: string = 'discovery_document_loaded'; + expect(result).toBeFalsy(); + }); + }); - const result: boolean = component.consideredAsPageReloadEvent(event); + describe('hasValidToken', () => { + it('should return true if both tokens are valid', () => { + jest.spyOn(authService, 'hasValidAccessToken').mockReturnValue(true); + jest.spyOn(authService, 'hasValidIdToken').mockReturnValue(true); - expect(result).toBeTruthy(); - }) + const result: boolean = component.hasValidToken(); - it('should return false if event is "discovery_document_loaded" and tokens are invalid', () => { - component.hasValidToken = jest.fn().mockReturnValue(false); - const event: string = 'discovery_document_loaded'; + expect(result).toBeTruthy(); + }); - const result: boolean = component.consideredAsPageReloadEvent(event); + it('should return false if access token is invalid', () => { + jest.spyOn(authService, 'hasValidAccessToken').mockReturnValue(false); + jest.spyOn(authService, 'hasValidIdToken').mockReturnValue(true); - expect(result).toBeFalsy(); - }) + const result: boolean = component.hasValidToken(); - it('should return false if event is not "discovery_document_loaded" and tokens are valid', () => { - component.hasValidToken = jest.fn().mockReturnValue(true); - const event: string = 'something_else'; + expect(result).toBeFalsy(); + }); - const result: boolean = component.consideredAsPageReloadEvent(event); + it('should return false if id token is invalid', () => { + jest.spyOn(authService, 'hasValidAccessToken').mockReturnValue(true); + jest.spyOn(authService, 'hasValidIdToken').mockReturnValue(false); - expect(result).toBeFalsy(); - }) + const result: boolean = component.hasValidToken(); - it('should return false if event is not "discovery_document_loaded" and tokens are invalid', () => { - component.hasValidToken = jest.fn().mockReturnValue(false); - const event: string = 'something_else'; + expect(result).toBeFalsy(); + }); - const result: boolean = component.consideredAsPageReloadEvent(event); + it('should return false if both tokens are invalid', () => { + jest.spyOn(authService, 'hasValidAccessToken').mockReturnValue(false); + jest.spyOn(authService, 'hasValidIdToken').mockReturnValue(false); - expect(result).toBeFalsy(); - }) - }) + const result: boolean = component.hasValidToken(); - describe('hasValidToken', () => { - it('should return true if both tokens are valid', () => { - jest.spyOn(authService, 'hasValidAccessToken').mockReturnValue(true); - jest.spyOn(authService, 'hasValidIdToken').mockReturnValue(true); + expect(result).toBeFalsy(); + }); + }); - const result: boolean = component.hasValidToken(); + describe('loadApiRootAndNavigate', () => { + describe('apiRootResource loaded', () => { + const apiRootStateResource = createStateResource(createApiRootResource()); - expect(result).toBeTruthy(); - }) + beforeEach(() => { + apiRootFacade.getApiRoot.mockReturnValue(of(apiRootStateResource)); + }); - it('should return false if access token is invalid', () => { - jest.spyOn(authService, 'hasValidAccessToken').mockReturnValue(false); - jest.spyOn(authService, 'hasValidIdToken').mockReturnValue(true); + it('should call apiRootFacade.getApiRoot to get the apiRoot', () => { + component.loadApiRootAndNavigate(); - const result: boolean = component.hasValidToken(); + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }); - expect(result).toBeFalsy(); - }) + it('should call navigationService.navigate', (done) => { + const spy = jest.spyOn(navigationService, 'navigate'); - it('should return false if id token is invalid', () => { - jest.spyOn(authService, 'hasValidAccessToken').mockReturnValue(true); - jest.spyOn(authService, 'hasValidIdToken').mockReturnValue(false); + component.loadApiRootAndNavigate().subscribe(() => { + expect(spy).toHaveBeenCalled(); + done(); + }); + }); - const result: boolean = component.hasValidToken(); + it('should call buildInitialPath', (done) => { + component.buildInitialPath = jest.fn(); - expect(result).toBeFalsy(); - }) + component.loadApiRootAndNavigate().subscribe(() => { + expect(component.buildInitialPath).toHaveBeenCalled(); + done(); + }); + }); + }); - it('should return false if both tokens are invalid', () => { - jest.spyOn(authService, 'hasValidAccessToken').mockReturnValue(false); - jest.spyOn(authService, 'hasValidIdToken').mockReturnValue(false); + describe('apiRoot.resource is null', () => { + it.skip('should not call navigationService.navigate', (done) => { + apiRootFacade.getApiRoot.mockReturnValue(of(createEmptyStateResource())); + const spy = jest.spyOn(navigationService, 'navigate'); - const result: boolean = component.hasValidToken(); + component.loadApiRootAndNavigate().subscribe(() => { + expect(spy).not.toHaveBeenCalled(); + done(); + }); + }); + }); + }); - expect(result).toBeFalsy(); - }) - }) + describe('buildInitialPath', () => { + describe('with existing window.location.pathname', () => { + const path: string = '/vorgang/xyz'; + const url: string = 'http://localhost' + path; - describe('loadApiRootAndNavigate', () => { + beforeEach(() => { + setWindowLocationUrl(url); + }); - describe('apiRootResource loaded', () => { - const apiRootStateResource = createStateResource(createApiRootResource()); + it('should not call buildPathSegmentsFromLocalStorage', () => { + const spy = jest.spyOn(VorgangNavigationUtil, 'buildPathSegmentsFromLocalStorage'); - beforeEach(() => { - apiRootFacade.getApiRoot.mockReturnValue(of(apiRootStateResource)); - }) + component.buildInitialPath(); - it('should call apiRootFacade.getApiRoot to get the apiRoot', () => { - component.loadApiRootAndNavigate(); + expect(spy).not.toHaveBeenCalled(); + }); - expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); - }) + it('should return window.location.pathname', () => { + const redirectPath: string = component.buildInitialPath(); - it('should call navigationService.navigate', (done) => { - const spy = jest.spyOn(navigationService, 'navigate'); + expect(redirectPath).toBe(path); + }); + }); - component.loadApiRootAndNavigate().subscribe(() => { - expect(spy).toHaveBeenCalled(); - done(); - }); - }) + describe('with empty window.location.pathname', () => { + const url: string = 'http://localhost/'; - it('should call buildInitialPath', (done) => { - component.buildInitialPath = jest.fn(); + beforeEach(() => { + setWindowLocationUrl(url); + }); - component.loadApiRootAndNavigate().subscribe(() => { - expect(component.buildInitialPath).toHaveBeenCalled(); - done(); - }); - }) + it('should call buildPathSegmentsFromLocalStorage', () => { + const spy = jest.spyOn(VorgangNavigationUtil, 'buildPathSegmentsFromLocalStorage'); - }) + component.buildInitialPath(); - describe('apiRoot.resource is null', () => { - it.skip('should not call navigationService.navigate', (done) => { - apiRootFacade.getApiRoot.mockReturnValue(of(createEmptyStateResource())); - const spy = jest.spyOn(navigationService, 'navigate'); + expect(spy).toHaveBeenCalled(); + }); - component.loadApiRootAndNavigate().subscribe(() => { - expect(spy).not.toHaveBeenCalled(); - done(); - }); - }) - }) + it('should return path segments from localStorage', () => { + const pathSegments: string[] = ['alle', 'angenommen']; + jest + .spyOn(VorgangNavigationUtil, 'buildPathSegmentsFromLocalStorage') + .mockReturnValue(pathSegments); - }) + const redirectUri: string = component.buildInitialPath(); - describe('buildInitialPath', () => { - - describe('with existing window.location.pathname', () => { - const path: string = '/vorgang/xyz'; - const url: string = 'http://localhost' + path; - - beforeEach(() => { - setWindowLocationUrl(url); - }) - - it('should not call buildPathSegmentsFromLocalStorage', () => { - const spy = jest.spyOn(VorgangNavigationUtil, 'buildPathSegmentsFromLocalStorage'); - - component.buildInitialPath(); - - expect(spy).not.toHaveBeenCalled(); - }) - - - it('should return window.location.pathname', () => { - const redirectPath: string = component.buildInitialPath(); - - expect(redirectPath).toBe(path); - }) - }) - - describe('with empty window.location.pathname', () => { - const url: string = 'http://localhost/'; - - beforeEach(() => { - setWindowLocationUrl(url); - }) - - it('should call buildPathSegmentsFromLocalStorage', () => { - const spy = jest.spyOn(VorgangNavigationUtil, 'buildPathSegmentsFromLocalStorage'); - - component.buildInitialPath(); - - expect(spy).toHaveBeenCalled(); - }) - - it('should return path segments from localStorage', () => { - const pathSegments: string[] = ['alle', 'angenommen']; - jest.spyOn(VorgangNavigationUtil, 'buildPathSegmentsFromLocalStorage').mockReturnValue(pathSegments); - - const redirectUri: string = component.buildInitialPath(); - - expect(redirectUri).toBe('/alle/angenommen'); - }) - }) - - }) + expect(redirectUri).toBe('/alle/angenommen'); + }); + }); + }); }); diff --git a/alfa-client/apps/alfa/src/app/app.component.ts b/alfa-client/apps/alfa/src/app/app.component.ts index 5a80d4ca28d3084416e11dc74774307aed19f297..db8d9b623124ec7b0b5a1cdc259d3d919742220e 100644 --- a/alfa-client/apps/alfa/src/app/app.component.ts +++ b/alfa-client/apps/alfa/src/app/app.component.ts @@ -34,91 +34,94 @@ import { Environment } from 'libs/environment-shared/src/lib/environment.model'; import { Observable, Subscription, filter, tap } from 'rxjs'; @Component({ - selector: 'alfa-root', - templateUrl: './app.component.html', - styleUrls: ['./app.component.scss'] + selector: 'alfa-root', + templateUrl: './app.component.html', + styleUrls: ['./app.component.scss'], }) export class AppComponent implements OnInit { - - public apiRoot$: Observable<StateResource<ApiRootResource>>; - private oAuthEventSubscription: Subscription; - - constructor( - @Inject(ENVIRONMENT_CONFIG) private envConfig: Environment, - private apiRootFacade: ApiRootFacade, - private iconService: IconService, - private oAuthService: OAuthService, - private navigationService: NavigationService - ) { - this.iconService.registerIcons(); - } - - ngOnInit(): void { - this.proceedWithLogin(); - this.listenToOAuthEvents(); - } - - proceedWithLogin(): void { - this.oAuthService.configure(this.buildConfiguration()); - this.oAuthService.setupAutomaticSilentRefresh(); - this.oAuthService.tokenValidationHandler = new JwksValidationHandler(); - this.oAuthService.loadDiscoveryDocumentAndLogin(); - } - - buildConfiguration(): AuthConfig { - return { - // Url of the Identity Provider - issuer: this.envConfig.authServer + '/realms/' + this.envConfig.realm, - - // URL of the SPA to redirect the user to after login - redirectUri: window.location.origin + this.buildInitialPath(), - postLogoutRedirectUri: window.location.origin + '/', - - // URL of the SPA to redirect the user after silent refresh - silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html', - useSilentRefresh: true, - - // The SPA's id. The SPA is registerd with this id at the auth-server - clientId: this.envConfig.clientId, - - // set the scope for the permissions the client should request - scope: 'openid profile email', - requireHttps: false - }; - } - - buildInitialPath(): string { - return window.location.pathname === '/' - ? '/' + buildPathSegmentsFromLocalStorage().join('/') - : window.location.pathname; - } - - listenToOAuthEvents(): void { - this.oAuthEventSubscription = this.oAuthService.events.pipe( - filter((event: OAuthEvent) => this.consideredAsLoginEvent(event.type) || this.consideredAsPageReloadEvent(event.type)) - ).subscribe(() => this.apiRoot$ = this.loadApiRootAndNavigate()); - } - - consideredAsLoginEvent(eventType: string): boolean { - return eventType === 'token_received'; - } - - consideredAsPageReloadEvent(eventType: string): boolean { - return eventType === 'discovery_document_loaded' && this.hasValidToken(); - } - - hasValidToken(): boolean { - return this.oAuthService.hasValidAccessToken() && this.oAuthService.hasValidIdToken(); - } - - loadApiRootAndNavigate(): Observable<StateResource<ApiRootResource>> { - return this.apiRootFacade.getApiRoot().pipe( - filter(apiRoot => isNotNull(apiRoot.resource)), - tap(() => { - this.navigationService.navigate(this.buildInitialPath()); - this.oAuthEventSubscription.unsubscribe(); - }) - ); - } + public apiRoot$: Observable<StateResource<ApiRootResource>>; + private oAuthEventSubscription: Subscription; + + constructor( + @Inject(ENVIRONMENT_CONFIG) private envConfig: Environment, + private apiRootFacade: ApiRootFacade, + private iconService: IconService, + private oAuthService: OAuthService, + private navigationService: NavigationService, + ) { + this.iconService.registerIcons(); + } + + ngOnInit(): void { + this.proceedWithLogin(); + this.listenToOAuthEvents(); + } + + proceedWithLogin(): void { + this.oAuthService.configure(this.buildConfiguration()); + this.oAuthService.setupAutomaticSilentRefresh(); + this.oAuthService.tokenValidationHandler = new JwksValidationHandler(); + this.oAuthService.loadDiscoveryDocumentAndLogin(); + } + + buildConfiguration(): AuthConfig { + return { + // Url of the Identity Provider + issuer: this.envConfig.authServer + '/realms/' + this.envConfig.realm, + + // URL of the SPA to redirect the user to after login + redirectUri: window.location.origin + this.buildInitialPath(), + postLogoutRedirectUri: window.location.origin + '/', + + // URL of the SPA to redirect the user after silent refresh + silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html', + useSilentRefresh: true, + + // The SPA's id. The SPA is registerd with this id at the auth-server + clientId: this.envConfig.clientId, + + // set the scope for the permissions the client should request + scope: 'openid profile email', + requireHttps: false, + }; + } + + buildInitialPath(): string { + return window.location.pathname === '/' ? + '/' + buildPathSegmentsFromLocalStorage().join('/') + : window.location.pathname; + } + + listenToOAuthEvents(): void { + this.oAuthEventSubscription = this.oAuthService.events + .pipe( + filter( + (event: OAuthEvent) => + this.consideredAsLoginEvent(event.type) || this.consideredAsPageReloadEvent(event.type), + ), + ) + .subscribe(() => (this.apiRoot$ = this.loadApiRootAndNavigate())); + } + + consideredAsLoginEvent(eventType: string): boolean { + return eventType === 'token_received'; + } + + consideredAsPageReloadEvent(eventType: string): boolean { + return eventType === 'discovery_document_loaded' && this.hasValidToken(); + } + + hasValidToken(): boolean { + return this.oAuthService.hasValidAccessToken() && this.oAuthService.hasValidIdToken(); + } + + loadApiRootAndNavigate(): Observable<StateResource<ApiRootResource>> { + return this.apiRootFacade.getApiRoot().pipe( + filter((apiRoot) => isNotNull(apiRoot.resource)), + tap(() => { + this.navigationService.navigate(this.buildInitialPath()); + this.oAuthEventSubscription.unsubscribe(); + }), + ); + } } - diff --git a/alfa-client/apps/alfa/src/app/app.module.spec.ts b/alfa-client/apps/alfa/src/app/app.module.spec.ts index 48a7d51247431c2d3642ec728f5f6889c36b6c9a..664002ee91557326a8aad3ab91de81411a90f535 100644 --- a/alfa-client/apps/alfa/src/app/app.module.spec.ts +++ b/alfa-client/apps/alfa/src/app/app.module.spec.ts @@ -21,17 +21,17 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { TestBed } from "@angular/core/testing"; -import { AppModule } from "./app.module"; +import { TestBed } from '@angular/core/testing'; +import { AppModule } from './app.module'; describe('AppModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [AppModule] - }) - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [AppModule], + }); + }); - it('should create', () => { - expect(AppModule).toBeDefined(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(AppModule).toBeDefined(); + }); +}); diff --git a/alfa-client/apps/alfa/src/app/app.module.ts b/alfa-client/apps/alfa/src/app/app.module.ts index ad4ea87e381fa9ce6f0005455532b31988543a64..f5d4ecaa9ffc04d3cd69590ef9fc964b2c01dd86 100644 --- a/alfa-client/apps/alfa/src/app/app.module.ts +++ b/alfa-client/apps/alfa/src/app/app.module.ts @@ -46,55 +46,55 @@ import { AppComponent } from './app.component'; registerLocaleData(localeDe); const routes: Routes = [ - { - path: '', - loadChildren: () => import('@alfa-client/vorgang').then(m => m.VorgangModule) - } + { + path: '', + loadChildren: () => import('@alfa-client/vorgang').then((m) => m.VorgangModule), + }, ]; @NgModule({ - declarations: [ - AppComponent, - ], - imports: [ - BrowserModule, - HttpClientModule, - BrowserAnimationsModule, - RouterModule.forRoot(routes, { - initialNavigation: 'disabled', - onSameUrlNavigation: 'reload', + declarations: [AppComponent], + imports: [ + BrowserModule, + HttpClientModule, + BrowserAnimationsModule, + RouterModule.forRoot(routes, { + initialNavigation: 'disabled', + onSameUrlNavigation: 'reload', + }), + UiModule, + EnvironmentModule, + OAuthModule.forRoot({ + resourceServer: { + sendAccessToken: true, + }, + }), + ApiRootModule, + NavigationModule, + AppSharedModule, + StoreModule.forRoot( + {}, + { + metaReducers: [], + runtimeChecks: { + strictActionImmutability: true, + strictStateImmutability: true, + }, + }, + ), + EffectsModule.forRoot([]), + environment.production ? [] : StoreDevtoolsModule.instrument(), + StoreRouterConnectingModule.forRoot(), - }), - UiModule, - EnvironmentModule, - OAuthModule.forRoot({ - resourceServer: { - sendAccessToken: true - }, - }), - ApiRootModule, - NavigationModule, - AppSharedModule, - StoreModule.forRoot({}, { - metaReducers: [], - runtimeChecks: { - strictActionImmutability: true, - strictStateImmutability: true - } - }), - EffectsModule.forRoot([]), - environment.production ? [] : StoreDevtoolsModule.instrument(), - StoreRouterConnectingModule.forRoot(), - - // Workaround: load any module depending on ApiRootActions.loadApiRootSuccess - // TODO Check if a future NgRx version will solve Lazy Loading + Effects.forFeature() - HintSharedModule - // - ], - providers: [ - { provide: LOCALE_ID, useValue: 'de' }, - { provide: UrlSerializer, useClass: OzgCloudUrlSerializer } - ], - bootstrap: [AppComponent] + // Workaround: load any module depending on ApiRootActions.loadApiRootSuccess + // TODO Check if a future NgRx version will solve Lazy Loading + Effects.forFeature() + HintSharedModule, + // + ], + providers: [ + { provide: LOCALE_ID, useValue: 'de' }, + { provide: UrlSerializer, useClass: OzgCloudUrlSerializer }, + ], + bootstrap: [AppComponent], }) -export class AppModule { } +export class AppModule {} diff --git a/alfa-client/apps/alfa/src/environments/environment.prod.ts b/alfa-client/apps/alfa/src/environments/environment.prod.ts index 8a6d639364da456e454e104a81c9c81886dbc7eb..2fe1167acb0efa94f13f4552c3596b0857cd1ffc 100644 --- a/alfa-client/apps/alfa/src/environments/environment.prod.ts +++ b/alfa-client/apps/alfa/src/environments/environment.prod.ts @@ -22,6 +22,6 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export const environment = { - production: true, - environmentUrl: null, + production: true, + environmentUrl: null, }; diff --git a/alfa-client/apps/alfa/src/environments/environment.ts b/alfa-client/apps/alfa/src/environments/environment.ts index b6b45f8ad8f2f55c7abf25792149bd91ffb5e7fa..24745931699763efa8d08c904051b5903fe5ddde 100644 --- a/alfa-client/apps/alfa/src/environments/environment.ts +++ b/alfa-client/apps/alfa/src/environments/environment.ts @@ -26,8 +26,8 @@ // The list of file replacements can be found in `angular.json`. export const environment = { - production: false, - environmentUrl: null + production: false, + environmentUrl: null, }; /* diff --git a/alfa-client/apps/alfa/src/favicon/site.webmanifest b/alfa-client/apps/alfa/src/favicon/site.webmanifest index 56ae4d7feec28ecc7b740939b36fe53d992aaa93..4b3316ddbd4ee5702059eebef55d0634b1aa8b3d 100644 --- a/alfa-client/apps/alfa/src/favicon/site.webmanifest +++ b/alfa-client/apps/alfa/src/favicon/site.webmanifest @@ -1,19 +1,19 @@ { - "name": "Alfa", - "short_name": "Alfa - Allgemeines Fachverfahren", - "icons": [ - { - "src": "/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "theme_color": "#ffffff", - "background_color": "#ffffff", - "display": "standalone" + "name": "Alfa", + "short_name": "Alfa - Allgemeines Fachverfahren", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" } diff --git a/alfa-client/apps/alfa/src/index.html b/alfa-client/apps/alfa/src/index.html index 8c0ca5b41fdd81f2ec97265d8b9d93f2d29d6106..d7173d85eabb61e97dee0175289b9a1d829e002c 100644 --- a/alfa-client/apps/alfa/src/index.html +++ b/alfa-client/apps/alfa/src/index.html @@ -23,21 +23,21 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<!DOCTYPE html> +<!doctype html> <html lang="de"> -<head> - <meta charset="utf-8"/> - <title>Alfa</title> - <base href="/"/> - <meta content="width=device-width, initial-scale=1" name="viewport"/> - <link rel="icon" href="/favicon.ico" sizes="any"> - <link rel="icon" href="/favicon.svg" type="image/svg+xml"> - <link rel="apple-touch-icon" href="/apple-touch-icon.png"/> - <link rel="manifest" href="/site.webmanifest"/> - <meta name="msapplication-TileColor" content="#ffffff"> - <meta name="theme-color" content="#ffffff"> -</head> -<body class="mat-typography mat-app-background"> -<alfa-root></alfa-root> -</body> + <head> + <meta charset="utf-8" /> + <title>Alfa</title> + <base href="/" /> + <meta content="width=device-width, initial-scale=1" name="viewport" /> + <link rel="icon" href="/favicon.ico" sizes="any" /> + <link rel="icon" href="/favicon.svg" type="image/svg+xml" /> + <link rel="apple-touch-icon" href="/apple-touch-icon.png" /> + <link rel="manifest" href="/site.webmanifest" /> + <meta name="msapplication-TileColor" content="#ffffff" /> + <meta name="theme-color" content="#ffffff" /> + </head> + <body class="mat-typography mat-app-background"> + <alfa-root></alfa-root> + </body> </html> diff --git a/alfa-client/apps/alfa/src/main.ts b/alfa-client/apps/alfa/src/main.ts index 45438374fd1ec056313a92a23414851121aea3d2..badb69907f88a9f9e82b724d9e3a31530dd02b87 100644 --- a/alfa-client/apps/alfa/src/main.ts +++ b/alfa-client/apps/alfa/src/main.ts @@ -29,15 +29,15 @@ import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; loadEnvironment(environment.environmentUrl).then((env) => { - if (isNil(env)) { - console.error('Connection Error: environment is undefined'); - return; - } - if (env.production) { - enableProdMode(); - } + if (isNil(env)) { + console.error('Connection Error: environment is undefined'); + return; + } + if (env.production) { + enableProdMode(); + } - platformBrowserDynamic() - .bootstrapModule(AppModule) - .catch((err) => console.log(err)); -}); \ No newline at end of file + platformBrowserDynamic() + .bootstrapModule(AppModule) + .catch((err) => console.log(err)); +}); diff --git a/alfa-client/apps/alfa/src/silent-refresh.html b/alfa-client/apps/alfa/src/silent-refresh.html index e4244b37497b8980ac91c44f6300575ee90dd209..6cc26b2f4c94ace9b82dd96058da0cbe41c8affa 100644 --- a/alfa-client/apps/alfa/src/silent-refresh.html +++ b/alfa-client/apps/alfa/src/silent-refresh.html @@ -23,15 +23,18 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<!DOCTYPE html> +<!doctype html> <html lang="de"> -<head> - <meta charset="utf-8"/> - <title>silent refresh</title> -</head> -<body> -<script> - (window.opener || window.parent).postMessage(location.hash || ('#' + location.search), location.origin); -</script> -</body> + <head> + <meta charset="utf-8" /> + <title>silent refresh</title> + </head> + <body> + <script> + (window.opener || window.parent).postMessage( + location.hash || '#' + location.search, + location.origin, + ); + </script> + </body> </html> diff --git a/alfa-client/apps/alfa/src/styles/abstracts/_breakpoints.scss b/alfa-client/apps/alfa/src/styles/abstracts/_breakpoints.scss index d89ad7073332b65edc9fc82070e334e972cd5ba4..24a64d7b5737ea1c6af9639b5cba5b852f189f95 100644 --- a/alfa-client/apps/alfa/src/styles/abstracts/_breakpoints.scss +++ b/alfa-client/apps/alfa/src/styles/abstracts/_breakpoints.scss @@ -22,9 +22,9 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ $breakpoints: ( - phone: 320px, - tablet: 768px, - desktop: 1024px, - largeDesktop: 1240px, - xxlDesktop: 1450px + phone: 320px, + tablet: 768px, + desktop: 1024px, + largeDesktop: 1240px, + xxlDesktop: 1450px, ); diff --git a/alfa-client/apps/alfa/src/styles/abstracts/_functions.scss b/alfa-client/apps/alfa/src/styles/abstracts/_functions.scss index b75d4b92d6975206765e56639bf224a3c7bba666..793cf4a50121eb8255b554a6b2af646df3c06ecc 100644 --- a/alfa-client/apps/alfa/src/styles/abstracts/_functions.scss +++ b/alfa-client/apps/alfa/src/styles/abstracts/_functions.scss @@ -3,6 +3,6 @@ @import 'variables'; @function pxToRem($px) { - $rem: math.div($px, $default-font-size); - @return #{$rem}rem; + $rem: math.div($px, $default-font-size); + @return #{$rem}rem; } diff --git a/alfa-client/apps/alfa/src/styles/abstracts/_variables.scss b/alfa-client/apps/alfa/src/styles/abstracts/_variables.scss index 9a5f0140059c6c5ffc5049d79a46cf4f27ded0b1..21fa9559b6dcd7eafb4486651d33fb27b07d89c2 100644 --- a/alfa-client/apps/alfa/src/styles/abstracts/_variables.scss +++ b/alfa-client/apps/alfa/src/styles/abstracts/_variables.scss @@ -51,27 +51,30 @@ $statusBeschiedenPalette: mat.define-palette(mat.$green-palette, 600, 300, 800); $statusAbgeschlossenPalette: mat.define-palette(mat.$green-palette, 600, 300, 800); $statusVerworfenPalette: mat.define-palette(mat.$gray-palette, 600, 300, 800); -$alfaTheme: mat.define-light-theme(( - color: ( - primary: $primaryPalette, - accent: $accentPalette, - warn: $warnPalette, - ) -)); - +$alfaTheme: mat.define-light-theme( + ( + color: ( + primary: $primaryPalette, + accent: $accentPalette, + warn: $warnPalette, + ), + ) +); // dark theme $primaryDarkPalette: mat.define-palette(mat.$yellow-palette, 700, 300, 900); $accentDarkPalette: mat.define-palette(mat.$brown-palette, 600, 300, 800); -$alfaDarkTheme: mat.define-dark-theme(( - color: ( - primary: $primaryDarkPalette, - accent: $accentDarkPalette, - warn: $warnPalette - ) -)); +$alfaDarkTheme: mat.define-dark-theme( + ( + color: ( + primary: $primaryDarkPalette, + accent: $accentDarkPalette, + warn: $warnPalette, + ), + ) +); $default-font-size: 16px; -$iconHeight: 24px; \ No newline at end of file +$iconHeight: 24px; diff --git a/alfa-client/apps/alfa/src/styles/base/_setup.scss b/alfa-client/apps/alfa/src/styles/base/_setup.scss index 02ffa48cc627960dd9224a2043e76b943575ca06..4c231070ae2cd650b289be0ba11fc82c61875ce2 100644 --- a/alfa-client/apps/alfa/src/styles/base/_setup.scss +++ b/alfa-client/apps/alfa/src/styles/base/_setup.scss @@ -22,18 +22,21 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ html { - box-sizing: border-box; + box-sizing: border-box; } -*, *:before, *:after { - box-sizing: inherit; +*, +*:before, +*:after { + box-sizing: inherit; } -html, body { - height: 100%; +html, +body { + height: 100%; } body { - margin: 0; - font-family: Roboto, "Helvetica Neue", sans-serif; + margin: 0; + font-family: Roboto, 'Helvetica Neue', sans-serif; } diff --git a/alfa-client/apps/alfa/src/styles/layout/_main.scss b/alfa-client/apps/alfa/src/styles/layout/_main.scss index e026b1fffd5e57d0ed81d9fed9c86f623ffe8f58..24416fcac3cc06cd96d4740b7b2d120833cfe3f1 100644 --- a/alfa-client/apps/alfa/src/styles/layout/_main.scss +++ b/alfa-client/apps/alfa/src/styles/layout/_main.scss @@ -21,30 +21,30 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ - @import 'variables'; +@import 'variables'; .l-scroll-area { - height: calc(100vh - $header-height - $navigation-height); - background-color: #fff; - // TODO Wofür ist der box-shadow? - // box-shadow: inset 0 -1px 0 0 rgba(0, 0, 0, 0.08), inset 1px 0 0 rgba(0, 0, 0, 0.08), inset -1px 0 0 rgba(0, 0, 0, 0.08); - overflow: auto; - padding-bottom: 40px; - outline: 0; + height: calc(100vh - $header-height - $navigation-height); + background-color: #fff; + // TODO Wofür ist der box-shadow? + // box-shadow: inset 0 -1px 0 0 rgba(0, 0, 0, 0.08), inset 1px 0 0 rgba(0, 0, 0, 0.08), inset -1px 0 0 rgba(0, 0, 0, 0.08); + overflow: auto; + padding-bottom: 40px; + outline: 0; - &--full { - // TODO Wofür ist der box-shadow? - // box-shadow: inset 0 -1px 0 0 rgba(0, 0, 0, 0.08), inset 1px 0 0 rgba(0, 0, 0, 0.08), inset -1px 0 0 rgba(0, 0, 0, 0.08); - position: relative; - display: block; - min-height: calc(100vh - $header-height - $navigation-height); - background-color: #fff; - } + &--full { + // TODO Wofür ist der box-shadow? + // box-shadow: inset 0 -1px 0 0 rgba(0, 0, 0, 0.08), inset 1px 0 0 rgba(0, 0, 0, 0.08), inset -1px 0 0 rgba(0, 0, 0, 0.08); + position: relative; + display: block; + min-height: calc(100vh - $header-height - $navigation-height); + background-color: #fff; + } } body.dark { - .l-scroll-area, - .l-scroll-area--full { - background-color: rgb(40, 40, 40); - } + .l-scroll-area, + .l-scroll-area--full { + background-color: rgb(40, 40, 40); + } } diff --git a/alfa-client/apps/alfa/src/styles/main.scss b/alfa-client/apps/alfa/src/styles/main.scss index 66798f3f13ac17815ef952e4893628807257c5c9..d02332085bd5ee826646a4ddcf64ce37bd58a20f 100644 --- a/alfa-client/apps/alfa/src/styles/main.scss +++ b/alfa-client/apps/alfa/src/styles/main.scss @@ -58,20 +58,19 @@ @include mat.core(); @mixin custom-components-theme($theme) { - @include expansion-panel($theme); - @include button($theme); - @include breadcrumb($theme); - @include search-container($theme); - @include user-profile-icon($theme); - @include internal-server-error-dialog($theme); - @include autocomplete($theme); + @include expansion-panel($theme); + @include button($theme); + @include breadcrumb($theme); + @include search-container($theme); + @include user-profile-icon($theme); + @include internal-server-error-dialog($theme); + @include autocomplete($theme); } @include mat.all-component-themes($alfaTheme); @include custom-components-theme($alfaTheme); - body.dark { - @include mat.all-component-colors($alfaDarkTheme); - @include custom-components-theme($alfaDarkTheme); -} \ No newline at end of file + @include mat.all-component-colors($alfaDarkTheme); + @include custom-components-theme($alfaDarkTheme); +} diff --git a/alfa-client/apps/alfa/src/styles/material/_autocomplete.scss b/alfa-client/apps/alfa/src/styles/material/_autocomplete.scss index 6148c2c9c10c4325bab15b25caa06ddaffeee169..f4c86c65ffaf0fdeff8b1c1ee050f786136acdca 100644 --- a/alfa-client/apps/alfa/src/styles/material/_autocomplete.scss +++ b/alfa-client/apps/alfa/src/styles/material/_autocomplete.scss @@ -3,72 +3,71 @@ @use 'variables'; @mixin autocomplete($theme) { - $color-config: mat.get-color-config($theme); - $primary-palette: map.get($color-config, 'primary'); + $color-config: mat.get-color-config($theme); + $primary-palette: map.get($color-config, 'primary'); - .cdk-overlay-pane { - &:before { - content: ""; - height: 7px; - width: 100%; - position: absolute; - top: -6px; - background: inherit; - z-index: 2; - } - } + .cdk-overlay-pane { + &:before { + content: ''; + height: 7px; + width: 100%; + position: absolute; + top: -6px; + background: inherit; + z-index: 2; + } + } - alfa-vorgang-search { + alfa-vorgang-search { + button.mat-mdc-icon-button.mat-mdc-button-base { + padding: 8px; + width: 40px; + height: 40px; + } - button.mat-mdc-icon-button.mat-mdc-button-base { - padding: 8px; - width: 40px; - height: 40px; - } + .mdc-text-field--no-label:not(.mdc-text-field--outlined):not(.mdc-text-field--textarea) + .mat-mdc-form-field-infix { + padding: 0.4375em 0; + min-height: auto; + } + } - .mdc-text-field--no-label:not(.mdc-text-field--outlined):not(.mdc-text-field--textarea) .mat-mdc-form-field-infix { - padding: 0.4375em 0; - min-height: auto; - } + .mdc-menu-surface.mat-mdc-autocomplete-panel.vorgang-search { + max-height: calc(100vh - $header-height); + max-width: 600px; + width: calc(600px - (800px - 100vw)); + height: auto; + box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.4); + position: relative; + border-bottom-left-radius: 20px; + border-bottom-right-radius: 20px; + margin-left: -40px; + padding: 0; - } + .mat-mdc-option { + border-top: 1px solid rgba(0, 0, 0, 0.08); + font-size: 14px; + padding: 0.5rem 1rem; + margin-bottom: 0 !important; - .mdc-menu-surface.mat-mdc-autocomplete-panel.vorgang-search { - max-height: calc(100vh - $header-height); - max-width: 600px; - width: calc(600px - (800px - 100vw)); - height: auto; - box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.4); - position: relative; - border-bottom-left-radius: 20px; - border-bottom-right-radius: 20px; - margin-left: -40px; - padding: 0; + &:first-child { + border-top: none; + } - .mat-mdc-option { - border-top: 1px solid rgba(0, 0, 0, 0.08); - font-size: 14px; - padding: 0.5rem 1rem; - margin-bottom: 0 !important; + .mdc-list-item__primary-text { + flex-grow: 1; + } - &:first-child { - border-top: none; - } - - .mdc-list-item__primary-text { - flex-grow: 1; - } - - .line .date { - span { - vertical-align: middle; - } - mat-icon { - margin-right: 0.25rem; - min-width: 1.5rem; - vertical-align: middle; - } - } - } - } -} \ No newline at end of file + .line .date { + span { + vertical-align: middle; + } + mat-icon { + margin-right: 0.25rem; + min-width: 1.5rem; + vertical-align: middle; + } + } + } + } +} diff --git a/alfa-client/apps/alfa/src/styles/material/_button.scss b/alfa-client/apps/alfa/src/styles/material/_button.scss index 1a4428a2dbed949fadaab221ed6371e16c10c00a..6db8ac0e08eb1f97764aea85752b78179e60c039 100644 --- a/alfa-client/apps/alfa/src/styles/material/_button.scss +++ b/alfa-client/apps/alfa/src/styles/material/_button.scss @@ -2,27 +2,28 @@ @use '@angular/material' as mat; @mixin button($theme) { - $color-config: mat.get-color-config($theme); - $primary: map.get($color-config, 'primary'); + $color-config: mat.get-color-config($theme); + $primary: map.get($color-config, 'primary'); - ozgcloud-button-with-spinner, - ozgcloud-stroked-button-with-spinner { - .mat-primary svg path { - fill: mat.get-color-from-palette($primary); - } - } + ozgcloud-button-with-spinner, + ozgcloud-stroked-button-with-spinner { + .mat-primary svg path { + fill: mat.get-color-from-palette($primary); + } + } - .mdc-button { - mat-icon { - font-size: 24px !important; - width: 24px !important; - height: 24px !important - } + .mdc-button { + mat-icon { + font-size: 24px !important; + width: 24px !important; + height: 24px !important; + } + } - } - - .mat-mdc-unelevated-button > .mat-icon, .mat-mdc-raised-button > .mat-icon, .mat-mdc-outlined-button > .mat-icon { - margin-left: 0 !important; - margin-right: 0 !important; - } + .mat-mdc-unelevated-button > .mat-icon, + .mat-mdc-raised-button > .mat-icon, + .mat-mdc-outlined-button > .mat-icon { + margin-left: 0 !important; + margin-right: 0 !important; + } } diff --git a/alfa-client/apps/alfa/src/styles/material/_dialog.scss b/alfa-client/apps/alfa/src/styles/material/_dialog.scss index 4d3bedaf252b5c1e72232bc9f87ba245feffa5f0..ac715993faddf5592a3be69d8bf4f0191cda7639 100644 --- a/alfa-client/apps/alfa/src/styles/material/_dialog.scss +++ b/alfa-client/apps/alfa/src/styles/material/_dialog.scss @@ -2,36 +2,35 @@ @use '@angular/material' as mat; @mixin internal-server-error-dialog($theme) { - $color-config: mat.get-color-config($theme); - $primary-palette: map.get($color-config, 'primary'); - - h1 { - color: mat.get-color-from-palette($primary-palette) !important; - font-size: 24px !important; - font-weight: normal !important; - } - - .mat-mdc-dialog-title { - margin-bottom: 0 !important; - padding-top: 16px !important; - } - - ozgcloud-fixed-dialog .mat-mdc-dialog-title { - margin-bottom: 0 !important; - padding-top: 0 !important; - } - - - .mdc-dialog__title::before { - height: 0 !important; - } - - .mat-mdc-dialog-content .mdc-dialog__content, - .mdc-dialog .mdc-dialog__content { - padding-bottom: 24px !important; - } - - .mat-mdc-dialog-actions { - padding: 0 24px 24px 24px !important; - } + $color-config: mat.get-color-config($theme); + $primary-palette: map.get($color-config, 'primary'); + + h1 { + color: mat.get-color-from-palette($primary-palette) !important; + font-size: 24px !important; + font-weight: normal !important; + } + + .mat-mdc-dialog-title { + margin-bottom: 0 !important; + padding-top: 16px !important; + } + + ozgcloud-fixed-dialog .mat-mdc-dialog-title { + margin-bottom: 0 !important; + padding-top: 0 !important; + } + + .mdc-dialog__title::before { + height: 0 !important; + } + + .mat-mdc-dialog-content .mdc-dialog__content, + .mdc-dialog .mdc-dialog__content { + padding-bottom: 24px !important; + } + + .mat-mdc-dialog-actions { + padding: 0 24px 24px 24px !important; + } } diff --git a/alfa-client/apps/alfa/src/styles/material/_expansion-panel.scss b/alfa-client/apps/alfa/src/styles/material/_expansion-panel.scss index bbf2ad6d5a78048f83af97cc59439dd5e2de4b41..e5c83366af924cf6831cde0584e1bbcfc79e1463 100644 --- a/alfa-client/apps/alfa/src/styles/material/_expansion-panel.scss +++ b/alfa-client/apps/alfa/src/styles/material/_expansion-panel.scss @@ -26,76 +26,76 @@ @import 'variables'; @mixin expansion-panel($theme) { - $color-config: mat.get-color-config($theme); - $primary-palette: map.get($color-config, 'primary'); + $color-config: mat.get-color-config($theme); + $primary-palette: map.get($color-config, 'primary'); - ozgcloud-expansion-panel h3 { - color: mat.get-color-from-palette($primary-palette); - } + ozgcloud-expansion-panel h3 { + color: mat.get-color-from-palette($primary-palette); + } - body.mat-typography ozgcloud-expansion-panel { - .mat-expansion-panel-header { - padding: 0 !important; - height: 44px !important; - } + body.mat-typography ozgcloud-expansion-panel { + .mat-expansion-panel-header { + padding: 0 !important; + height: 44px !important; + } - h3 { - margin-bottom: 0; - font-weight: 500; - margin-left: 16px; - font-size: 16px; - } + h3 { + margin-bottom: 0; + font-weight: 500; + margin-left: 16px; + font-size: 16px; + } - .mat-expansion-panel-body { - padding: 0 0 16px 56px; - } + .mat-expansion-panel-body { + padding: 0 0 16px 56px; + } - ozgcloud-expansion-panel { - .mat-expansion-panel-header { - height: 40px !important; - } + ozgcloud-expansion-panel { + .mat-expansion-panel-header { + height: 40px !important; + } - h3 { - color: inherit; - font-size: 14px !important; - font-weight: 500 !important; - margin-left: 0; - } + h3 { + color: inherit; + font-size: 14px !important; + font-weight: 500 !important; + margin-left: 0; + } - .mat-expansion-panel-header-title { - flex-direction: row-reverse; - justify-content: flex-end; - } + .mat-expansion-panel-header-title { + flex-direction: row-reverse; + justify-content: flex-end; + } - .mat-expansion-panel-body { - padding: 0 0 0 16px; - } - } - } + .mat-expansion-panel-body { + padding: 0 0 0 16px; + } + } + } - body.mat-typography ozgcloud-expansion-panel-with-user { - .mat-expansion-panel-body { - padding: 0 0 0 32px; - } - } + body.mat-typography ozgcloud-expansion-panel-with-user { + .mat-expansion-panel-body { + padding: 0 0 0 32px; + } + } - .section.wiedervorlagen { - .mat-expansion-panel-body .mat-expansion-panel-body { - padding: 0 0 0 24px; - } - } + .section.wiedervorlagen { + .mat-expansion-panel-body .mat-expansion-panel-body { + padding: 0 0 0 24px; + } + } } .mat-expansion-panel { - display: flex; - align-items: center; - height: 44px !important; - background-color: inherit; - box-shadow: none; - border-radius: 0; - font-size: 14px; + display: flex; + align-items: center; + height: 44px !important; + background-color: inherit; + box-shadow: none; + border-radius: 0; + font-size: 14px; } :host-context(.dark) .mat-expansion-panel { - background-color: $darkBackgroundExpansionPanelLike; + background-color: $darkBackgroundExpansionPanelLike; } diff --git a/alfa-client/apps/alfa/src/styles/material/_formfield.scss b/alfa-client/apps/alfa/src/styles/material/_formfield.scss index 4930da8223f4d3cbb1a8d2c16ec3b263c76ee052..2e22e8b8ecf4a04dc2810a38022639466d2f3962 100644 --- a/alfa-client/apps/alfa/src/styles/material/_formfield.scss +++ b/alfa-client/apps/alfa/src/styles/material/_formfield.scss @@ -1,36 +1,36 @@ alfa-vorgang-search { - .mdc-text-field--filled, - .mdc-text-field--filled:hover { - .mdc-line-ripple::before, - .mdc-line-ripple::after { - border-bottom: none; - } - } + .mdc-text-field--filled, + .mdc-text-field--filled:hover { + .mdc-line-ripple::before, + .mdc-line-ripple::after { + border-bottom: none; + } + } - .mat-mdc-form-field-focus-overlay, - .mdc-text-field--filled:not(.mdc-text-field--disabled) { - background-color: transparent !important; - } + .mat-mdc-form-field-focus-overlay, + .mdc-text-field--filled:not(.mdc-text-field--disabled) { + background-color: transparent !important; + } } ozgcloud-fixed-dialog { - .mat-mdc-form-field-focus-overlay, - .mdc-text-field--filled:not(.mdc-text-field--disabled) { - background-color: transparent !important; - } + .mat-mdc-form-field-focus-overlay, + .mdc-text-field--filled:not(.mdc-text-field--disabled) { + background-color: transparent !important; + } - .mdc-text-field { - padding: 0; - } + .mdc-text-field { + padding: 0; + } } body.dark { - mat-form-field { - --mdc-theme-error: red; - --mdc-filled-text-field-error-focus-label-text-color: red; - --mdc-outlined-text-field-error-focus-label-text-color: red; - --mdc-filled-text-field-error-label-text-color: red; - --mdc-outlined-text-field-error-label-text-color: red; - --mdc-filled-text-field-disabled-active-indicator-color: red; - } + mat-form-field { + --mdc-theme-error: red; + --mdc-filled-text-field-error-focus-label-text-color: red; + --mdc-outlined-text-field-error-focus-label-text-color: red; + --mdc-filled-text-field-error-label-text-color: red; + --mdc-outlined-text-field-error-label-text-color: red; + --mdc-filled-text-field-disabled-active-indicator-color: red; + } } diff --git a/alfa-client/apps/alfa/src/styles/material/_icons.scss b/alfa-client/apps/alfa/src/styles/material/_icons.scss index 0a25cbe23335ee7de9b19a787aadca0103790b1d..316b5b5ddc6e38cd6c4089c0e6124b4a15a90329 100644 --- a/alfa-client/apps/alfa/src/styles/material/_icons.scss +++ b/alfa-client/apps/alfa/src/styles/material/_icons.scss @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .mat-icon { - overflow: unset !important; -} \ No newline at end of file + overflow: unset !important; +} diff --git a/alfa-client/apps/alfa/src/styles/material/_list.scss b/alfa-client/apps/alfa/src/styles/material/_list.scss index 5426fe1965fa84fa868e75182228e4599a50a6d7..542402469b00259042fc9c5459b4b34e8bdc69b8 100644 --- a/alfa-client/apps/alfa/src/styles/material/_list.scss +++ b/alfa-client/apps/alfa/src/styles/material/_list.scss @@ -1,33 +1,33 @@ body.dark { - .mdc-list-item--with-leading-icon .mdc-list-item__start, - .mdc-list-item__secondary-text { - color: white !important; - } + .mdc-list-item--with-leading-icon .mdc-list-item__start, + .mdc-list-item__secondary-text { + color: white !important; + } } .mdc-list-item--with-leading-icon .mdc-list-item__start, .mdc-list-item__secondary-text { - color: rgba(0, 0, 0, 0.87) !important; + color: rgba(0, 0, 0, 0.87) !important; } .mdc-list-item--with-leading-icon .mdc-list-item__start { - margin: 0 !important; - line-height: 24px !important; + margin: 0 !important; + line-height: 24px !important; } .mat-mdc-list-item.mdc-list-item--with-leading-icon.mdc-list-item--with-one-line, .mat-mdc-list-item.mdc-list-item--with-leading-icon.mdc-list-item--with-two-lines { - height: auto !important; + height: auto !important; } .mdc-list-item__secondary-text::before { - height: auto !important; + height: auto !important; } .mdc-list-item__content { - padding-left: 6px; + padding-left: 6px; } .mdc-list-item { - margin-bottom: 8px; -} \ No newline at end of file + margin-bottom: 8px; +} diff --git a/alfa-client/apps/alfa/src/styles/material/_menu.scss b/alfa-client/apps/alfa/src/styles/material/_menu.scss index e10960afa907a888d525ef1c53a5fa5fb4cc29b0..835661a949456ec3e8e6d43eeb8769b7a43b9a81 100644 --- a/alfa-client/apps/alfa/src/styles/material/_menu.scss +++ b/alfa-client/apps/alfa/src/styles/material/_menu.scss @@ -1,23 +1,23 @@ @use 'variables'; .mat-mdc-menu-panel.mat-mdc-menu-panel { - max-width: 365px !important; - background-color: $background; + max-width: 365px !important; + background-color: $background; } body.dark { - .mat-mdc-menu-panel.mat-mdc-menu-panel { - background-color: $darkBackgroundExpansionPanelLike; - } + .mat-mdc-menu-panel.mat-mdc-menu-panel { + background-color: $darkBackgroundExpansionPanelLike; + } } alfa-help-menu { - .mat-mdc-fab { - box-shadow: none !important; - background-color: transparent !important; - border-radius: 10px; - height: 40px; - width: auto; - padding: 0.5rem; - } -} \ No newline at end of file + .mat-mdc-fab { + box-shadow: none !important; + background-color: transparent !important; + border-radius: 10px; + height: 40px; + width: auto; + padding: 0.5rem; + } +} diff --git a/alfa-client/apps/alfa/src/styles/material/_snackbar.scss b/alfa-client/apps/alfa/src/styles/material/_snackbar.scss index cc36ed9e78aaed9e699a4c34b31a6327506ebc57..ab8994e15c2e1fa40b5581cf16b0341a64304e9b 100644 --- a/alfa-client/apps/alfa/src/styles/material/_snackbar.scss +++ b/alfa-client/apps/alfa/src/styles/material/_snackbar.scss @@ -1,49 +1,53 @@ .mat-mdc-snack-bar-container { - ozgcloud-snackbar-info > button { - color: #2196f3 !important; - height: 24px !important; - } + ozgcloud-snackbar-info > button { + color: #2196f3 !important; + height: 24px !important; + } } .mat-mdc-snack-bar-container.error { - .mdc-snackbar__surface { - background-color: transparent !important; - box-shadow: none !important; - } + .mdc-snackbar__surface { + background-color: transparent !important; + box-shadow: none !important; + } - .mdc-snackbar__label { - padding-top: 11px !important; - padding-bottom: 11px !important; - color: black !important; - } + .mdc-snackbar__label { + padding-top: 11px !important; + padding-bottom: 11px !important; + color: black !important; + } - .mat-mdc-button-persistent-ripple, .mat-mdc-button-ripple { - display: none; - } + .mat-mdc-button-persistent-ripple, + .mat-mdc-button-ripple { + display: none; + } - min-width: 240px; - max-width: 90vw; + min-width: 240px; + max-width: 90vw; - border: 3px solid mat.get-color-from-palette($warnPalette); - border-radius: 4px; - background-color: lighten(mat.get-color-from-palette($warnPalette), 38%); - box-shadow: 0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12); - color: rgba(#000, 0.89); - position: relative; + border: 3px solid mat.get-color-from-palette($warnPalette); + border-radius: 4px; + background-color: lighten(mat.get-color-from-palette($warnPalette), 38%); + box-shadow: + 0px 3px 5px -1px rgba(0, 0, 0, 0.2), + 0px 6px 10px 0px rgba(0, 0, 0, 0.14), + 0px 1px 18px 0px rgba(0, 0, 0, 0.12); + color: rgba(#000, 0.89); + position: relative; - &:before { - position: absolute; - content: url("/assets/icons/error_outline_white.svg"); - display: block; - background-color: mat.get-color-from-palette($warnPalette); - left: 0; - top: 0; - padding: 11px 9px 11px 7px; - color: #fff; - height: 100%; - } + &:before { + position: absolute; + content: url('/assets/icons/error_outline_white.svg'); + display: block; + background-color: mat.get-color-from-palette($warnPalette); + left: 0; + top: 0; + padding: 11px 9px 11px 7px; + color: #fff; + height: 100%; + } - > div { - margin-left: 44px; - } + > div { + margin-left: 44px; + } } diff --git a/alfa-client/apps/alfa/src/styles/material/_tabs.scss b/alfa-client/apps/alfa/src/styles/material/_tabs.scss index 3cfafb3bb42f45f37fd86fc9aea0b3bef823e346..bee57c8e73b9d5e394d29aa191893e7861a5d667 100644 --- a/alfa-client/apps/alfa/src/styles/material/_tabs.scss +++ b/alfa-client/apps/alfa/src/styles/material/_tabs.scss @@ -22,16 +22,16 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .mat-mdc-tab-header { - border-bottom: 1px solid rgba(0, 0, 0, 0.12); + border-bottom: 1px solid rgba(0, 0, 0, 0.12); } .mat-mdc-tab { - padding: 0 !important; - min-width: auto !important; - margin: 0 12px !important; - &:first-child { - margin-left: 0 !important; - } - &:last-child { - margin-right: 0 !important; - } + padding: 0 !important; + min-width: auto !important; + margin: 0 12px !important; + &:first-child { + margin-left: 0 !important; + } + &:last-child { + margin-right: 0 !important; + } } diff --git a/alfa-client/apps/alfa/src/styles/material/_tooltip.scss b/alfa-client/apps/alfa/src/styles/material/_tooltip.scss index c900b9ece70d04818a1d1b39c76a7a8d4596eec0..543eb47ab24a3ce0049bb07400bcf584e2e58af7 100644 --- a/alfa-client/apps/alfa/src/styles/material/_tooltip.scss +++ b/alfa-client/apps/alfa/src/styles/material/_tooltip.scss @@ -1,12 +1,12 @@ .mat-tooltip { - font-size: 12px !important; - padding-top: 2px !important; - padding-bottom: 2px !important; - margin-top: 2px !important; - margin-bottom: 2px !important; - white-space: pre-line; + font-size: 12px !important; + padding-top: 2px !important; + padding-bottom: 2px !important; + margin-top: 2px !important; + margin-bottom: 2px !important; + white-space: pre-line; - &.word-break { - word-break: break-word; - } + &.word-break { + word-break: break-word; + } } diff --git a/alfa-client/apps/alfa/src/styles/material/_typography.scss b/alfa-client/apps/alfa/src/styles/material/_typography.scss index f0f7ab67a35609d1a675770005b367a1b63b7f7d..20fab3cd00fbbda98d550f038342dff2a4781c18 100644 --- a/alfa-client/apps/alfa/src/styles/material/_typography.scss +++ b/alfa-client/apps/alfa/src/styles/material/_typography.scss @@ -6,5 +6,5 @@ .mat-mdc-menu-content, .mdc-list-item__primary-text, .mat-mdc-dialog-container .mdc-dialog__content { - letter-spacing: normal !important; -} \ No newline at end of file + letter-spacing: normal !important; +} diff --git a/alfa-client/apps/alfa/src/test-setup.ts b/alfa-client/apps/alfa/src/test-setup.ts index 32096869a0084d5cdd50f8fd6f051a9f7afe7ed7..9ffb6a66afc4d1c41f58bba4790410511a159f6d 100644 --- a/alfa-client/apps/alfa/src/test-setup.ts +++ b/alfa-client/apps/alfa/src/test-setup.ts @@ -25,13 +25,11 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting, + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { teardown: { destroyAfterEach: false } } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, +}); diff --git a/alfa-client/apps/alfa/tsconfig.app.json b/alfa-client/apps/alfa/tsconfig.app.json index 9985bb559e24956e1f7d141289a23a447bfedcbc..c80264023776e99d93e926107262208631eff19e 100644 --- a/alfa-client/apps/alfa/tsconfig.app.json +++ b/alfa-client/apps/alfa/tsconfig.app.json @@ -1,11 +1,11 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": [], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/main.ts", "src/polyfills.ts"], - "exclude": ["jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": [], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/main.ts", "src/polyfills.ts"], + "exclude": ["jest.config.ts"] } diff --git a/alfa-client/apps/alfa/tsconfig.editor.json b/alfa-client/apps/alfa/tsconfig.editor.json index 7855a792cae410028a2176093faa831aa4a953a3..1bf3c0a7455d9f0731999e8ef4486967bbf3c0aa 100644 --- a/alfa-client/apps/alfa/tsconfig.editor.json +++ b/alfa-client/apps/alfa/tsconfig.editor.json @@ -1,8 +1,8 @@ { - "extends": "./tsconfig.json", - "include": ["**/*.ts"], - "compilerOptions": { - "types": ["jest", "node"] - }, - "exclude": ["jest.config.ts"] + "extends": "./tsconfig.json", + "include": ["**/*.ts"], + "compilerOptions": { + "types": ["jest", "node"] + }, + "exclude": ["jest.config.ts"] } diff --git a/alfa-client/apps/alfa/tsconfig.json b/alfa-client/apps/alfa/tsconfig.json index db74b7e9ab12d1a89705409932e2743b7aef2e3d..7dcba407693f4a5f840c46a2b43bdb687b270b09 100644 --- a/alfa-client/apps/alfa/tsconfig.json +++ b/alfa-client/apps/alfa/tsconfig.json @@ -1,19 +1,19 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - }, - { - "path": "./tsconfig.editor.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.spec.json" + }, + { + "path": "./tsconfig.editor.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/apps/alfa/tsconfig.spec.json b/alfa-client/apps/alfa/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/apps/alfa/tsconfig.spec.json +++ b/alfa-client/apps/alfa/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/jest.preset.js b/alfa-client/jest.preset.js index 5d900d715c763167022577290b88f2aa9203257a..d09b17cf634d64b5e690e5e11055713be752eed8 100644 --- a/alfa-client/jest.preset.js +++ b/alfa-client/jest.preset.js @@ -24,9 +24,9 @@ const nxPreset = require('@nx/jest/preset').default; module.exports = { - ...nxPreset, - moduleNameMapper: { - 'lodash-es': 'lodash', - }, - workerIdleMemoryLimit: '1024MB' + ...nxPreset, + moduleNameMapper: { + 'lodash-es': 'lodash', + }, + workerIdleMemoryLimit: '1024MB', }; diff --git a/alfa-client/libs/api-root-shared/.eslintrc.json b/alfa-client/libs/api-root-shared/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/api-root-shared/.eslintrc.json +++ b/alfa-client/libs/api-root-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/api-root-shared/jest.config.ts b/alfa-client/libs/api-root-shared/jest.config.ts index b4cf7efb67374106980f83d5e797d0ee5fdfeaa1..2c45c13d990440750cb60ad4e5c164ac6f83bd49 100644 --- a/alfa-client/libs/api-root-shared/jest.config.ts +++ b/alfa-client/libs/api-root-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'api-root-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/api-root-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'api-root-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/api-root-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/api-root-shared/project.json b/alfa-client/libs/api-root-shared/project.json index b1345fea87b4e4829555eb1427f4d6ed978be31d..cd5c6eb62c61393c7c9f38be1ccb58011f1e9fc3 100644 --- a/alfa-client/libs/api-root-shared/project.json +++ b/alfa-client/libs/api-root-shared/project.json @@ -1,34 +1,34 @@ { - "name": "api-root-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/api-root-shared/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/api-root-shared/src/**/*.ts", - "libs/api-root-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/api-root-shared/tsconfig.spec.json", - "jestConfig": "libs/api-root-shared/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/api-root-shared"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "api-root-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/api-root-shared/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/api-root-shared/src/**/*.ts", + "libs/api-root-shared/src/**/*.html" + ] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/api-root-shared/tsconfig.spec.json", + "jestConfig": "libs/api-root-shared/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/api-root-shared"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/api-root-shared/src/index.ts b/alfa-client/libs/api-root-shared/src/index.ts index 4d786513964a4004b801e6deb6ac1d86ef5a5ad1..e5e86564d2ccecfa220c494e08e962aa84de1a3f 100644 --- a/alfa-client/libs/api-root-shared/src/index.ts +++ b/alfa-client/libs/api-root-shared/src/index.ts @@ -29,4 +29,3 @@ export * from './lib/api-root.linkrel'; export * from './lib/api-root.model'; export * from './lib/api-root.module'; export * from './lib/api-root.service'; - diff --git a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.actions.ts b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.actions.ts index be7192ebd711ccfd46767a2af285a540de030ee5..495cadf10f7141cf335b06b189b476eb5c42fc82 100644 --- a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.actions.ts +++ b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.actions.ts @@ -21,14 +21,24 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { ApiErrorAction, TypedActionCreator, TypedActionCreatorWithProps } from '@alfa-client/tech-shared'; +import { + ApiErrorAction, + TypedActionCreator, + TypedActionCreatorWithProps, +} from '@alfa-client/tech-shared'; import { createAction, props } from '@ngrx/store'; import { ApiRootResource } from '../api-root.model'; export interface ApiRootProps { - apiRoot: ApiRootResource + apiRoot: ApiRootResource; } export const loadApiRoot: TypedActionCreator = createAction('[ApiRoot] Load'); -export const loadApiRootSuccess: TypedActionCreatorWithProps<ApiRootProps> = createAction('[ApiRoot] Load Success', props<ApiRootProps>()); -export const loadApiRootFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[ApiRoot] Load Failure', props<ApiErrorAction>()); \ No newline at end of file +export const loadApiRootSuccess: TypedActionCreatorWithProps<ApiRootProps> = createAction( + '[ApiRoot] Load Success', + props<ApiRootProps>(), +); +export const loadApiRootFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[ApiRoot] Load Failure', + props<ApiErrorAction>(), +); diff --git a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.effects.spec.ts b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.effects.spec.ts index f45369747804f0504876b675542ab0cfcfce19a0..4f01df644726dbea44520f1a9bad7ab7f7584b00 100644 --- a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.effects.spec.ts +++ b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.effects.spec.ts @@ -39,56 +39,59 @@ import { ApiRootEffects } from './api-root.effects'; import * as ApiRootActions from './api-root.actions'; describe('ApiRootEffects', () => { - let actions: Observable<Action>; - let effects: ApiRootEffects; + let actions: Observable<Action>; + let effects: ApiRootEffects; - const apiRootService = mock(ApiRootRepository); + const apiRootService = mock(ApiRootRepository); - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - ApiRootEffects, - provideMockActions(() => actions), - provideMockStore(), - { - provide: ApiRootRepository, - useValue: apiRootService - } - ] - }); - effects = TestBed.inject(ApiRootEffects); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + ApiRootEffects, + provideMockActions(() => actions), + provideMockStore(), + { + provide: ApiRootRepository, + useValue: apiRootService, + }, + ], + }); + effects = TestBed.inject(ApiRootEffects); + }); - describe('load', () => { + describe('load', () => { + const apiRoot: ApiRootResource = createApiRootResource(); - const apiRoot: ApiRootResource = createApiRootResource(); + it('should call service', () => { + actions = of(ApiRootActions.loadApiRoot()); - it('should call service', () => { - actions = of(ApiRootActions.loadApiRoot()); + effects.load$.subscribe(); - effects.load$.subscribe(); + expect(apiRootService.loadApiRoot).toHaveBeenCalled(); + }); - expect(apiRootService.loadApiRoot).toHaveBeenCalled(); - }) + it('should dispatch loadApiRootSuccess action', () => { + apiRootService.loadApiRoot.mockReturnValue(of(apiRoot)); - it('should dispatch loadApiRootSuccess action', () => { - apiRootService.loadApiRoot.mockReturnValue(of(apiRoot)); + actions = hot('-a-|', { a: ApiRootActions.loadApiRoot() }); - actions = hot('-a-|', { a: ApiRootActions.loadApiRoot() }); + const expected = hot('-a-|', { + a: ApiRootActions.loadApiRootSuccess(<ApiRootProps>{ apiRoot }), + }); + expect(effects.load$).toBeObservable(expected); + }); - const expected = hot('-a-|', { a: ApiRootActions.loadApiRootSuccess(<ApiRootProps>{ apiRoot }) }); - expect(effects.load$).toBeObservable(expected); - }) + it('should dispatch loadApiRootFailure action', () => { + const apiError: ApiError = createApiError(); + const errorResponse = cold('-#', {}, apiError); + apiRootService.loadApiRoot = jest.fn(() => errorResponse); - it('should dispatch loadApiRootFailure action', () => { - const apiError: ApiError = createApiError(); - const errorResponse = cold('-#', {}, apiError); - apiRootService.loadApiRoot = jest.fn(() => errorResponse); + const expected = cold('--c', { + c: ApiRootActions.loadApiRootFailure(<ApiErrorAction>{ apiError }), + }); + actions = hot('-a', { a: ApiRootActions.loadApiRoot() }); - const expected = cold('--c', { c: ApiRootActions.loadApiRootFailure(<ApiErrorAction>{ apiError }) }); - actions = hot('-a', { a: ApiRootActions.loadApiRoot() }); - - expect(effects.load$).toBeObservable(expected); - }) - }) -}); \ No newline at end of file + expect(effects.load$).toBeObservable(expected); + }); + }); +}); diff --git a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.effects.ts b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.effects.ts index 3cb880bebac97f9c82a4d5496ea9974d984c4c35..b81bf3b2070b11df2bb42208aa71ced0e949b6ae 100644 --- a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.effects.ts +++ b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.effects.ts @@ -31,13 +31,20 @@ import * as ApiRootActions from './api-root.actions'; @Injectable() export class ApiRootEffects { + constructor( + private readonly actions$: Actions, + private apiRootService: ApiRootRepository, + ) {} - constructor(private readonly actions$: Actions, private apiRootService: ApiRootRepository) { } - - load$ = createEffect(() =>this.actions$.pipe(ofType(ApiRootActions.loadApiRoot), - switchMap(() => this.apiRootService.loadApiRoot().pipe( - map(apiRoot => ApiRootActions.loadApiRootSuccess({ apiRoot })), - catchError(apiError => of(ApiRootActions.loadApiRootFailure({ apiError }))) - ))) - ) -} \ No newline at end of file + load$ = createEffect(() => + this.actions$.pipe( + ofType(ApiRootActions.loadApiRoot), + switchMap(() => + this.apiRootService.loadApiRoot().pipe( + map((apiRoot) => ApiRootActions.loadApiRootSuccess({ apiRoot })), + catchError((apiError) => of(ApiRootActions.loadApiRootFailure({ apiError }))), + ), + ), + ), + ); +} diff --git a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.facade.spec.ts b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.facade.spec.ts index 1233207173e49ff1f117697d6bde5e49b0e588f7..4214396719040dba4e83be4f698d4f156754066d 100644 --- a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.facade.spec.ts +++ b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.facade.spec.ts @@ -37,66 +37,63 @@ import { ApiRootFacade } from './api-root.facade'; import { ApiRootPartialState, API_ROOT_FEATURE_KEY, reducer } from './api-root.reducer'; describe('ApiRootFacade', () => { - let facade: ApiRootFacade; - let store: Store<ApiRootPartialState>; + let facade: ApiRootFacade; + let store: Store<ApiRootPartialState>; - const apiRootRepository = mock(ApiRootRepository); + const apiRootRepository = mock(ApiRootRepository); - describe('used in NgModule', () => { - beforeEach(() => { - @NgModule({ - imports: [ - StoreModule.forFeature(API_ROOT_FEATURE_KEY, reducer), - EffectsModule.forFeature([ApiRootEffects]), - ], - providers: [ApiRootFacade, - { - provide: ApiRootRepository, - useValue: apiRootRepository - }], - }) - class CustomFeatureModule { } + describe('used in NgModule', () => { + beforeEach(() => { + @NgModule({ + imports: [ + StoreModule.forFeature(API_ROOT_FEATURE_KEY, reducer), + EffectsModule.forFeature([ApiRootEffects]), + ], + providers: [ + ApiRootFacade, + { + provide: ApiRootRepository, + useValue: apiRootRepository, + }, + ], + }) + class CustomFeatureModule {} - @NgModule({ - imports: [ - StoreModule.forRoot({}), - EffectsModule.forRoot([]), - CustomFeatureModule, - ], - }) - class RootModule { } - TestBed.configureTestingModule({ imports: [RootModule] }); + @NgModule({ + imports: [StoreModule.forRoot({}), EffectsModule.forRoot([]), CustomFeatureModule], + }) + class RootModule {} + TestBed.configureTestingModule({ imports: [RootModule] }); - store = TestBed.inject(Store); - facade = TestBed.inject(ApiRootFacade); - }); + store = TestBed.inject(Store); + facade = TestBed.inject(ApiRootFacade); + }); - describe('get historie', () => { + describe('get historie', () => { + const apiRootResource: ApiRootResource = createApiRootResource(); - const apiRootResource: ApiRootResource = createApiRootResource(); + beforeEach(() => { + apiRootRepository.loadApiRoot.mockReturnValue(of(apiRootResource)); + }); - beforeEach(() => { - apiRootRepository.loadApiRoot.mockReturnValue(of(apiRootResource)); - }) + it('should return loading state resource on required loading resource', async () => { + let stateList = await readFirst(facade.getApiRoot()); - it('should return loading state resource on required loading resource', async () => { - let stateList = await readFirst(facade.getApiRoot()); + expect(stateList.resource).toBeNull(); + expect(stateList.loading).toEqual(true); + }); - expect(stateList.resource).toBeNull(); - expect(stateList.loading).toEqual(true); - }) + it('should return the loaded state resource', async () => { + let stateList = await readFirst(facade.getApiRoot()); + expect(stateList.resource).toBeNull(); + expect(stateList.loading).toEqual(true); - it('should return the loaded state resource', async () => { - let stateList = await readFirst(facade.getApiRoot()); - expect(stateList.resource).toBeNull(); - expect(stateList.loading).toEqual(true); + store.dispatch(ApiRootActions.loadApiRootSuccess({ apiRoot: apiRootResource })); - store.dispatch(ApiRootActions.loadApiRootSuccess({ apiRoot: apiRootResource })); - - stateList = await readFirst(facade.getApiRoot()); - expect(stateList.resource).toBe(apiRootResource); - expect(stateList.loading).toBe(false); - }); - }) - }); + stateList = await readFirst(facade.getApiRoot()); + expect(stateList.resource).toBe(apiRootResource); + expect(stateList.loading).toBe(false); + }); + }); + }); }); diff --git a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.facade.ts b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.facade.ts index f49462b65364ca3380e8d5c8d69b62e848b8320d..9625c511fb4f84a5e9c6d18cfcd09c0007a7581f 100644 --- a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.facade.ts +++ b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.facade.ts @@ -33,11 +33,16 @@ import * as ApiRootSelectors from './api-root.selectors'; @Injectable() export class ApiRootFacade { + constructor(private readonly store: Store) {} - constructor(private readonly store: Store) { } - - getApiRoot(): Observable<StateResource<ApiRootResource>> { - return this.store.select(ApiRootSelectors.apiRoot).pipe( - filter(apiRoot => !doIfLoadingRequired(apiRoot, () => this.store.dispatch(ApiRootActions.loadApiRoot())))); - } -} \ No newline at end of file + getApiRoot(): Observable<StateResource<ApiRootResource>> { + return this.store + .select(ApiRootSelectors.apiRoot) + .pipe( + filter( + (apiRoot) => + !doIfLoadingRequired(apiRoot, () => this.store.dispatch(ApiRootActions.loadApiRoot())), + ), + ); + } +} diff --git a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.reducer.spec.ts b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.reducer.spec.ts index e14e8d662e1af4ef006040802709a6c8d2d4130e..b05b321a389ba884c2aa6562597bbfef3e19a7f6 100644 --- a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.reducer.spec.ts +++ b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.reducer.spec.ts @@ -31,39 +31,35 @@ import { ApiRootState, initialState, reducer } from './api-root.reducer'; import * as ApiRootActions from './api-root.actions'; describe('ApiRoot Reducer', () => { + describe('on loadHistorie action', () => { + it('should set loading to true', () => { + const action = ApiRootActions.loadApiRoot(); - describe('on loadHistorie action', () => { + const result: ApiRootState = reducer(initialState, action); - it('should set loading to true', () => { - const action = ApiRootActions.loadApiRoot(); + expect(result.apiRoot.loading).toBeTruthy(); + }); + }); - const result: ApiRootState = reducer(initialState, action); + describe('on loadApiRootSuccess action', () => { + it('should set loaded resource into state', () => { + const apiRoot: ApiRootResource = createApiRootResource(); + const action = ApiRootActions.loadApiRootSuccess(<ApiRootProps>{ apiRoot }); - expect(result.apiRoot.loading).toBeTruthy(); - }) - }) + const result: ApiRootState = reducer(initialState, action); - describe('on loadApiRootSuccess action', () => { + expect(result.apiRoot).toEqual(createStateResource(apiRoot)); + }); + }); - it('should set loaded resource into state', () => { - const apiRoot: ApiRootResource = createApiRootResource(); - const action = ApiRootActions.loadApiRootSuccess(<ApiRootProps>{ apiRoot }); + describe('on loadApiRootFailure action', () => { + it('should set error into state', () => { + const apiError: ApiError = createApiError(); + const action = ApiRootActions.loadApiRootFailure(<ApiErrorAction>{ apiError }); - const result: ApiRootState = reducer(initialState, action); + const result: ApiRootState = reducer(initialState, action); - expect(result.apiRoot).toEqual(createStateResource(apiRoot)); - }) - }) - - describe('on loadApiRootFailure action', () => { - - it('should set error into state', () => { - const apiError: ApiError = createApiError(); - const action = ApiRootActions.loadApiRootFailure(<ApiErrorAction>{ apiError }); - - const result: ApiRootState = reducer(initialState, action); - - expect(result.apiRoot.error).toBe(apiError); - }) - }) + expect(result.apiRoot.error).toBe(apiError); + }); + }); }); diff --git a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.reducer.ts b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.reducer.ts index 742dc2ea2720ca208a760e67786a323033d02c3e..982b1251302e3d5915885535b6788505c3d55333 100644 --- a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.reducer.ts +++ b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.reducer.ts @@ -21,7 +21,13 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { ApiErrorAction, createEmptyStateResource, createErrorStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + ApiErrorAction, + createEmptyStateResource, + createErrorStateResource, + createStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { Action, createReducer, on } from '@ngrx/store'; import { ApiRootResource } from '../api-root.model'; import { ApiRootProps } from './api-root.actions'; @@ -31,33 +37,33 @@ import * as ApiRootActions from './api-root.actions'; export const API_ROOT_FEATURE_KEY = 'ApiRootState'; export interface ApiRootState { - apiRoot: StateResource<ApiRootResource>; + apiRoot: StateResource<ApiRootResource>; } export interface ApiRootPartialState { - readonly [API_ROOT_FEATURE_KEY]: ApiRootState; + readonly [API_ROOT_FEATURE_KEY]: ApiRootState; } export const initialState: ApiRootState = { - apiRoot: createEmptyStateResource() -} + apiRoot: createEmptyStateResource(), +}; const apiRootReducer = createReducer( - initialState, - on(ApiRootActions.loadApiRoot, (state: ApiRootState) => ({ - ...state, - apiRoot: { ...state.apiRoot, loading: true } - })), - on(ApiRootActions.loadApiRootSuccess, (state: ApiRootState, props: ApiRootProps) => ({ - ...state, - apiRoot: createStateResource(props.apiRoot) - })), - on(ApiRootActions.loadApiRootFailure, (state: ApiRootState, props: ApiErrorAction) => ({ - ...state, - apiRoot: createErrorStateResource(props.apiError) - })) + initialState, + on(ApiRootActions.loadApiRoot, (state: ApiRootState) => ({ + ...state, + apiRoot: { ...state.apiRoot, loading: true }, + })), + on(ApiRootActions.loadApiRootSuccess, (state: ApiRootState, props: ApiRootProps) => ({ + ...state, + apiRoot: createStateResource(props.apiRoot), + })), + on(ApiRootActions.loadApiRootFailure, (state: ApiRootState, props: ApiErrorAction) => ({ + ...state, + apiRoot: createErrorStateResource(props.apiError), + })), ); export function reducer(state: ApiRootState, action: Action) { - return apiRootReducer(state, action); -} \ No newline at end of file + return apiRootReducer(state, action); +} diff --git a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.selectors.spec.ts b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.selectors.spec.ts index a3f6bef323fd08804c951b39f129fcab193c1669..2766a15cb97de2e3f56322dba30d9b0ad8c09aa8 100644 --- a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.selectors.spec.ts +++ b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.selectors.spec.ts @@ -28,26 +28,24 @@ import { ApiRootPartialState, initialState } from './api-root.reducer'; import * as ApiRootSelectors from './api-root.selectors'; describe('ApiRoot Selectors', () => { + let state: ApiRootPartialState; - let state: ApiRootPartialState; + const apiRoot: StateResource<ApiRootResource> = createStateResource(createApiRootResource()); - const apiRoot: StateResource<ApiRootResource> = createStateResource(createApiRootResource()); + beforeEach(() => { + state = { + ApiRootState: { + ...initialState, + apiRoot, + }, + }; + }); - beforeEach(() => { - state = { - ApiRootState: { - ...initialState, - apiRoot - } - } - }); + describe('apiRootSelector', () => { + it('should return historieList', () => { + const result = ApiRootSelectors.apiRoot(state); - describe('apiRootSelector', () => { - - it('should return historieList', () => { - const result = ApiRootSelectors.apiRoot(state); - - expect(result).toBe(apiRoot); - }) - }) -}); \ No newline at end of file + expect(result).toBe(apiRoot); + }); + }); +}); diff --git a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.selectors.ts b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.selectors.ts index d9a8ec9c685529f2ce67986edc096b4566eb4dd1..c4faba48eb987d5c2e0c78e17ab8b706d8eeb838 100644 --- a/alfa-client/libs/api-root-shared/src/lib/+state/api-root.selectors.ts +++ b/alfa-client/libs/api-root-shared/src/lib/+state/api-root.selectors.ts @@ -26,4 +26,4 @@ import { ApiRootState, API_ROOT_FEATURE_KEY } from './api-root.reducer'; export const getApiRootState = createFeatureSelector<ApiRootState>(API_ROOT_FEATURE_KEY); -export const apiRoot = createSelector(getApiRootState, (state: ApiRootState) => state.apiRoot); \ No newline at end of file +export const apiRoot = createSelector(getApiRootState, (state: ApiRootState) => state.apiRoot); diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts index c3021e43ea73e5bf27b26373ba2461e9016ad184..d8a70c20e7bccf6401fe08087ee4508002b14288 100644 --- a/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts +++ b/alfa-client/libs/api-root-shared/src/lib/api-root.linkrel.ts @@ -22,38 +22,38 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum ApiRootLinkRel { - CURRENT_USER = 'currentUser', - DOWNLOAD_TOKEN = 'downloadToken', - SEARCH_ALLE = 'search_all', - SEARCH_MEINE = 'search_my', - SEARCH_UNASSIGNED = 'search_unassigned', - ALLE_VORGAENGE = 'vorgaenge_all', - MEINE_VORGAENGE = 'vorgaenge_my', - UNASSIGNED = 'vorgaenge_unassigned', - ALLE_VORGAENGE_NEU = 'vorgaenge_neu_all', - MEINE_VORGAENGE_NEU = 'vorgaenge_neu_my', - UNASSIGNED_NEU = 'vorgaenge_neu_unassigned', - ALLE_VORGAENGE_ANGENOMMEN = 'vorgaenge_angenommen_all', - MEINE_VORGAENGE_ANGENOMMEN = 'vorgaenge_angenommen_my', - UNASSIGNED_ANGENOMMEN = 'vorgaenge_angenommen_unassigned', - ALLE_VORGAENGE_IN_BEARBEITUNG = 'vorgaenge_in_bearbeitung_all', - MEINE_VORGAENGE_IN_BEARBEITUNG = 'vorgaenge_in_bearbeitung_my', - UNASSIGNED_IN_BEARBEITUNG = 'vorgaenge_in_bearbeitung_unassigned', - ALLE_VORGAENGE_BESCHIEDEN = 'vorgaenge_beschieden_all', - MEINE_VORGAENGE_BESCHIEDEN = 'vorgaenge_beschieden_my', - UNASSIGNED_BESCHIEDEN = 'vorgaenge_beschieden_unassigned', - ALLE_VORGAENGE_ABGESCHLOSSEN = 'vorgaenge_abgeschlossen_all', - MEINE_VORGAENGE_ABGESCHLOSSEN = 'vorgaenge_abgeschlossen_my', - UNASSIGNED_ABGESCHLOSSEN = 'vorgaenge_abgeschlossen_unassigned', - ALLE_VORGAENGE_VERWORFEN = 'vorgaenge_verworfen_all', - MEINE_VORGAENGE_VERWORFEN = 'vorgaenge_verworfen_my', - UNASSIGNED_VERWORFEN = 'vorgaenge_verworfen_unassigned', - ALL_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_all', - MY_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_my', - UNASSIGNED_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_unassigned', - ALLE_VORGAENGE_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_all', - MEINE_VORGAENGE_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_my', - UNASSIGNED_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_unassigned', - DOCUMENTATIONS = 'documentations', - HINTS = 'hints' -} \ No newline at end of file + CURRENT_USER = 'currentUser', + DOWNLOAD_TOKEN = 'downloadToken', + SEARCH_ALLE = 'search_all', + SEARCH_MEINE = 'search_my', + SEARCH_UNASSIGNED = 'search_unassigned', + ALLE_VORGAENGE = 'vorgaenge_all', + MEINE_VORGAENGE = 'vorgaenge_my', + UNASSIGNED = 'vorgaenge_unassigned', + ALLE_VORGAENGE_NEU = 'vorgaenge_neu_all', + MEINE_VORGAENGE_NEU = 'vorgaenge_neu_my', + UNASSIGNED_NEU = 'vorgaenge_neu_unassigned', + ALLE_VORGAENGE_ANGENOMMEN = 'vorgaenge_angenommen_all', + MEINE_VORGAENGE_ANGENOMMEN = 'vorgaenge_angenommen_my', + UNASSIGNED_ANGENOMMEN = 'vorgaenge_angenommen_unassigned', + ALLE_VORGAENGE_IN_BEARBEITUNG = 'vorgaenge_in_bearbeitung_all', + MEINE_VORGAENGE_IN_BEARBEITUNG = 'vorgaenge_in_bearbeitung_my', + UNASSIGNED_IN_BEARBEITUNG = 'vorgaenge_in_bearbeitung_unassigned', + ALLE_VORGAENGE_BESCHIEDEN = 'vorgaenge_beschieden_all', + MEINE_VORGAENGE_BESCHIEDEN = 'vorgaenge_beschieden_my', + UNASSIGNED_BESCHIEDEN = 'vorgaenge_beschieden_unassigned', + ALLE_VORGAENGE_ABGESCHLOSSEN = 'vorgaenge_abgeschlossen_all', + MEINE_VORGAENGE_ABGESCHLOSSEN = 'vorgaenge_abgeschlossen_my', + UNASSIGNED_ABGESCHLOSSEN = 'vorgaenge_abgeschlossen_unassigned', + ALLE_VORGAENGE_VERWORFEN = 'vorgaenge_verworfen_all', + MEINE_VORGAENGE_VERWORFEN = 'vorgaenge_verworfen_my', + UNASSIGNED_VERWORFEN = 'vorgaenge_verworfen_unassigned', + ALL_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_all', + MY_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_my', + UNASSIGNED_WIEDERVORLAGEN = 'vorgaenge_wiedervorlagen_unassigned', + ALLE_VORGAENGE_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_all', + MEINE_VORGAENGE_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_my', + UNASSIGNED_ZU_LOESCHEN = 'vorgaenge_zu_loeschen_unassigned', + DOCUMENTATIONS = 'documentations', + HINTS = 'hints', +} diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.model.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.model.ts index 8e5051c9c946cf046ccfcae5539a3beae9fea35e..266ace0fe550d962f224f602818fb4ab773fecce 100644 --- a/alfa-client/libs/api-root-shared/src/lib/api-root.model.ts +++ b/alfa-client/libs/api-root-shared/src/lib/api-root.model.ts @@ -24,18 +24,18 @@ import { Resource, ResourceUri } from '@ngxp/rest'; export interface ApiRoot { - version: string; - buildTime: string; - javaVersion: string; - production: boolean; + version: string; + buildTime: string; + javaVersion: string; + production: boolean; } -export interface ApiRootResource extends ApiRoot, Resource { } +export interface ApiRootResource extends ApiRoot, Resource {} export interface ApiDownloadToken { - token: string; + token: string; } export interface DownloadTokenRequest { - fileId: ResourceUri -} \ No newline at end of file + fileId: ResourceUri; +} diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.module.spec.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.module.spec.ts index a57da0b3a3ecb67245acaad5916993c239545c8b..ae37fe37d18631418e6c0c075c0f1d67d41b0161 100644 --- a/alfa-client/libs/api-root-shared/src/lib/api-root.module.spec.ts +++ b/alfa-client/libs/api-root-shared/src/lib/api-root.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { ApiRootModule } from './api-root.module'; describe('ApiRootModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ApiRootModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ApiRootModule], + }).compileComponents(); + }); - it('should create', () => { - expect(ApiRootModule).toBeDefined(); - }); + it('should create', () => { + expect(ApiRootModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.module.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.module.ts index 765500fbfc92e669313e44926151c55eb9b65a71..d7a298a92754524736165c02df7bc5960928c128 100644 --- a/alfa-client/libs/api-root-shared/src/lib/api-root.module.ts +++ b/alfa-client/libs/api-root-shared/src/lib/api-root.module.ts @@ -33,12 +33,12 @@ import { ApiRootRepository } from './api-root.repository'; import { ApiRootService } from './api-root.service'; @NgModule({ - imports: [ - CommonModule, - RestModule, - StoreModule.forFeature(API_ROOT_FEATURE_KEY, reducer), - EffectsModule.forFeature([ApiRootEffects]), - ], - providers: [ApiRootService, ApiRootFacade, ApiRootRepository], + imports: [ + CommonModule, + RestModule, + StoreModule.forFeature(API_ROOT_FEATURE_KEY, reducer), + EffectsModule.forFeature([ApiRootEffects]), + ], + providers: [ApiRootService, ApiRootFacade, ApiRootRepository], }) -export class ApiRootModule { } +export class ApiRootModule {} diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.repository.spec.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.repository.spec.ts index ba24af9b5d42d642c76407d4e1f0e9344f262601..3b30e8efe741daad610b87bdcf675682074e82de 100644 --- a/alfa-client/libs/api-root-shared/src/lib/api-root.repository.spec.ts +++ b/alfa-client/libs/api-root-shared/src/lib/api-root.repository.spec.ts @@ -32,55 +32,60 @@ import { createEnvironment } from 'libs/environment-shared/test/environment'; import { ApiRootRepository } from './api-root.repository'; describe('ApiRoot Repository', () => { - let repository: ApiRootRepository; - let httpService: Mock<HttpService>; - let resourceFactory = mock(ResourceFactory); - let resourceWrapper = { post: jest.fn() }; + let repository: ApiRootRepository; + let httpService: Mock<HttpService>; + let resourceFactory = mock(ResourceFactory); + let resourceWrapper = { post: jest.fn() }; - const environment: Environment = createEnvironment(); + const environment: Environment = createEnvironment(); - beforeEach(() => { - httpService = mock(HttpService); + beforeEach(() => { + httpService = mock(HttpService); - repository = new ApiRootRepository(useFromMock(httpService), useFromMock(resourceFactory), environment); + repository = new ApiRootRepository( + useFromMock(httpService), + useFromMock(resourceFactory), + environment, + ); - resourceFactory.from.mockReturnValue(resourceWrapper); - }) + resourceFactory.from.mockReturnValue(resourceWrapper); + }); - describe('loadApiRoot', () => { + describe('loadApiRoot', () => { + it('should call httpService', () => { + repository.loadApiRoot(); - it('should call httpService', () => { - repository.loadApiRoot(); + expect(httpService.get).toHaveBeenCalledWith(environment.remoteHost); + }); + }); - expect(httpService.get).toHaveBeenCalledWith(environment.remoteHost); - }) - }) + describe('downloadToken', () => { + const resource: ApiRootResource = createApiRootResource(); + const uri: ResourceUri = faker.random.word(); - describe('downloadToken', () => { - const resource: ApiRootResource = createApiRootResource(); - const uri: ResourceUri = faker.random.word(); + beforeEach(() => { + resourceWrapper.post.mockReturnValue(hot('a', { a: resource })); + }); - beforeEach(() => { - resourceWrapper.post.mockReturnValue(hot('a', { a: resource })); - }) + it('should call resourceFactory', () => { + repository.downloadToken(resource, uri); - it('should call resourceFactory', () => { - repository.downloadToken(resource, uri); + expect(resourceFactory.from).toHaveBeenCalledWith(resource); + }); - expect(resourceFactory.from).toHaveBeenCalledWith(resource); - }) + it('should call resourceWrapper with link and body', () => { + repository.downloadToken(resource, uri); - it('should call resourceWrapper with link and body', () => { - repository.downloadToken(resource, uri); + expect(resourceWrapper.post).toHaveBeenCalledWith(ApiRootLinkRel.DOWNLOAD_TOKEN, { + fileId: uri, + }); + }); - expect(resourceWrapper.post).toHaveBeenCalledWith(ApiRootLinkRel.DOWNLOAD_TOKEN, { fileId: uri }) - }) + it('should return result', () => { + let result = repository.downloadToken(resource, uri); - it('should return result', () => { - let result = repository.downloadToken(resource, uri); - - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: resource })); - }) - }) -}) + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: resource })); + }); + }); +}); diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.repository.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.repository.ts index f7c8343c0516c8321d76ea8dfb12f5478326c204..7e0731486590de2da3bf5db1247d517a855f287d 100644 --- a/alfa-client/libs/api-root-shared/src/lib/api-root.repository.ts +++ b/alfa-client/libs/api-root-shared/src/lib/api-root.repository.ts @@ -31,18 +31,19 @@ import { DownloadTokenRequest } from './api-root.model'; @Injectable() export class ApiRootRepository { + constructor( + private httpService: HttpService, + private resourceFactory: ResourceFactory, + @Inject(ENVIRONMENT_CONFIG) private environmentConfig: Environment, + ) {} - constructor( - private httpService: HttpService, - private resourceFactory: ResourceFactory, - @Inject(ENVIRONMENT_CONFIG) private environmentConfig: Environment - ) { } + public loadApiRoot(): Observable<ApiRootResource> { + return this.httpService.get(this.environmentConfig.remoteHost); + } - public loadApiRoot(): Observable<ApiRootResource> { - return this.httpService.get(this.environmentConfig.remoteHost); - } - - public downloadToken(apiRootResource: ApiRootResource, fileUri: ResourceUri): Observable<any> { - return this.resourceFactory.from(apiRootResource).post(ApiRootLinkRel.DOWNLOAD_TOKEN, <DownloadTokenRequest>{ fileId: fileUri }) - } -} \ No newline at end of file + public downloadToken(apiRootResource: ApiRootResource, fileUri: ResourceUri): Observable<any> { + return this.resourceFactory + .from(apiRootResource) + .post(ApiRootLinkRel.DOWNLOAD_TOKEN, <DownloadTokenRequest>{ fileId: fileUri }); + } +} diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.service.spec.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.service.spec.ts index d722bc81d94ac916f534f97cf9cf1d2a79eda355..6b31ca4e664c845ed921dfe0c99cb4edf266dbc9 100644 --- a/alfa-client/libs/api-root-shared/src/lib/api-root.service.spec.ts +++ b/alfa-client/libs/api-root-shared/src/lib/api-root.service.spec.ts @@ -22,7 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { BinaryFileResource } from '@alfa-client/binary-file-shared'; -import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; import { getUrl } from '@ngxp/rest'; import { hot } from 'jest-marbles'; @@ -35,101 +39,98 @@ import { ApiRootRepository } from './api-root.repository'; import { ApiRootService } from './api-root.service'; describe('ApiRootService', () => { + var repository; + var service; + var facade; - var repository; - var service; - var facade; + const apiRoot: ApiRootResource = createApiRootResource(); + const apiRootStateResource: StateResource<ApiRootResource> = createStateResource(apiRoot); - const apiRoot: ApiRootResource = createApiRootResource(); - const apiRootStateResource: StateResource<ApiRootResource> = createStateResource(apiRoot); + beforeEach(() => { + repository = mock(ApiRootRepository); + facade = mock(ApiRootFacade); + service = new ApiRootService(repository, facade); + }); - beforeEach(() => { - repository = mock(ApiRootRepository); - facade = mock(ApiRootFacade); - service = new ApiRootService(repository, facade); - }) + describe('calling getApiRoot', () => { + beforeEach(() => { + repository.loadApiRoot.mockReturnValue(of(null)); + }); - describe('calling getApiRoot', () => { + it('should call repository', () => { + service.getApiRoot(); - beforeEach(() => { - repository.loadApiRoot.mockReturnValue(of(null)); - }) + expect(repository.loadApiRoot).toHaveBeenCalled(); + }); - it('should call repository', () => { - service.getApiRoot(); + it('should not call repository if already loading', () => { + service.apiRoot$.next(createEmptyStateResource(true)); - expect(repository.loadApiRoot).toHaveBeenCalled(); - }); + service.getApiRoot(); - it('should not call repository if already loading', () => { - service.apiRoot$.next(createEmptyStateResource(true)); + expect(repository.loadApiRoot).not.toHaveBeenCalled(); + }); - service.getApiRoot(); + it('should set loading flag', () => { + service.getApiRoot(); - expect(repository.loadApiRoot).not.toHaveBeenCalled(); - }); + expect(service.apiRoot$.value.loading).toBe(true); + }); - it('should set loading flag', () => { - service.getApiRoot(); + describe('on successful load', () => { + const apiRoot: ApiRoot = createApiRoot(); - expect(service.apiRoot$.value.loading).toBe(true); - }); + beforeEach(() => { + repository.loadApiRoot.mockReturnValue(of(apiRoot)); + }); - describe('on successful load', () => { - const apiRoot: ApiRoot = createApiRoot(); + it('should set loaded', () => { + service.getApiRoot(); - beforeEach(() => { - repository.loadApiRoot.mockReturnValue(of(apiRoot)); - }) + expect(service.apiRoot$.value.loaded).toBe(true); + }); - it('should set loaded', () => { - service.getApiRoot(); + it('should set resource', () => { + service.getApiRoot(); - expect(service.apiRoot$.value.loaded).toBe(true); - }); + expect(service.apiRoot$.value.resource).toBe(apiRoot); + }); - it('should set resource', () => { - service.getApiRoot(); + it('should unset loading', () => { + service.getApiRoot(); - expect(service.apiRoot$.value.resource).toBe(apiRoot); - }); + expect(service.apiRoot$.value.loading).toBe(false); + }); + }); + }); - it('should unset loading', () => { - service.getApiRoot(); + describe('getDownloadToken', () => { + const binaryFile: BinaryFileResource = createBinaryFileResource(); - expect(service.apiRoot$.value.loading).toBe(false); - }); - }) - }) + beforeEach(() => { + facade.getApiRoot.mockReturnValue(hot('-a', { a: apiRootStateResource })); + }); - describe('getDownloadToken', () => { + it('should call getApiRoot', () => { + service.getDownloadToken(binaryFile); - const binaryFile: BinaryFileResource = createBinaryFileResource(); + expect(facade.getApiRoot).toHaveBeenCalled(); + }); - beforeEach(() => { - facade.getApiRoot.mockReturnValue(hot('-a', { a: apiRootStateResource })); - }) + it('should NOT call repository on null apiRoot', () => { + service.getApiRoot = jest.fn().mockReturnValue(of(createEmptyStateResource())); - it('should call getApiRoot', () => { - service.getDownloadToken(binaryFile); + service.getDownloadToken(binaryFile).subscribe(); - expect(facade.getApiRoot).toHaveBeenCalled(); - }) + expect(repository.downloadToken).not.toHaveBeenCalled(); + }); - it('should NOT call repository on null apiRoot', () => { - service.getApiRoot = jest.fn().mockReturnValue(of(createEmptyStateResource())); + it('should call repository', () => { + facade.getApiRoot.mockReturnValue(of(apiRootStateResource)); - service.getDownloadToken(binaryFile).subscribe(); + service.getDownloadToken(binaryFile).subscribe(); - expect(repository.downloadToken).not.toHaveBeenCalled(); - }) - - it('should call repository', () => { - facade.getApiRoot.mockReturnValue(of(apiRootStateResource)); - - service.getDownloadToken(binaryFile).subscribe(); - - expect(repository.downloadToken).toHaveBeenCalledWith(apiRoot, getUrl(binaryFile)); - }) - }) -}) \ No newline at end of file + expect(repository.downloadToken).toHaveBeenCalledWith(apiRoot, getUrl(binaryFile)); + }); + }); +}); diff --git a/alfa-client/libs/api-root-shared/src/lib/api-root.service.ts b/alfa-client/libs/api-root-shared/src/lib/api-root.service.ts index d55781c3eaa3f26bcf833d7549e39660cd570f38..e3dc4aa32f22eb19996b4f20b1fd32ebb84e9bc3 100644 --- a/alfa-client/libs/api-root-shared/src/lib/api-root.service.ts +++ b/alfa-client/libs/api-root-shared/src/lib/api-root.service.ts @@ -22,7 +22,13 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Injectable } from '@angular/core'; -import { createEmptyStateResource, createStateResource, doIfLoadingRequired, isNotNull, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + doIfLoadingRequired, + isNotNull, + StateResource, +} from '@alfa-client/tech-shared'; import { getUrl, Resource } from '@ngxp/rest'; import { BehaviorSubject, Observable } from 'rxjs'; import { filter, switchMap } from 'rxjs/operators'; @@ -32,31 +38,35 @@ import { ApiRootRepository } from './api-root.repository'; @Injectable() export class ApiRootService { + private readonly apiRoot$: BehaviorSubject<StateResource<ApiRootResource>> = new BehaviorSubject< + StateResource<ApiRootResource> + >(createEmptyStateResource<ApiRootResource>()); - private readonly apiRoot$: BehaviorSubject<StateResource<ApiRootResource>> = new BehaviorSubject<StateResource<ApiRootResource>>(createEmptyStateResource<ApiRootResource>()); + constructor( + private repository: ApiRootRepository, + private apiRootFacade: ApiRootFacade, + ) {} - constructor(private repository: ApiRootRepository, private apiRootFacade: ApiRootFacade) { } + public getApiRoot(): Observable<StateResource<ApiRootResource>> { + doIfLoadingRequired(this.apiRoot$.value, () => this.loadApiRoot()); + return this.apiRoot$.asObservable(); + } - public getApiRoot(): Observable<StateResource<ApiRootResource>> { - doIfLoadingRequired(this.apiRoot$.value, () => this.loadApiRoot()) - return this.apiRoot$.asObservable(); - } + private loadApiRoot(): void { + this.apiRoot$.next({ ...this.apiRoot$.value, loading: true }); - private loadApiRoot(): void { - this.apiRoot$.next({ ...this.apiRoot$.value, loading: true }); + this.repository.loadApiRoot().subscribe((apiRoot) => { + if (apiRoot !== null) { + this.apiRoot$.next(createStateResource(apiRoot)); + } + }); + } - this.repository.loadApiRoot().subscribe(apiRoot => { - if (apiRoot !== null) { - this.apiRoot$.next(createStateResource(apiRoot)); - } - }) - } - - //TOOD: In der Facade zur Verfuegung stellen, aufrufende Stelle anpassen und den service lib protected machen - public getDownloadToken(resource: Resource): Observable<ApiDownloadToken> { - return this.apiRootFacade.getApiRoot().pipe( - filter(apiRoot => isNotNull(apiRoot.resource)), - switchMap(apiRoot => this.repository.downloadToken(apiRoot.resource, getUrl(resource))) - ); - } -} \ No newline at end of file + //TOOD: In der Facade zur Verfuegung stellen, aufrufende Stelle anpassen und den service lib protected machen + public getDownloadToken(resource: Resource): Observable<ApiDownloadToken> { + return this.apiRootFacade.getApiRoot().pipe( + filter((apiRoot) => isNotNull(apiRoot.resource)), + switchMap((apiRoot) => this.repository.downloadToken(apiRoot.resource, getUrl(resource))), + ); + } +} diff --git a/alfa-client/libs/api-root-shared/src/test-setup.ts b/alfa-client/libs/api-root-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/api-root-shared/src/test-setup.ts +++ b/alfa-client/libs/api-root-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/api-root-shared/test/api-root.ts b/alfa-client/libs/api-root-shared/test/api-root.ts index 87e59a270fb27cf2ed82fceb7dc0033eb7c38c27..a64c0a3a0d25ab7e9e2c5761ecbbfde019485cbf 100644 --- a/alfa-client/libs/api-root-shared/test/api-root.ts +++ b/alfa-client/libs/api-root-shared/test/api-root.ts @@ -25,15 +25,14 @@ import { toResource } from 'libs/tech-shared/test/resource'; import { ApiRoot, ApiRootResource } from '../src/lib/api-root.model'; export function createApiRootResource(linkRels: string[] = []): ApiRootResource { - return toResource(createApiRoot(), linkRels); + return toResource(createApiRoot(), linkRels); } export function createApiRoot(): ApiRoot { - return { - version: '1', - buildTime: '1', - javaVersion: '1', - production: false, - } + return { + version: '1', + buildTime: '1', + javaVersion: '1', + production: false, + }; } - diff --git a/alfa-client/libs/api-root-shared/tsconfig.json b/alfa-client/libs/api-root-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/api-root-shared/tsconfig.json +++ b/alfa-client/libs/api-root-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/api-root-shared/tsconfig.lib.json b/alfa-client/libs/api-root-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/api-root-shared/tsconfig.lib.json +++ b/alfa-client/libs/api-root-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/api-root-shared/tsconfig.spec.json b/alfa-client/libs/api-root-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/api-root-shared/tsconfig.spec.json +++ b/alfa-client/libs/api-root-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/app-shared/.eslintrc.json b/alfa-client/libs/app-shared/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/app-shared/.eslintrc.json +++ b/alfa-client/libs/app-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/app-shared/jest.config.ts b/alfa-client/libs/app-shared/jest.config.ts index 766e20f2f63db922cd5506517be0a5e39f6da7f7..878c1f30c7c82e675e689b125c5d2e2ff8a19cda 100644 --- a/alfa-client/libs/app-shared/jest.config.ts +++ b/alfa-client/libs/app-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'app-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/app-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'app-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/app-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/app-shared/project.json b/alfa-client/libs/app-shared/project.json index aa37703630a88ba7968819bb842774e156e801d9..f6e7f0f7c571b80fae83ac03113a85387a9dd06c 100644 --- a/alfa-client/libs/app-shared/project.json +++ b/alfa-client/libs/app-shared/project.json @@ -1,34 +1,31 @@ { - "name": "app-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/app-shared/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/app-shared/src/**/*.ts", - "libs/app-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/app-shared/tsconfig.spec.json", - "jestConfig": "libs/app-shared/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/app-shared"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "app-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/app-shared/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/app-shared/src/**/*.ts", "libs/app-shared/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/app-shared/tsconfig.spec.json", + "jestConfig": "libs/app-shared/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/app-shared"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/app-shared/src/lib/app-shared.module.spec.ts b/alfa-client/libs/app-shared/src/lib/app-shared.module.spec.ts index 19773573d8a3b73c84f47763b7ed2376d5ec5555..c5bce8845702b27e2a89de0d54c1b0a0d0f18d5a 100644 --- a/alfa-client/libs/app-shared/src/lib/app-shared.module.spec.ts +++ b/alfa-client/libs/app-shared/src/lib/app-shared.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { AppSharedModule } from './app-shared.module'; describe('AppSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [AppSharedModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [AppSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(AppSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(AppSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/app-shared/src/lib/app-shared.module.ts b/alfa-client/libs/app-shared/src/lib/app-shared.module.ts index b9199b88b223a72075ce242d9c4f80abe6a440e9..6ec0b7fc6f21a7fcbba11130b65f3de28984b570 100644 --- a/alfa-client/libs/app-shared/src/lib/app-shared.module.ts +++ b/alfa-client/libs/app-shared/src/lib/app-shared.module.ts @@ -27,12 +27,7 @@ import { RestModule } from '@ngxp/rest'; import { AppService } from './app.service'; @NgModule({ - imports: [ - CommonModule, - RestModule, - ], - providers: [ - AppService - ] + imports: [CommonModule, RestModule], + providers: [AppService], }) -export class AppSharedModule { } +export class AppSharedModule {} diff --git a/alfa-client/libs/app-shared/src/lib/app.service.spec.ts b/alfa-client/libs/app-shared/src/lib/app.service.spec.ts index 29fdfc7bf7cb8f8db0df9fb294ad8a85434ba86b..feed5c081eed7f6c0dd6a608425e7605a15a7da9 100644 --- a/alfa-client/libs/app-shared/src/lib/app.service.spec.ts +++ b/alfa-client/libs/app-shared/src/lib/app.service.spec.ts @@ -26,25 +26,24 @@ import { AppService } from './app.service'; import * as LocalStorage from './storage/storage'; describe('AppService', () => { - let service: AppService; + let service: AppService; - beforeEach(() => { - service = new AppService(); - }) + beforeEach(() => { + service = new AppService(); + }); - it('should create', () => { - expect(service).toBeTruthy(); - }) + it('should create', () => { + expect(service).toBeTruthy(); + }); - describe('setDarkMode', () => { + describe('setDarkMode', () => { + const darkModeStorage = jest.spyOn(LocalStorage, 'setDarkModeIntoStorage'); + const darkMode: boolean = true; - const darkModeStorage = jest.spyOn(LocalStorage, 'setDarkModeIntoStorage'); - const darkMode: boolean = true; + it('should set in localStorage', () => { + service.setDarkMode(darkMode); - it('should set in localStorage', () => { - service.setDarkMode(darkMode); - - expect(darkModeStorage).toHaveBeenCalledWith('true'); - }) - }) -}) \ No newline at end of file + expect(darkModeStorage).toHaveBeenCalledWith('true'); + }); + }); +}); diff --git a/alfa-client/libs/app-shared/src/lib/app.service.ts b/alfa-client/libs/app-shared/src/lib/app.service.ts index 9e18a8a202ad54132ed836969008f08ad9a93e58..0f1aa8c05f2ae7e1aa87aa3ea24de3d2ba34977b 100644 --- a/alfa-client/libs/app-shared/src/lib/app.service.ts +++ b/alfa-client/libs/app-shared/src/lib/app.service.ts @@ -27,16 +27,17 @@ import { getDarkModeFromLocalStorage, setDarkModeIntoStorage } from './storage/s @Injectable() export class AppService { + private readonly darkMode: BehaviorSubject<boolean> = new BehaviorSubject( + Boolean(JSON.parse(getDarkModeFromLocalStorage())), + ); - private readonly darkMode: BehaviorSubject<boolean> = new BehaviorSubject(Boolean((JSON.parse(getDarkModeFromLocalStorage())))); + public setDarkMode(darkMode: boolean): void { + setDarkModeIntoStorage(String(darkMode)); - public setDarkMode(darkMode: boolean): void { - setDarkModeIntoStorage(String(darkMode)); + this.darkMode.next(darkMode); + } - this.darkMode.next(darkMode); - } - - public getDarkMode(): Observable<boolean> { - return this.darkMode; - } -} \ No newline at end of file + public getDarkMode(): Observable<boolean> { + return this.darkMode; + } +} diff --git a/alfa-client/libs/app-shared/src/lib/auth.service.spec.ts b/alfa-client/libs/app-shared/src/lib/auth.service.spec.ts index 30c7c99ba9cac7d234f84336b56678a01f0d0cbb..dc8817ac440dc30ea216b77be84c4289f47185d3 100644 --- a/alfa-client/libs/app-shared/src/lib/auth.service.spec.ts +++ b/alfa-client/libs/app-shared/src/lib/auth.service.spec.ts @@ -8,101 +8,101 @@ import { AuthService } from './auth.service'; import * as Storage from './storage/storage'; describe('AuthService', () => { - let service: AuthService; - const oAuthService = mock(OAuthService); - const environment: Environment = createEnvironment(); - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - { - provide: OAuthService, - useValue: oAuthService - }, - { - provide: ENVIRONMENT_CONFIG, - useValue: environment - }, - ] - }); - service = TestBed.inject(AuthService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); - - describe('hasNoValidToken', () => { - it('should return false if both tokens are valid', () => { - jest.spyOn(oAuthService, 'hasValidAccessToken').mockReturnValue(true); - jest.spyOn(oAuthService, 'hasValidIdToken').mockReturnValue(true); - - TestBed.runInInjectionContext(() => { - const result: boolean = service.hasNoValidToken(); - - expect(result).toBeFalsy(); - }); - }) - - it('should return true if access token is invalid', () => { - jest.spyOn(oAuthService, 'hasValidAccessToken').mockReturnValue(false); - jest.spyOn(oAuthService, 'hasValidIdToken').mockReturnValue(true); - - TestBed.runInInjectionContext(() => { - const result: boolean = service.hasNoValidToken(); - - expect(result).toBeTruthy(); - }); - }) - - it('should return true if id token is invalid', () => { - jest.spyOn(oAuthService, 'hasValidAccessToken').mockReturnValue(true); - jest.spyOn(oAuthService, 'hasValidIdToken').mockReturnValue(false); - - TestBed.runInInjectionContext(() => { - const result: boolean = service.hasNoValidToken(); - - expect(result).toBeTruthy(); - }); - }) - - it('should return true if both tokens are invalid', () => { - jest.spyOn(oAuthService, 'hasValidAccessToken').mockReturnValue(false); - jest.spyOn(oAuthService, 'hasValidIdToken').mockReturnValue(false); - - TestBed.runInInjectionContext(() => { - const result: boolean = service.hasNoValidToken(); - - expect(result).toBeTruthy(); - }); - }) - }) - - describe('logout', () => { - it('should call oAuthService.logout', () => { - const spy: jest.SpyInstance<void, any> = jest.spyOn(oAuthService, 'logOut'); - - service.logout(); - - expect(spy).toHaveBeenCalled(); - }) - }) - - describe('logoutWithConfirmation', () => { - it('should call sessionStorage.removeItem with id_token', () => { - const spy: jest.SpyInstance<void> = jest.spyOn(Storage, 'removeIdTokenFromSessionStorage'); - - service.logoutWithConfirmation(); - - expect(spy).toHaveBeenCalled(); - }) - - it('should call oAuthService.logout', () => { - const customParameters: object = { client_id: environment.clientId }; - - service.logoutWithConfirmation(); - - expect(oAuthService.logOut).toHaveBeenCalledWith(customParameters); - }) - }) + let service: AuthService; + const oAuthService = mock(OAuthService); + const environment: Environment = createEnvironment(); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + { + provide: OAuthService, + useValue: oAuthService, + }, + { + provide: ENVIRONMENT_CONFIG, + useValue: environment, + }, + ], + }); + service = TestBed.inject(AuthService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + describe('hasNoValidToken', () => { + it('should return false if both tokens are valid', () => { + jest.spyOn(oAuthService, 'hasValidAccessToken').mockReturnValue(true); + jest.spyOn(oAuthService, 'hasValidIdToken').mockReturnValue(true); + + TestBed.runInInjectionContext(() => { + const result: boolean = service.hasNoValidToken(); + + expect(result).toBeFalsy(); + }); + }); + + it('should return true if access token is invalid', () => { + jest.spyOn(oAuthService, 'hasValidAccessToken').mockReturnValue(false); + jest.spyOn(oAuthService, 'hasValidIdToken').mockReturnValue(true); + + TestBed.runInInjectionContext(() => { + const result: boolean = service.hasNoValidToken(); + + expect(result).toBeTruthy(); + }); + }); + + it('should return true if id token is invalid', () => { + jest.spyOn(oAuthService, 'hasValidAccessToken').mockReturnValue(true); + jest.spyOn(oAuthService, 'hasValidIdToken').mockReturnValue(false); + + TestBed.runInInjectionContext(() => { + const result: boolean = service.hasNoValidToken(); + + expect(result).toBeTruthy(); + }); + }); + + it('should return true if both tokens are invalid', () => { + jest.spyOn(oAuthService, 'hasValidAccessToken').mockReturnValue(false); + jest.spyOn(oAuthService, 'hasValidIdToken').mockReturnValue(false); + + TestBed.runInInjectionContext(() => { + const result: boolean = service.hasNoValidToken(); + + expect(result).toBeTruthy(); + }); + }); + }); + + describe('logout', () => { + it('should call oAuthService.logout', () => { + const spy: jest.SpyInstance<void, any> = jest.spyOn(oAuthService, 'logOut'); + + service.logout(); + + expect(spy).toHaveBeenCalled(); + }); + }); + + describe('logoutWithConfirmation', () => { + it('should call sessionStorage.removeItem with id_token', () => { + const spy: jest.SpyInstance<void> = jest.spyOn(Storage, 'removeIdTokenFromSessionStorage'); + + service.logoutWithConfirmation(); + + expect(spy).toHaveBeenCalled(); + }); + + it('should call oAuthService.logout', () => { + const customParameters: object = { client_id: environment.clientId }; + + service.logoutWithConfirmation(); + + expect(oAuthService.logOut).toHaveBeenCalledWith(customParameters); + }); + }); }); diff --git a/alfa-client/libs/app-shared/src/lib/auth.service.ts b/alfa-client/libs/app-shared/src/lib/auth.service.ts index f92d5eee7ddb102d6623226828aa80fe308c0121..704e9ca4fe6aed0a1630300e4eb62c7aa4092d46 100644 --- a/alfa-client/libs/app-shared/src/lib/auth.service.ts +++ b/alfa-client/libs/app-shared/src/lib/auth.service.ts @@ -4,27 +4,26 @@ import { OAuthService } from 'angular-oauth2-oidc'; import { removeIdTokenFromSessionStorage } from './storage/storage'; @Injectable({ - providedIn: 'root' + providedIn: 'root', }) export class AuthService { + constructor( + private oAuthService: OAuthService, + @Inject(ENVIRONMENT_CONFIG) private envConfig: Environment, + ) {} - constructor( - private oAuthService: OAuthService, - @Inject(ENVIRONMENT_CONFIG) private envConfig: Environment, - ) { } + public hasNoValidToken(): boolean { + return !(this.oAuthService.hasValidAccessToken() && this.oAuthService.hasValidIdToken()); + } - public hasNoValidToken(): boolean { - return ! (this.oAuthService.hasValidAccessToken() && this.oAuthService.hasValidIdToken()); - } + public logout(): void { + this.oAuthService.logOut(); + } - public logout(): void { - this.oAuthService.logOut(); - } + public logoutWithConfirmation(): void { + removeIdTokenFromSessionStorage(); - public logoutWithConfirmation(): void { - removeIdTokenFromSessionStorage(); - - const customParameters: object = { client_id: this.envConfig.clientId }; - this.oAuthService.logOut(customParameters); - } + const customParameters: object = { client_id: this.envConfig.clientId }; + this.oAuthService.logOut(customParameters); + } } diff --git a/alfa-client/libs/app-shared/src/lib/storage/storage.spec.ts b/alfa-client/libs/app-shared/src/lib/storage/storage.spec.ts index ec594aa8a6a40b55d45a66b9770f314bffff8474..0c3d41ec93d860acede31301cc23b3daa7757415 100644 --- a/alfa-client/libs/app-shared/src/lib/storage/storage.spec.ts +++ b/alfa-client/libs/app-shared/src/lib/storage/storage.spec.ts @@ -1,16 +1,14 @@ import { removeIdTokenFromSessionStorage } from './storage'; beforeAll(() => { - // Mocking the prototype affects localStorage as well as sessionStorage - jest.spyOn(Object.getPrototypeOf(window.sessionStorage), 'removeItem'); -}) + // Mocking the prototype affects localStorage as well as sessionStorage + jest.spyOn(Object.getPrototypeOf(window.sessionStorage), 'removeItem'); +}); describe('removeIdTokenFromSessionStorage', () => { + it('should call sessionStorage.removeItem', () => { + removeIdTokenFromSessionStorage(); - it('should call sessionStorage.removeItem', () => { - removeIdTokenFromSessionStorage(); - - expect(sessionStorage.removeItem).toHaveBeenCalledWith('id_token'); - }) - -}) \ No newline at end of file + expect(sessionStorage.removeItem).toHaveBeenCalledWith('id_token'); + }); +}); diff --git a/alfa-client/libs/app-shared/src/lib/storage/storage.ts b/alfa-client/libs/app-shared/src/lib/storage/storage.ts index 2e43cc87c3ab9a32a5a8547281e666adca39841e..74cdb3717c28c4a2f604e9f10628e0eab49c5eff 100644 --- a/alfa-client/libs/app-shared/src/lib/storage/storage.ts +++ b/alfa-client/libs/app-shared/src/lib/storage/storage.ts @@ -27,37 +27,37 @@ export const localStorageFilter: string = 'filter'; export const localStorageView: string = 'view'; export function setDarkModeIntoStorage(value: string): void { - localStorage.setItem(localStorageDark, value); + localStorage.setItem(localStorageDark, value); } export function getDarkModeFromLocalStorage(): string { - return localStorage.getItem(localStorageDark); + return localStorage.getItem(localStorageDark); } export function setFilterIntoStorage(value: string): void { - localStorage.setItem(localStorageFilter, value); + localStorage.setItem(localStorageFilter, value); } export function getFilterFromLocalStorage(): string { - return localStorage.getItem(localStorageFilter); + return localStorage.getItem(localStorageFilter); } export function setViewIntoStorage(value: string): void { - localStorage.setItem(localStorageView, value); + localStorage.setItem(localStorageView, value); } export function getViewFromLocalStorage(): string { - return localStorage.getItem(localStorageView); + return localStorage.getItem(localStorageView); } export function removeLocalStorageView(): void { - localStorage.removeItem(localStorageView); + localStorage.removeItem(localStorageView); } export function removeLocalStorageFilter(): void { - localStorage.removeItem(localStorageFilter); + localStorage.removeItem(localStorageFilter); } export function removeIdTokenFromSessionStorage(): void { - sessionStorage.removeItem('id_token'); -} \ No newline at end of file + sessionStorage.removeItem('id_token'); +} diff --git a/alfa-client/libs/app-shared/src/test-setup.ts b/alfa-client/libs/app-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/app-shared/src/test-setup.ts +++ b/alfa-client/libs/app-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/app-shared/tsconfig.json b/alfa-client/libs/app-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/app-shared/tsconfig.json +++ b/alfa-client/libs/app-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/app-shared/tsconfig.lib.json b/alfa-client/libs/app-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/app-shared/tsconfig.lib.json +++ b/alfa-client/libs/app-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/app-shared/tsconfig.spec.json b/alfa-client/libs/app-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/app-shared/tsconfig.spec.json +++ b/alfa-client/libs/app-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/bescheid-shared/.eslintrc.json b/alfa-client/libs/bescheid-shared/.eslintrc.json index 7b7b6231394b8c5674ce1b007077d4327aea7fda..9416ef7fe3c2643718ea92627388bf35847fc788 100644 --- a/alfa-client/libs/bescheid-shared/.eslintrc.json +++ b/alfa-client/libs/bescheid-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - }, - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ] - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + }, + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"] + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/bescheid-shared/jest.config.ts b/alfa-client/libs/bescheid-shared/jest.config.ts index 245218e41948fc892626b498859a534712ef33fa..226486ae2604f0f0bec413f17dc0141026c55c6c 100644 --- a/alfa-client/libs/bescheid-shared/jest.config.ts +++ b/alfa-client/libs/bescheid-shared/jest.config.ts @@ -1,22 +1,22 @@ export default { - displayName: 'bescheid-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/bescheid-shared', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'bescheid-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/bescheid-shared', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/bescheid-shared/project.json b/alfa-client/libs/bescheid-shared/project.json index 45a24331911c9172ca12290a4cae0e0309b4d943..967342fdb29603b7432e0a599f339af36d81b7b9 100644 --- a/alfa-client/libs/bescheid-shared/project.json +++ b/alfa-client/libs/bescheid-shared/project.json @@ -1,29 +1,29 @@ { - "name": "bescheid-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/bescheid-shared/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/bescheid-shared"], - "options": { - "tsConfig": "libs/bescheid-shared/tsconfig.spec.json", - "jestConfig": "libs/bescheid-shared/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/bescheid-shared/src/**/*.ts", - "libs/bescheid-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [] + "name": "bescheid-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/bescheid-shared/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/bescheid-shared"], + "options": { + "tsConfig": "libs/bescheid-shared/tsconfig.spec.json", + "jestConfig": "libs/bescheid-shared/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/bescheid-shared/src/**/*.ts", + "libs/bescheid-shared/src/**/*.html" + ] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [] } diff --git a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.facade.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.facade.spec.ts index b065dc4252e7ea2e5b5c6eb16582d2b7a7ed48c9..b07673efb637d2565358c33723a9953ee187923b 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.facade.spec.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.facade.spec.ts @@ -12,40 +12,44 @@ import { BescheidFacade } from './bescheid.facade'; import * as CommandActions from '../../../../command-shared/src/lib/+state/command.actions'; describe('BescheidFacade', () => { - const store: Mock<Store> = mock(Store); - let facade: BescheidFacade; - let selectSubj: Subject<StateResource<Resource>>; - - beforeEach(() => { - selectSubj = new Subject(); - store.select.mockReturnValue(selectSubj); - - facade = new BescheidFacade(useFromMock(store)); - }); - - describe('getBescheidCommand', () => { - - it('should return selected value', (done) => { - const expected: StateResource<CommandResource> = createStateResource(createCommandResource()); - - facade.getBescheidCommand().subscribe(userSettings => { - expect(userSettings).toBe(expected); - done(); - }); - - selectSubj.next(expected); - }) - }) - - describe('createBescheid', () => { - - it('should dispatch "createCommand"', () => { - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const createCommand: CreateCommand = createCreateCommand(CommandOrder.CREATE_BESCHEID); - - facade.createBescheid(vorgangWithEingang, createCommand); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.CREATE_BESCHEID , command: createCommand })) - }) - }) -}) \ No newline at end of file + const store: Mock<Store> = mock(Store); + let facade: BescheidFacade; + let selectSubj: Subject<StateResource<Resource>>; + + beforeEach(() => { + selectSubj = new Subject(); + store.select.mockReturnValue(selectSubj); + + facade = new BescheidFacade(useFromMock(store)); + }); + + describe('getBescheidCommand', () => { + it('should return selected value', (done) => { + const expected: StateResource<CommandResource> = createStateResource(createCommandResource()); + + facade.getBescheidCommand().subscribe((userSettings) => { + expect(userSettings).toBe(expected); + done(); + }); + + selectSubj.next(expected); + }); + }); + + describe('createBescheid', () => { + it('should dispatch "createCommand"', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const createCommand: CreateCommand = createCreateCommand(CommandOrder.CREATE_BESCHEID); + + facade.createBescheid(vorgangWithEingang, createCommand); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.CREATE_BESCHEID, + command: createCommand, + }), + ); + }); + }); +}); diff --git a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.facade.ts b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.facade.ts index 43a4f4efb1463d86846a92be1538cf8e1cfead93..edc0f3cf13e936863b5dc18fbfef37e212b7c2e3 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.facade.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.facade.ts @@ -10,14 +10,22 @@ import * as BescheidSelectors from './bescheid.selectors'; @Injectable() export class BescheidFacade { + constructor(private store: Store) {} - constructor(private store: Store) { } + public getBescheidCommand(): Observable<StateResource<CommandResource>> { + return this.store.select(BescheidSelectors.bescheidCommand); + } - public getBescheidCommand(): Observable<StateResource<CommandResource>> { - return this.store.select(BescheidSelectors.bescheidCommand); - } - - public createBescheid(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.CREATE_BESCHEID, command })) - } -} \ No newline at end of file + public createBescheid( + vorgangWithEingang: VorgangWithEingangResource, + command: CreateCommand, + ): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.CREATE_BESCHEID, + command, + }), + ); + } +} diff --git a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.spec.ts index ba9b5f16ebe4e6595eba6ce4ee6319d6cfd686ad..4bb1aaeb771597aa5bfa7e3298cf72bc6f424242 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.spec.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.spec.ts @@ -8,42 +8,44 @@ import { BescheidState, initialState, reducer } from './bescheid.reducer'; import * as CommandActions from '../../../../command-shared/src/lib/+state/command.actions'; describe('Bescheid Reducer', () => { - - describe('unknown action', () => { - - it('should return current state', () => { - const action: Action = {} as Action; - - const result = reducer(initialState, action); - - expect(result).toBe(initialState); - }) - }) - - describe('bescheidCommand', () => { - - describe('on "createCommand" action', () => { - - it('should set resource loading', () => { - const resource: VorgangWithEingangResource = createVorgangWithEingangResource(); - const action: Action = CommandActions.createCommand({ resource, linkRel: VorgangWithEingangLinkRel.CREATE_BESCHEID, command: { ...createCommandResource(), order: CommandOrder.CREATE_BESCHEID } }); - - const state: BescheidState = reducer(initialState, action); - - expect(state.bescheidCommand.loading).toBeTruthy(); - }) - }) - - describe('on "createCommandSuccess" action', () => { - - it('should set resource', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.CREATE_BESCHEID }; - const action: Action = CommandActions.createCommandSuccess({ command }); - - const state: BescheidState = reducer(initialState, action); - - expect(state.bescheidCommand.resource).toBe(command); - }) - }) - }) -}) \ No newline at end of file + describe('unknown action', () => { + it('should return current state', () => { + const action: Action = {} as Action; + + const result = reducer(initialState, action); + + expect(result).toBe(initialState); + }); + }); + + describe('bescheidCommand', () => { + describe('on "createCommand" action', () => { + it('should set resource loading', () => { + const resource: VorgangWithEingangResource = createVorgangWithEingangResource(); + const action: Action = CommandActions.createCommand({ + resource, + linkRel: VorgangWithEingangLinkRel.CREATE_BESCHEID, + command: { ...createCommandResource(), order: CommandOrder.CREATE_BESCHEID }, + }); + + const state: BescheidState = reducer(initialState, action); + + expect(state.bescheidCommand.loading).toBeTruthy(); + }); + }); + + describe('on "createCommandSuccess" action', () => { + it('should set resource', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.CREATE_BESCHEID, + }; + const action: Action = CommandActions.createCommandSuccess({ command }); + + const state: BescheidState = reducer(initialState, action); + + expect(state.bescheidCommand.resource).toBe(command); + }); + }); + }); +}); diff --git a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.ts b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.ts index 4d6ec9badeff4e078d2ae753add1fb78b3b6ae7b..0982bb1ff81a3ca7c2be852749c396099199aa6c 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.reducer.ts @@ -1,5 +1,9 @@ import { CommandProps, CommandResource, CreateCommandProps } from '@alfa-client/command-shared'; -import { StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Action, ActionReducer, createReducer, on } from '@ngrx/store'; import { isCreateBescheidCommand } from '../bescheid.util'; @@ -8,31 +12,37 @@ import * as CommandActions from '../../../../command-shared/src/lib/+state/comma export const BESCHEID_FEATURE_KEY = 'BescheidState'; export interface BescheidPartialState { - readonly [BESCHEID_FEATURE_KEY]: BescheidState; + readonly [BESCHEID_FEATURE_KEY]: BescheidState; } export interface BescheidState { - bescheidCommand: StateResource<CommandResource> + bescheidCommand: StateResource<CommandResource>; } export const initialState: BescheidState = { - bescheidCommand: createEmptyStateResource() + bescheidCommand: createEmptyStateResource(), }; const bescheidReducer: ActionReducer<BescheidState, Action> = createReducer( - initialState, - on(CommandActions.createCommand, (state: BescheidState, props: CreateCommandProps): BescheidState => { - return isCreateBescheidCommand(props.command.order) - ? { ...state, bescheidCommand: { ...state.bescheidCommand, loading: true } } - : state; - }), - on(CommandActions.createCommandSuccess, (state: BescheidState, props: CommandProps): BescheidState => { - return isCreateBescheidCommand(props.command.order) - ? { ...state, bescheidCommand: createStateResource(props.command) } - : state; - }), + initialState, + on( + CommandActions.createCommand, + (state: BescheidState, props: CreateCommandProps): BescheidState => { + return isCreateBescheidCommand(props.command.order) ? + { ...state, bescheidCommand: { ...state.bescheidCommand, loading: true } } + : state; + }, + ), + on( + CommandActions.createCommandSuccess, + (state: BescheidState, props: CommandProps): BescheidState => { + return isCreateBescheidCommand(props.command.order) ? + { ...state, bescheidCommand: createStateResource(props.command) } + : state; + }, + ), ); export function reducer(state: BescheidState, action: Action): BescheidState { - return bescheidReducer(state, action); + return bescheidReducer(state, action); } diff --git a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.selectors.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.selectors.spec.ts index 2372a613c438c3414c11b98b6f947c88a5d98bfc..04f7dfd10e8da45695ae20069e5d11713af0e6b0 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.selectors.spec.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.selectors.spec.ts @@ -6,24 +6,25 @@ import { BescheidPartialState, initialState } from './bescheid.reducer'; import * as BescheidSelectors from './bescheid.selectors'; describe('Bescheid Selectors', () => { + let state: BescheidPartialState; - let state: BescheidPartialState; + const bescheidCommand: StateResource<CommandResource> = + createStateResource(createCommandResource()); - const bescheidCommand: StateResource<CommandResource> = createStateResource(createCommandResource()); + beforeEach(() => { + state = { + BescheidState: { + ...initialState, + bescheidCommand, + }, + }; + }); - beforeEach(() => { - state = { - BescheidState: { - ...initialState, - bescheidCommand - } - } - }) - - describe('bescheidCommand', () => { - - it('should return bescheidCommand from state', () => { - expect(BescheidSelectors.bescheidCommand.projector(state.BescheidState)).toEqual(bescheidCommand); - }) - }) -}) \ No newline at end of file + describe('bescheidCommand', () => { + it('should return bescheidCommand from state', () => { + expect(BescheidSelectors.bescheidCommand.projector(state.BescheidState)).toEqual( + bescheidCommand, + ); + }); + }); +}); diff --git a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.selectors.ts b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.selectors.ts index 81832e3d7b0806db6ed32f50ddf555615b14de4f..78facfef40dad11ac7ae2cb68ce9679e41301e5b 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.selectors.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/+state/bescheid.selectors.ts @@ -3,6 +3,10 @@ import { StateResource } from '@alfa-client/tech-shared'; import { createFeatureSelector, createSelector, MemoizedSelector } from '@ngrx/store'; import { BESCHEID_FEATURE_KEY, BescheidState } from './bescheid.reducer'; -export const getBescheidState: MemoizedSelector<object, BescheidState> = createFeatureSelector<BescheidState>(BESCHEID_FEATURE_KEY); +export const getBescheidState: MemoizedSelector<object, BescheidState> = + createFeatureSelector<BescheidState>(BESCHEID_FEATURE_KEY); -export const bescheidCommand: MemoizedSelector<BescheidState, StateResource<CommandResource>> = createSelector(getBescheidState, (state: BescheidState) => state.bescheidCommand); \ No newline at end of file +export const bescheidCommand: MemoizedSelector< + BescheidState, + StateResource<CommandResource> +> = createSelector(getBescheidState, (state: BescheidState) => state.bescheidCommand); diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid-shared.module.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid-shared.module.spec.ts index b9c321128a88d786be8392ed2137e1ec608dcd8f..2b49d505e2c6d9459478f2a94c1c11b0dfc58e02 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid-shared.module.spec.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid-shared.module.spec.ts @@ -2,13 +2,13 @@ import { TestBed } from '@angular/core/testing'; import { BescheidSharedModule } from './bescheid-shared.module'; describe('BescheidSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [BescheidSharedModule] - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [BescheidSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(BescheidSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(BescheidSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid-shared.module.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid-shared.module.ts index 1ec7d62add0710b30d79981d53798e6097eb615d..98624ede19929f1cc0a52270494e132089a247b0 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid-shared.module.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid-shared.module.ts @@ -6,10 +6,7 @@ import { BESCHEID_FEATURE_KEY, reducer } from './+state/bescheid.reducer'; import { BescheidService } from './bescheid.service'; @NgModule({ - imports: [ - CommonModule, - StoreModule.forFeature(BESCHEID_FEATURE_KEY, reducer) - ], - providers: [BescheidService, BescheidFacade] + imports: [CommonModule, StoreModule.forFeature(BESCHEID_FEATURE_KEY, reducer)], + providers: [BescheidService, BescheidFacade], }) -export class BescheidSharedModule { } +export class BescheidSharedModule {} diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts index 01d05f54e914c44482f2ab0b51227502fb6ecde9..ea19e6c47512fd63d6cf026db0398c3cee7516ed 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.spec.ts @@ -6,37 +6,38 @@ import { BescheidService } from './bescheid.service'; import { buildCreateBescheidCommand } from './bescheid.util'; describe('BescheidService', () => { - let facade: Mock<BescheidFacade>; + let facade: Mock<BescheidFacade>; - let service: BescheidService; + let service: BescheidService; - beforeEach(() => { - facade = mock(BescheidFacade); + beforeEach(() => { + facade = mock(BescheidFacade); - service = new BescheidService(useFromMock(facade)); - }) + service = new BescheidService(useFromMock(facade)); + }); - it('should be created', () => { - expect(service).toBeTruthy(); - }) + it('should be created', () => { + expect(service).toBeTruthy(); + }); - describe('getBescheidCommand', () => { + describe('getBescheidCommand', () => { + it('should call facade', () => { + service.getBescheidCommand(); - it('should call facade', () => { - service.getBescheidCommand(); + expect(facade.getBescheidCommand).toHaveBeenCalled(); + }); + }); - expect(facade.getBescheidCommand).toHaveBeenCalled(); - }) - }) + describe('createBescheid', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - describe('createBescheid', () => { + it('should call facade', () => { + service.createBescheid(vorgangWithEingang); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - it('should call facade', () => { - service.createBescheid(vorgangWithEingang); - - expect(facade.createBescheid).toHaveBeenCalledWith(vorgangWithEingang, buildCreateBescheidCommand()); - }) - }) -}) \ No newline at end of file + expect(facade.createBescheid).toHaveBeenCalledWith( + vorgangWithEingang, + buildCreateBescheidCommand(), + ); + }); + }); +}); diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts index 5ccb48282b0af37801632981a9c4b971ed93d1c8..331a0a49aecc555fee5b7995a4d2c0970582433d 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.service.ts @@ -8,14 +8,13 @@ import { buildCreateBescheidCommand } from './bescheid.util'; @Injectable() export class BescheidService { + constructor(private facade: BescheidFacade) {} - constructor(private facade: BescheidFacade){ } + public getBescheidCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getBescheidCommand(); + } - public getBescheidCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getBescheidCommand(); - } - - public createBescheid(vorgangWithEingang: VorgangWithEingangResource): void { - this.facade.createBescheid(vorgangWithEingang, buildCreateBescheidCommand()); - } -} \ No newline at end of file + public createBescheid(vorgangWithEingang: VorgangWithEingangResource): void { + this.facade.createBescheid(vorgangWithEingang, buildCreateBescheidCommand()); + } +} diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.util.spec.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.util.spec.ts index 4b9a3bc0cb93b7d3e2616cd3c877e25df47cf035..2b8a30c80b4869f5206b806254272b0c0bbb4617 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.util.spec.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.util.spec.ts @@ -1,29 +1,26 @@ -import { CommandOrder, CreateCommand } from "@alfa-client/command-shared"; -import { buildCreateBescheidCommand, isCreateBescheidCommand } from "./bescheid.util"; +import { CommandOrder, CreateCommand } from '@alfa-client/command-shared'; +import { buildCreateBescheidCommand, isCreateBescheidCommand } from './bescheid.util'; describe('BescheidUtil', () => { + describe('buildCreateBescheidCommand', () => { + it('should have order', () => { + const command: CreateCommand = buildCreateBescheidCommand(); - describe('buildCreateBescheidCommand', () => { + expect(command.order).toEqual(CommandOrder.CREATE_BESCHEID); + }); - it('should have order', () => { - const command: CreateCommand = buildCreateBescheidCommand(); + it('should have body', () => { + const command: CreateCommand = buildCreateBescheidCommand(); - expect(command.order).toEqual(CommandOrder.CREATE_BESCHEID); - }) + expect(command.body).toBeNull(); + }); + }); - it('should have body', () => { - const command: CreateCommand = buildCreateBescheidCommand(); + describe('isCreateBescheidCommand', () => { + it('should return true on matching command', () => { + const isCommand: boolean = isCreateBescheidCommand(CommandOrder.CREATE_BESCHEID); - expect(command.body).toBeNull(); - }) - }) - - describe('isCreateBescheidCommand', () => { - - it('should return true on matching command', () => { - const isCommand: boolean = isCreateBescheidCommand(CommandOrder.CREATE_BESCHEID); - - expect(isCommand).toBeTruthy(); - }) - }) -}) \ No newline at end of file + expect(isCommand).toBeTruthy(); + }); + }); +}); diff --git a/alfa-client/libs/bescheid-shared/src/lib/bescheid.util.ts b/alfa-client/libs/bescheid-shared/src/lib/bescheid.util.ts index a24a9112beda9a1037645cbf91f46d5d93ca616d..ffc13a4bec310ad87a9ecf0d706bdc740eeef6cc 100644 --- a/alfa-client/libs/bescheid-shared/src/lib/bescheid.util.ts +++ b/alfa-client/libs/bescheid-shared/src/lib/bescheid.util.ts @@ -1,9 +1,9 @@ import { CommandOrder, CreateCommand } from '@alfa-client/command-shared'; export function buildCreateBescheidCommand(): CreateCommand { - return { order: CommandOrder.CREATE_BESCHEID, body: null }; + return { order: CommandOrder.CREATE_BESCHEID, body: null }; } export function isCreateBescheidCommand(order: CommandOrder): boolean { - return order == CommandOrder.CREATE_BESCHEID; -} \ No newline at end of file + return order == CommandOrder.CREATE_BESCHEID; +} diff --git a/alfa-client/libs/bescheid-shared/src/test-setup.ts b/alfa-client/libs/bescheid-shared/src/test-setup.ts index c46b7746401d5f7c0664f0c8b71978be45d76c40..392f52b2bd1b4fe2897b491615573c9c423951ae 100644 --- a/alfa-client/libs/bescheid-shared/src/test-setup.ts +++ b/alfa-client/libs/bescheid-shared/src/test-setup.ts @@ -2,17 +2,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/bescheid-shared/tsconfig.json b/alfa-client/libs/bescheid-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/bescheid-shared/tsconfig.json +++ b/alfa-client/libs/bescheid-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/bescheid-shared/tsconfig.lib.json b/alfa-client/libs/bescheid-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/bescheid-shared/tsconfig.lib.json +++ b/alfa-client/libs/bescheid-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/bescheid-shared/tsconfig.spec.json b/alfa-client/libs/bescheid-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/bescheid-shared/tsconfig.spec.json +++ b/alfa-client/libs/bescheid-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/bescheid/.eslintrc.json b/alfa-client/libs/bescheid/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/bescheid/.eslintrc.json +++ b/alfa-client/libs/bescheid/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/bescheid/jest.config.ts b/alfa-client/libs/bescheid/jest.config.ts index 9442161c20ba37437ba36561b5468122e54205ea..6253ad3e208ecc0405d43d62b17ca5e5821aa18c 100644 --- a/alfa-client/libs/bescheid/jest.config.ts +++ b/alfa-client/libs/bescheid/jest.config.ts @@ -1,22 +1,22 @@ export default { - displayName: 'bescheid', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/bescheid', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'bescheid', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/bescheid', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/bescheid/project.json b/alfa-client/libs/bescheid/project.json index 1c4c1beaa83855497d36b3344aaf2a4dde7d4368..c343af42f102c6be1b9093b1a9261152d2b142a4 100644 --- a/alfa-client/libs/bescheid/project.json +++ b/alfa-client/libs/bescheid/project.json @@ -1,29 +1,26 @@ { - "name": "bescheid", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/bescheid/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/bescheid"], - "options": { - "tsConfig": "libs/bescheid/tsconfig.spec.json", - "jestConfig": "libs/bescheid/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/bescheid/src/**/*.ts", - "libs/bescheid/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [] + "name": "bescheid", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/bescheid/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/bescheid"], + "options": { + "tsConfig": "libs/bescheid/tsconfig.spec.json", + "jestConfig": "libs/bescheid/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/bescheid/src/**/*.ts", "libs/bescheid/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [] } diff --git a/alfa-client/libs/bescheid/src/lib/bescheid.module.spec.ts b/alfa-client/libs/bescheid/src/lib/bescheid.module.spec.ts index a2ccd840a0696468cf99b8997502a0cd5c9235c3..1cec6915751170fa0149f2b3fb0d9568fd92edb0 100644 --- a/alfa-client/libs/bescheid/src/lib/bescheid.module.spec.ts +++ b/alfa-client/libs/bescheid/src/lib/bescheid.module.spec.ts @@ -2,13 +2,13 @@ import { TestBed } from '@angular/core/testing'; import { BescheidModule } from './bescheid.module'; describe('BescheidModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [BescheidModule] - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [BescheidModule], + }).compileComponents(); + }); - it('should create', () => { - expect(BescheidModule).toBeDefined(); - }); + it('should create', () => { + expect(BescheidModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/bescheid/src/lib/bescheid.module.ts b/alfa-client/libs/bescheid/src/lib/bescheid.module.ts index 7725aea40d9d642fff243ab8a017964bdeb83b50..b1c7c89dd010d60ca9f7d070bab63ae543747113 100644 --- a/alfa-client/libs/bescheid/src/lib/bescheid.module.ts +++ b/alfa-client/libs/bescheid/src/lib/bescheid.module.ts @@ -8,19 +8,8 @@ import { CreateBescheidButtonContainerComponent } from './create-bescheid-button import { CreateBescheidButtonComponent } from './create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component'; @NgModule({ - imports: [ - CommonModule, - BescheidSharedModule, - TechSharedModule, - UiModule, - CommandSharedModule - ], - declarations: [ - CreateBescheidButtonContainerComponent, - CreateBescheidButtonComponent, - ], - exports: [ - CreateBescheidButtonContainerComponent - ] + imports: [CommonModule, BescheidSharedModule, TechSharedModule, UiModule, CommandSharedModule], + declarations: [CreateBescheidButtonContainerComponent, CreateBescheidButtonComponent], + exports: [CreateBescheidButtonContainerComponent], }) -export class BescheidModule { } +export class BescheidModule {} diff --git a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.html b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.html index 29f46da70f6fcb92e023b779f0f30318f939969e..1cc547861a553e8955f7f4481a862c2d5daeb535 100644 --- a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.html +++ b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.html @@ -1,4 +1,6 @@ -<alfa-create-bescheid-button data-test-id="create-bescheid-button-component" - [createBescheidCommand]="createBescheidInCommand$ | async" - (createBescheid)="create()"> -</alfa-create-bescheid-button> \ No newline at end of file +<alfa-create-bescheid-button + data-test-id="create-bescheid-button-component" + [createBescheidCommand]="createBescheidInCommand$ | async" + (createBescheid)="create()" +> +</alfa-create-bescheid-button> diff --git a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.spec.ts b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.spec.ts index 5c48c16d624d672183632ab0207d14000f08c992..55dc7e67d6a90ba7555860c8ead94e494bc39316 100644 --- a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.spec.ts +++ b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.spec.ts @@ -9,52 +9,50 @@ import { CreateBescheidButtonContainerComponent } from './create-bescheid-button import { CreateBescheidButtonComponent } from './create-bescheid-button/create-bescheid-button.component'; describe('CreateBescheidButtonContainerComponent', () => { - let component: CreateBescheidButtonContainerComponent; - let fixture: ComponentFixture<CreateBescheidButtonContainerComponent>; - - const createBescheidComponent: string = getDataTestIdOf('create-bescheid-button-component'); - const service: Mock<BescheidService> = mock(BescheidService); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - CreateBescheidButtonContainerComponent, - MockComponent(CreateBescheidButtonComponent) - ], - providers:[ - { - provide: BescheidService, - useValue: service - } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(CreateBescheidButtonContainerComponent); - component = fixture.componentInstance; - component.vorgangWithEingang = vorgangWithEingang; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should get bescheid command', () => { - component.ngOnInit(); - - expect(service.getBescheidCommand).toHaveBeenCalled(); - }) - }) - - describe('create', () => { - - it('should call service', () => { - dispatchEventFromFixture(fixture, createBescheidComponent, 'createBescheid'); - - expect(service.createBescheid).toHaveBeenCalledWith(vorgangWithEingang); - }) - }) + let component: CreateBescheidButtonContainerComponent; + let fixture: ComponentFixture<CreateBescheidButtonContainerComponent>; + + const createBescheidComponent: string = getDataTestIdOf('create-bescheid-button-component'); + const service: Mock<BescheidService> = mock(BescheidService); + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + CreateBescheidButtonContainerComponent, + MockComponent(CreateBescheidButtonComponent), + ], + providers: [ + { + provide: BescheidService, + useValue: service, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(CreateBescheidButtonContainerComponent); + component = fixture.componentInstance; + component.vorgangWithEingang = vorgangWithEingang; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should get bescheid command', () => { + component.ngOnInit(); + + expect(service.getBescheidCommand).toHaveBeenCalled(); + }); + }); + + describe('create', () => { + it('should call service', () => { + dispatchEventFromFixture(fixture, createBescheidComponent, 'createBescheid'); + + expect(service.createBescheid).toHaveBeenCalledWith(vorgangWithEingang); + }); + }); }); diff --git a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.ts b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.ts index 9f1f8c4bfd94199090823af480843874a3a4b2e4..d559b59fdae22f29bce22feaf8105a678c7ae4ee 100644 --- a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.ts +++ b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button-container.component.ts @@ -6,23 +6,24 @@ import { BescheidService } from 'libs/bescheid-shared/src/lib/bescheid.service'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-create-bescheid-button-container', - templateUrl: './create-bescheid-button-container.component.html', - styleUrls: ['./create-bescheid-button-container.component.scss'], + selector: 'alfa-create-bescheid-button-container', + templateUrl: './create-bescheid-button-container.component.html', + styleUrls: ['./create-bescheid-button-container.component.scss'], }) export class CreateBescheidButtonContainerComponent implements OnInit { + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() vorgangWithEingang: VorgangWithEingangResource; + public createBescheidInCommand$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - public createBescheidInCommand$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + constructor(private bescheidService: BescheidService) {} - constructor(private bescheidService: BescheidService){ } + ngOnInit(): void { + this.createBescheidInCommand$ = this.bescheidService.getBescheidCommand(); + } - ngOnInit(): void { - this.createBescheidInCommand$ = this.bescheidService.getBescheidCommand(); - } - - public create(): void { - this.bescheidService.createBescheid(this.vorgangWithEingang); - } -} \ No newline at end of file + public create(): void { + this.bescheidService.createBescheid(this.vorgangWithEingang); + } +} diff --git a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.html b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.html index cd4c0f6240ce2b57a89cf296e61803623a5de0ac..ac1efb73c28ad0ed875c79f084ebf9a5ee55dec6 100644 --- a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.html +++ b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.html @@ -1,6 +1,8 @@ -<ozgcloud-icon-button-with-spinner data-test-id="create-bescheid-icon-button" - icon="description" - toolTip="Bescheid erstellen" - [stateResource]="createBescheidCommand" - (clickEmitter)="createBescheid.emit()"> -</ozgcloud-icon-button-with-spinner> \ No newline at end of file +<ozgcloud-icon-button-with-spinner + data-test-id="create-bescheid-icon-button" + icon="description" + toolTip="Bescheid erstellen" + [stateResource]="createBescheidCommand" + (clickEmitter)="createBescheid.emit()" +> +</ozgcloud-icon-button-with-spinner> diff --git a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.spec.ts b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.spec.ts index 7e5650caf243d75eb5f90557c7bb4f096b5f5768..d15b7638e4686c64dd015cae79be7e3cee5915f4 100644 --- a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.spec.ts +++ b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.spec.ts @@ -6,36 +6,32 @@ import { MockComponent } from 'ng-mocks'; import { CreateBescheidButtonComponent } from './create-bescheid-button.component'; describe('CreateBescheidButtonComponent', () => { - let component: CreateBescheidButtonComponent; - let fixture: ComponentFixture<CreateBescheidButtonComponent>; + let component: CreateBescheidButtonComponent; + let fixture: ComponentFixture<CreateBescheidButtonComponent>; - const createBescheidButton: string = getDataTestIdOf('create-bescheid-icon-button'); + const createBescheidButton: string = getDataTestIdOf('create-bescheid-icon-button'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - CreateBescheidButtonComponent, - MockComponent(IconButtonWithSpinnerComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [CreateBescheidButtonComponent, MockComponent(IconButtonWithSpinnerComponent)], + }).compileComponents(); - fixture = TestBed.createComponent(CreateBescheidButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(CreateBescheidButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('on button click', () => { + describe('on button click', () => { + it('should emit createBescheid', () => { + jest.spyOn(component.createBescheid, 'emit'); - it('should emit createBescheid', () => { - jest.spyOn(component.createBescheid, 'emit'); + dispatchEventFromFixture(fixture, createBescheidButton, 'clickEmitter'); - dispatchEventFromFixture(fixture, createBescheidButton, 'clickEmitter'); - - expect(component.createBescheid.emit).toHaveBeenCalled(); - }) - }) + expect(component.createBescheid.emit).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.ts b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.ts index 5f723e346f7e825087fa86471efeeedbddd480e0..d01c5ecd049877b9fd5a63e4e2ee4cde9cd034b0 100644 --- a/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.ts +++ b/alfa-client/libs/bescheid/src/lib/create-bescheid-button-container/create-bescheid-button/create-bescheid-button.component.ts @@ -3,13 +3,13 @@ import { CommandResource } from '@alfa-client/command-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-create-bescheid-button', - templateUrl: './create-bescheid-button.component.html', - styleUrls: ['./create-bescheid-button.component.scss'], + selector: 'alfa-create-bescheid-button', + templateUrl: './create-bescheid-button.component.html', + styleUrls: ['./create-bescheid-button.component.scss'], }) export class CreateBescheidButtonComponent { + @Input() createBescheidCommand: StateResource<CommandResource> = + createEmptyStateResource<CommandResource>(); - @Input() createBescheidCommand: StateResource<CommandResource> = createEmptyStateResource<CommandResource>(); - - @Output() createBescheid: EventEmitter<void> = new EventEmitter(); + @Output() createBescheid: EventEmitter<void> = new EventEmitter(); } diff --git a/alfa-client/libs/bescheid/src/test-setup.ts b/alfa-client/libs/bescheid/src/test-setup.ts index a34d602adcc3acf9aca31a86021eff1f069e918d..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/bescheid/src/test-setup.ts +++ b/alfa-client/libs/bescheid/src/test-setup.ts @@ -25,15 +25,14 @@ import '@testing-library/jest-dom'; import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); \ No newline at end of file +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/bescheid/tsconfig.json b/alfa-client/libs/bescheid/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/bescheid/tsconfig.json +++ b/alfa-client/libs/bescheid/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/bescheid/tsconfig.lib.json b/alfa-client/libs/bescheid/tsconfig.lib.json index 6757e10fe15ded449292f3072040ec1101e5ecd4..dcc35a71ee8a26bc9394b9cf96b02996be26ec16 100644 --- a/alfa-client/libs/bescheid/tsconfig.lib.json +++ b/alfa-client/libs/bescheid/tsconfig.lib.json @@ -1,17 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [] - }, - "exclude": [ - "src/test-setup.ts", - "src/**/*.spec.ts", - "jest.config.ts", - "src/**/*.test.ts" - ], - "include": ["src/**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["src/test-setup.ts", "src/**/*.spec.ts", "jest.config.ts", "src/**/*.test.ts"], + "include": ["src/**/*.ts"] } diff --git a/alfa-client/libs/bescheid/tsconfig.spec.json b/alfa-client/libs/bescheid/tsconfig.spec.json index 4950ae2f7859509b300543bff1c1e5ce4b1e2d5c..c3cb17f784fa2f7b9a4b0e7c9b03663500f4ee3d 100644 --- a/alfa-client/libs/bescheid/tsconfig.spec.json +++ b/alfa-client/libs/bescheid/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/binary-file-shared/.eslintrc.json b/alfa-client/libs/binary-file-shared/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/binary-file-shared/.eslintrc.json +++ b/alfa-client/libs/binary-file-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/binary-file-shared/jest.config.ts b/alfa-client/libs/binary-file-shared/jest.config.ts index 0b87c11107b24a700f9f43a98d33e04dfd29b3df..b9ecba9c94a7232349117d10cf61ed251f8b3093 100644 --- a/alfa-client/libs/binary-file-shared/jest.config.ts +++ b/alfa-client/libs/binary-file-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'binary-file-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/binary-file-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'binary-file-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/binary-file-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/binary-file-shared/project.json b/alfa-client/libs/binary-file-shared/project.json index 334edb95228fc9360258023355adca6fc45ba448..cbe0c5c2b859b9e9f45dca3d40a1cc26ff2c12ee 100644 --- a/alfa-client/libs/binary-file-shared/project.json +++ b/alfa-client/libs/binary-file-shared/project.json @@ -1,29 +1,29 @@ { - "name": "binary-file-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/binary-file-shared/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/binary-file-shared"], - "options": { - "tsConfig": "libs/binary-file-shared/tsconfig.spec.json", - "jestConfig": "libs/binary-file-shared/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/binary-file-shared/src/**/*.ts", - "libs/binary-file-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [] + "name": "binary-file-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/binary-file-shared/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/binary-file-shared"], + "options": { + "tsConfig": "libs/binary-file-shared/tsconfig.spec.json", + "jestConfig": "libs/binary-file-shared/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/binary-file-shared/src/**/*.ts", + "libs/binary-file-shared/src/**/*.html" + ] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [] } diff --git a/alfa-client/libs/binary-file-shared/src/index.ts b/alfa-client/libs/binary-file-shared/src/index.ts index 858a52ed12c250ffe7312616426d99e668b15caf..59c3d550204e416f3d666a7993fe504f7d1ec1ba 100644 --- a/alfa-client/libs/binary-file-shared/src/index.ts +++ b/alfa-client/libs/binary-file-shared/src/index.ts @@ -28,4 +28,3 @@ export * from './lib/binary-file.linkrel'; export * from './lib/binary-file.model'; export * from './lib/binary-file.service'; export * from './lib/binary-file.util'; - diff --git a/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.actions.ts b/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.actions.ts index 24a817950470ca41a7b726d8ae47c46b2faa4bee..2c9c5ea0a0d6eb67717fa9e059d157ac9dd8cdff 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.actions.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.actions.ts @@ -28,29 +28,38 @@ import { Resource, ResourceUri } from '@ngxp/rest'; import { BinaryFileListResource } from '../binary-file.model'; export interface DownloadBinaryFileAsPdfAction { - uri: ResourceUri - fileName: string, - successAction: () => TypedAction<string>, - failureAction: (apiError: ApiError) => ApiErrorAction & TypedAction<string> + uri: ResourceUri; + fileName: string; + successAction: () => TypedAction<string>; + failureAction: (apiError: ApiError) => ApiErrorAction & TypedAction<string>; } -export const downloadPdf: TypedActionCreatorWithProps<DownloadBinaryFileAsPdfAction> = createAction('[BinaryFile] Download pdf file', props<DownloadBinaryFileAsPdfAction>()); +export const downloadPdf: TypedActionCreatorWithProps<DownloadBinaryFileAsPdfAction> = createAction( + '[BinaryFile] Download pdf file', + props<DownloadBinaryFileAsPdfAction>(), +); export interface SaveFileProps { - fileData: Blob - fileName: string + fileData: Blob; + fileName: string; } -export const saveFile: TypedActionCreatorWithProps<SaveFileProps> = createAction('[BinaryFile/API] Save file', props<SaveFileProps>()); +export const saveFile: TypedActionCreatorWithProps<SaveFileProps> = createAction( + '[BinaryFile/API] Save file', + props<SaveFileProps>(), +); export interface LoadBinaryFileListSuccessProps { - binaryFileList: BinaryFileListResource + binaryFileList: BinaryFileListResource; } export interface LoadBinaryFileListProps { - resource: Resource, - linkRel: string, - successAction: (binaryFileList: BinaryFileListResource) => LoadBinaryFileListSuccessProps & TypedAction<string>, - failureAction: (apiError: ApiError) => ApiErrorAction & TypedAction<string> + resource: Resource; + linkRel: string; + successAction: ( + binaryFileList: BinaryFileListResource, + ) => LoadBinaryFileListSuccessProps & TypedAction<string>; + failureAction: (apiError: ApiError) => ApiErrorAction & TypedAction<string>; } -export const loadBinaryFileList: TypedActionCreatorWithProps<LoadBinaryFileListProps> = createAction('[BinaryFile] Load BinaryFile List', props<LoadBinaryFileListProps>()); \ No newline at end of file +export const loadBinaryFileList: TypedActionCreatorWithProps<LoadBinaryFileListProps> = + createAction('[BinaryFile] Load BinaryFile List', props<LoadBinaryFileListProps>()); diff --git a/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.spec.ts b/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.spec.ts index a23acd441f945b77f34245e29b15ffdd7281e4ef..e2116027b706b34555fecda3fb6f409db18d605f 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.spec.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.spec.ts @@ -23,7 +23,12 @@ */ import { TestBed } from '@angular/core/testing'; import faker from '@faker-js/faker'; -import { ApiError, ApiErrorAction, TypedActionCreator, TypedActionCreatorWithProps } from '@alfa-client/tech-shared'; +import { + ApiError, + ApiErrorAction, + TypedActionCreator, + TypedActionCreatorWithProps, +} from '@alfa-client/tech-shared'; import { Mock, mock } from '@alfa-client/test-utils'; import { provideMockActions } from '@ngrx/effects/testing'; import { Action, createAction, props } from '@ngrx/store'; @@ -33,139 +38,164 @@ import { Resource, ResourceUri } from '@ngxp/rest'; import { hot } from 'jasmine-marbles'; import { cold } from 'jest-marbles'; import { ColdObservable } from 'jest-marbles/typings/src/rxjs/cold-observable'; -import { createBinaryFileListResource, createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; +import { + createBinaryFileListResource, + createBinaryFileResource, +} from 'libs/binary-file-shared/test/binary-file'; import { createApiError } from 'libs/tech-shared/test/error'; import { Observable, of } from 'rxjs'; import { BinaryFileListResource } from '../binary-file.model'; import { BinaryFileRepository } from '../binary-file.repository'; -import { DownloadBinaryFileAsPdfAction, LoadBinaryFileListProps, LoadBinaryFileListSuccessProps } from './binary-file.actions'; +import { + DownloadBinaryFileAsPdfAction, + LoadBinaryFileListProps, + LoadBinaryFileListSuccessProps, +} from './binary-file.actions'; import { BinaryFileEffects } from './binary-file.effects'; import * as BinaryFileActions from './binary-file.actions'; describe('BinaryFileEffects', () => { - let actions: Observable<Action>; - let effects: BinaryFileEffects; - - const repository: Mock<BinaryFileRepository> = mock(BinaryFileRepository); - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - BinaryFileEffects, - provideMockActions(() => actions), - provideMockStore(), - { - provide: BinaryFileRepository, - useValue: repository - }, - ], - }); - - effects = TestBed.inject(BinaryFileEffects); - }); - - describe('downloadPdf', () => { - - const uri: ResourceUri = faker.internet.url(); - const fileName: string = faker.random.alphaNumeric(); - const fileData: Blob = new Blob(); - - const downloadAsPdfSuccess: TypedActionCreator = createAction('[Test Action] Download Success'); - const downloadAsPdfFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Test Action] Download Failure', props<ApiErrorAction>()); - - const downloadPdfAction: DownloadBinaryFileAsPdfAction & TypedAction<string> = BinaryFileActions.downloadPdf({ successAction: downloadAsPdfSuccess, failureAction: (apiError) => downloadAsPdfFailure({ apiError }), fileName, uri }); - - it('should call repository', () => { - actions = hot('-a', { a: downloadPdfAction }); - - effects.downloadPdf$.subscribe(() => { - expect(repository.downloadPdf).toHaveBeenCalledWith(uri); - }); - }); - - it('should dispatch success action on no error', () => { - repository.downloadPdf.mockReturnValue(of(fileData)); - - actions = hot('-a', { a: downloadPdfAction }); - - const expected: ColdObservable = cold('-(bc)', { - b: BinaryFileActions.saveFile({ fileName, fileData }), - c: downloadAsPdfSuccess() - }); - expect(effects.downloadPdf$).toBeObservable(expected); - }); - - it.skip('should dispatch failure actions on error', () => { - const apiError: ApiError = createApiError() - const error = { error: { error: apiError } }; - const errorResponse = cold('-#', {}, error); - repository.downloadPdf = jest.fn(() => errorResponse); - - actions = hot('-a', { a: downloadPdfAction }); - - const expected: ColdObservable = cold('--b', { b: downloadAsPdfFailure({ apiError }) }); - expect(effects.downloadPdf$).toBeObservable(expected); - }) - }); - - describe('saveAsPdf', () => { - - const fileName: string = faker.random.alphaNumeric(); - const fileData: Blob = new Blob(); - - it('should save file', () => { - effects.save = jest.fn(); - - actions = hot('a', { a: BinaryFileActions.saveFile({ fileData, fileName }) }); - - effects.saveFile$.subscribe(() => { - expect(effects.save).toHaveBeenCalledWith(fileData, fileName); - }) - }) - }) - - describe('loadBinaryFileList', () => { - - const resource: Resource = createBinaryFileResource(); - const linkRel: string = faker.internet.url(); - - const loadSuccess: TypedActionCreatorWithProps<LoadBinaryFileListSuccessProps> = createAction('[Test Action] Download Success', props<LoadBinaryFileListSuccessProps>()); - const loadFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Test Action] Download Failure', props<ApiErrorAction>()); - - const loadBinaryFileListAction: LoadBinaryFileListProps & TypedAction<string> = BinaryFileActions.loadBinaryFileList({ resource, linkRel, successAction: (binaryFileList: BinaryFileListResource) => loadSuccess({ binaryFileList }), failureAction: (apiError: ApiError) => loadFailure({ apiError }) }); - - const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); - - beforeEach(() => { - repository.getFiles.mockReturnValue(of(binaryFileList)); - }) - - it('should call repository', () => { - actions = of(loadBinaryFileListAction); - - effects.loadBinaryFileList$.subscribe(); - - expect(repository.getFiles).toHaveBeenCalledWith(resource, linkRel); - }); - - it('should dispatch success action on no error', () => { - actions = hot('-a', { a: loadBinaryFileListAction }); - - const expected: ColdObservable = cold('-b', { b: loadSuccess({ binaryFileList })}); - expect(effects.loadBinaryFileList$).toBeObservable(expected); - }); - - it.skip('should dispatch failure actions on error', () => { - const apiError: ApiError = createApiError() - const error = { error: { error: apiError } }; - const errorResponse = cold('-#', {}, error); - repository.getFiles = jest.fn(() => errorResponse); - - const expected: ColdObservable = cold('--b', { b: loadFailure({ apiError }) }); - actions = hot('-a', { a: loadBinaryFileListAction }); - - expect(effects.loadBinaryFileList$).toBeObservable(expected); - }) - }); + let actions: Observable<Action>; + let effects: BinaryFileEffects; + + const repository: Mock<BinaryFileRepository> = mock(BinaryFileRepository); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + BinaryFileEffects, + provideMockActions(() => actions), + provideMockStore(), + { + provide: BinaryFileRepository, + useValue: repository, + }, + ], + }); + + effects = TestBed.inject(BinaryFileEffects); + }); + + describe('downloadPdf', () => { + const uri: ResourceUri = faker.internet.url(); + const fileName: string = faker.random.alphaNumeric(); + const fileData: Blob = new Blob(); + + const downloadAsPdfSuccess: TypedActionCreator = createAction('[Test Action] Download Success'); + const downloadAsPdfFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[Test Action] Download Failure', + props<ApiErrorAction>(), + ); + + const downloadPdfAction: DownloadBinaryFileAsPdfAction & TypedAction<string> = + BinaryFileActions.downloadPdf({ + successAction: downloadAsPdfSuccess, + failureAction: (apiError) => downloadAsPdfFailure({ apiError }), + fileName, + uri, + }); + + it('should call repository', () => { + actions = hot('-a', { a: downloadPdfAction }); + + effects.downloadPdf$.subscribe(() => { + expect(repository.downloadPdf).toHaveBeenCalledWith(uri); + }); + }); + + it('should dispatch success action on no error', () => { + repository.downloadPdf.mockReturnValue(of(fileData)); + + actions = hot('-a', { a: downloadPdfAction }); + + const expected: ColdObservable = cold('-(bc)', { + b: BinaryFileActions.saveFile({ fileName, fileData }), + c: downloadAsPdfSuccess(), + }); + expect(effects.downloadPdf$).toBeObservable(expected); + }); + + it.skip('should dispatch failure actions on error', () => { + const apiError: ApiError = createApiError(); + const error = { error: { error: apiError } }; + const errorResponse = cold('-#', {}, error); + repository.downloadPdf = jest.fn(() => errorResponse); + + actions = hot('-a', { a: downloadPdfAction }); + + const expected: ColdObservable = cold('--b', { b: downloadAsPdfFailure({ apiError }) }); + expect(effects.downloadPdf$).toBeObservable(expected); + }); + }); + + describe('saveAsPdf', () => { + const fileName: string = faker.random.alphaNumeric(); + const fileData: Blob = new Blob(); + + it('should save file', () => { + effects.save = jest.fn(); + + actions = hot('a', { a: BinaryFileActions.saveFile({ fileData, fileName }) }); + + effects.saveFile$.subscribe(() => { + expect(effects.save).toHaveBeenCalledWith(fileData, fileName); + }); + }); + }); + + describe('loadBinaryFileList', () => { + const resource: Resource = createBinaryFileResource(); + const linkRel: string = faker.internet.url(); + + const loadSuccess: TypedActionCreatorWithProps<LoadBinaryFileListSuccessProps> = createAction( + '[Test Action] Download Success', + props<LoadBinaryFileListSuccessProps>(), + ); + const loadFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[Test Action] Download Failure', + props<ApiErrorAction>(), + ); + + const loadBinaryFileListAction: LoadBinaryFileListProps & TypedAction<string> = + BinaryFileActions.loadBinaryFileList({ + resource, + linkRel, + successAction: (binaryFileList: BinaryFileListResource) => loadSuccess({ binaryFileList }), + failureAction: (apiError: ApiError) => loadFailure({ apiError }), + }); + + const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); + + beforeEach(() => { + repository.getFiles.mockReturnValue(of(binaryFileList)); + }); + + it('should call repository', () => { + actions = of(loadBinaryFileListAction); + + effects.loadBinaryFileList$.subscribe(); + + expect(repository.getFiles).toHaveBeenCalledWith(resource, linkRel); + }); + + it('should dispatch success action on no error', () => { + actions = hot('-a', { a: loadBinaryFileListAction }); + + const expected: ColdObservable = cold('-b', { b: loadSuccess({ binaryFileList }) }); + expect(effects.loadBinaryFileList$).toBeObservable(expected); + }); + + it.skip('should dispatch failure actions on error', () => { + const apiError: ApiError = createApiError(); + const error = { error: { error: apiError } }; + const errorResponse = cold('-#', {}, error); + repository.getFiles = jest.fn(() => errorResponse); + + const expected: ColdObservable = cold('--b', { b: loadFailure({ apiError }) }); + actions = hot('-a', { a: loadBinaryFileListAction }); + + expect(effects.loadBinaryFileList$).toBeObservable(expected); + }); + }); }); diff --git a/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts b/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts index c9cbfd45b1bcd4eea38f757c2d6d9048cad53a5c..9a2f67de4758c0196504471e93a8af43a833ee59 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.effects.ts @@ -27,39 +27,59 @@ import { of } from 'rxjs'; import { catchError, map, mergeMap, switchMap, tap } from 'rxjs/operators'; import { BinaryFileListResource } from '../binary-file.model'; import { BinaryFileRepository } from '../binary-file.repository'; -import { DownloadBinaryFileAsPdfAction, LoadBinaryFileListProps, SaveFileProps } from './binary-file.actions'; +import { + DownloadBinaryFileAsPdfAction, + LoadBinaryFileListProps, + SaveFileProps, +} from './binary-file.actions'; import * as saveAs from 'file-saver'; import * as BinaryFileActions from './binary-file.actions'; @Injectable() export class BinaryFileEffects { + constructor( + private readonly actions$: Actions, + private readonly repository: BinaryFileRepository, + ) {} - constructor(private readonly actions$: Actions, private readonly repository: BinaryFileRepository) { } + downloadPdf$ = createEffect(() => + this.actions$.pipe( + ofType(BinaryFileActions.downloadPdf), + switchMap((action: DownloadBinaryFileAsPdfAction) => + this.repository.downloadPdf(action.uri).pipe( + mergeMap((fileData: Blob) => [ + BinaryFileActions.saveFile({ fileData, fileName: action.fileName }), + action.successAction(), + ]), + catchError((error) => of(action.failureAction(error.error))), + ), + ), + ), + ); - downloadPdf$ = createEffect(() => this.actions$.pipe( - ofType(BinaryFileActions.downloadPdf), - switchMap((action: DownloadBinaryFileAsPdfAction) => this.repository.downloadPdf(action.uri).pipe( - mergeMap((fileData: Blob) => [BinaryFileActions.saveFile({ fileData, fileName: action.fileName }), action.successAction()]), - catchError(error => of(action.failureAction(error.error))) - )) - )); + saveFile$ = createEffect( + () => + this.actions$.pipe( + ofType(BinaryFileActions.saveFile), + tap((props: SaveFileProps) => this.save(props.fileData, props.fileName)), + ), + { dispatch: false }, + ); - saveFile$ = createEffect(() => this.actions$.pipe( - ofType(BinaryFileActions.saveFile), - tap((props: SaveFileProps) => this.save(props.fileData, props.fileName)) - ), { dispatch: false }); + save(fileData: Blob, name: string): void { + saveAs(fileData, name); + } - - save(fileData: Blob, name: string): void { - saveAs(fileData, name); - } - - loadBinaryFileList$ = createEffect(() => this.actions$.pipe( - ofType(BinaryFileActions.loadBinaryFileList), - switchMap((props: LoadBinaryFileListProps) => this.repository.getFiles(props.resource, props.linkRel).pipe( - map((binaryFileList: BinaryFileListResource) => props.successAction(binaryFileList)), - catchError(error => of(props.failureAction(error.error))) - )) - )); -} \ No newline at end of file + loadBinaryFileList$ = createEffect(() => + this.actions$.pipe( + ofType(BinaryFileActions.loadBinaryFileList), + switchMap((props: LoadBinaryFileListProps) => + this.repository.getFiles(props.resource, props.linkRel).pipe( + map((binaryFileList: BinaryFileListResource) => props.successAction(binaryFileList)), + catchError((error) => of(props.failureAction(error.error))), + ), + ), + ), + ); +} diff --git a/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.reducer.ts b/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.reducer.ts index b1b7dc30b710107722f68a54f9aa4913bea14515..a74d9310b3f22a667d49fbcf1628c9205680c5fb 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.reducer.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/+state/binary-file.reducer.ts @@ -25,10 +25,10 @@ import { Action, createReducer } from '@ngrx/store'; export const BINARY_FILE_FEATURE_KEY = 'BinaryFileState'; -export interface BinaryFileState { } +export interface BinaryFileState {} export interface BinaryFilePartialState { - readonly [BINARY_FILE_FEATURE_KEY]: BinaryFileState; + readonly [BINARY_FILE_FEATURE_KEY]: BinaryFileState; } export const initialBinaryFileState: BinaryFileState = {}; @@ -36,5 +36,5 @@ export const initialBinaryFileState: BinaryFileState = {}; const reducer = createReducer(initialBinaryFileState); export function binaryFileReducer(state: BinaryFileState, action: Action) { - return reducer(state, action); -} \ No newline at end of file + return reducer(state, action); +} diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file-shared.module.spec.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file-shared.module.spec.ts index 3efe1a1f5b5601cd3eee8849cb046dbb861c2eab..c00e6e7b9b553e4aa0ee683893c757de62741e11 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/binary-file-shared.module.spec.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file-shared.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { BinaryFileSharedModule } from './binary-file-shared.module'; describe('BinaryFileSharedModule', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [BinaryFileSharedModule] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [BinaryFileSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(BinaryFileSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(BinaryFileSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file-shared.module.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file-shared.module.ts index 90d3886dfcd144eef4b24b127c7bf281569fb8ef..a0abfb23e3be1f7344c6bbe3e3bee17841938db5 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/binary-file-shared.module.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file-shared.module.ts @@ -29,13 +29,13 @@ import { BinaryFileEffects } from './+state/binary-file.effects'; import * as fromBinaryFile from './+state/binary-file.reducer'; @NgModule({ - imports: [ - CommonModule, - StoreModule.forFeature( - fromBinaryFile.BINARY_FILE_FEATURE_KEY, - fromBinaryFile.binaryFileReducer - ), - EffectsModule.forFeature([BinaryFileEffects]), - ] + imports: [ + CommonModule, + StoreModule.forFeature( + fromBinaryFile.BINARY_FILE_FEATURE_KEY, + fromBinaryFile.binaryFileReducer, + ), + EffectsModule.forFeature([BinaryFileEffects]), + ], }) -export class BinaryFileSharedModule { } +export class BinaryFileSharedModule {} diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.linkrel.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.linkrel.ts index 0bf1ddc021bfaa9a04709f092dfde45cd05cee77..2bc6bbf62e9b6dc3bda604024bf6f485917acf09 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.linkrel.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.linkrel.ts @@ -22,9 +22,9 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum BinaryFileLinkRel { - DOWNLOAD = 'download' + DOWNLOAD = 'download', } export enum BinaryFileListLinkRel { - FILE_LIST = 'ozgFileList'//TODO renaming, in sync with backend + FILE_LIST = 'ozgFileList', //TODO renaming, in sync with backend } diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.model.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.model.ts index 9c0fac8f3c03859ef1046c38e9cfc5d431fe651c..e204b8be3b7232aef82b564db4c32be3aaec85a3 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.model.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.model.ts @@ -25,11 +25,11 @@ import { ListResource } from '@alfa-client/tech-shared'; import { Resource } from '@ngxp/rest'; export interface BinaryFile { - name: string, - size: number, - contentType: string + name: string; + size: number; + contentType: string; } -export interface BinaryFileResource extends BinaryFile, Resource { } +export interface BinaryFileResource extends BinaryFile, Resource {} -export interface BinaryFileListResource extends ListResource { } +export interface BinaryFileListResource extends ListResource {} diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts index 73044ce45ee2e0ffd516a1241490fb369d7e2ab8..9ad810e73de5bb0a2015ad9b012adc2700f705d1 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.spec.ts @@ -23,7 +23,13 @@ */ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { faker } from '@faker-js/faker'; -import { ContentType, GetRequestOptions, HttpErrorHandler, ListResource, TechSharedModule } from '@alfa-client/tech-shared'; +import { + ContentType, + GetRequestOptions, + HttpErrorHandler, + ListResource, + TechSharedModule, +} from '@alfa-client/tech-shared'; import { mock, mockClass, useFromMock } from '@alfa-client/test-utils'; import { Resource, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; @@ -36,184 +42,186 @@ import { BinaryFileResource } from './binary-file.model'; import { BinaryFileRepository } from './binary-file.repository'; describe('BinaryFileRepository', () => { - let repository: BinaryFileRepository; + let repository: BinaryFileRepository; - const httpClient = mock(HttpClient); - const resourceFactory = mock(ResourceFactory); - const resourceWrapper = { get: jest.fn() }; + const httpClient = mock(HttpClient); + const resourceFactory = mock(ResourceFactory); + const resourceWrapper = { get: jest.fn() }; - beforeEach(() => { - mockInterceptor(); + beforeEach(() => { + mockInterceptor(); - repository = new BinaryFileRepository(useFromMock(httpClient), useFromMock(resourceFactory)); + repository = new BinaryFileRepository(useFromMock(httpClient), useFromMock(resourceFactory)); - resourceFactory.from.mockReturnValue(resourceWrapper); - resourceFactory.fromId.mockReturnValue(resourceWrapper); - }) + resourceFactory.from.mockReturnValue(resourceWrapper); + resourceFactory.fromId.mockReturnValue(resourceWrapper); + }); - function mockInterceptor(): void { - mockClass(TechSharedModule).injector = <any>{ get: () => useFromMock(mock(HttpErrorHandler)) }; - } + function mockInterceptor(): void { + mockClass(TechSharedModule).injector = <any>{ get: () => useFromMock(mock(HttpErrorHandler)) }; + } - it('should be created', () => { - expect(repository).toBeTruthy(); - }) + it('should be created', () => { + expect(repository).toBeTruthy(); + }); - describe('uploadFile', () => { + describe('uploadFile', () => { + const dummyLinkRel: string = DummyLinkRel.DUMMY; + const dummyResource: Resource = createDummyResource([dummyLinkRel]); + const blob: Blob = new Blob(['test text'], { type: 'text/plain' }); - const dummyLinkRel: string = DummyLinkRel.DUMMY; - const dummyResource: Resource = createDummyResource([dummyLinkRel]); - const blob: Blob = new Blob(['test text'], { type: 'text/plain' }); + beforeEach(() => { + httpClient.post.mockReturnValue(of({})); + }); - beforeEach(() => { - httpClient.post.mockReturnValue(of({})); - }) + it('should call POST on httpClient with uri and data', () => { + const formData: FormData = new FormData(); + formData.append('file', blob, 'filename'); - it('should call POST on httpClient with uri and data', () => { - const formData: FormData = new FormData(); - formData.append('file', blob, 'filename'); + repository.uploadFile(dummyResource, dummyLinkRel, <File>blob); - repository.uploadFile(dummyResource, dummyLinkRel, <File>blob); + expect(httpClient.post).toHaveBeenCalledWith(getUrl(dummyResource, dummyLinkRel), formData, { + observe: 'response', + }); + }); - expect(httpClient.post).toHaveBeenCalledWith(getUrl(dummyResource, dummyLinkRel), formData, { observe: 'response' }); - }) + it('and return result', () => { + let result = repository.uploadFile(dummyResource, dummyLinkRel, <File>blob); - it('and return result', () => { - let result = repository.uploadFile(dummyResource, dummyLinkRel, <File>blob); + expect(result).not.toBeNull(); + }); + }); - expect(result).not.toBeNull(); - }) - }) + describe('download', () => { + const blob = {}; + const binaryFileResource: BinaryFileResource = createBinaryFileResource([ + BinaryFileLinkRel.DOWNLOAD, + ]); - describe('download', () => { + beforeEach(() => { + httpClient.get.mockReturnValue(hot('a', { a: blob })); + }); - const blob = {}; - const binaryFileResource: BinaryFileResource = createBinaryFileResource([BinaryFileLinkRel.DOWNLOAD]); + it('should call httpClient', () => { + const requestOptions = {}; + repository.buildRequestOptions = jest.fn(); + (<any>repository.buildRequestOptions).mockReturnValue(requestOptions); - beforeEach(() => { - httpClient.get.mockReturnValue(hot('a', { a: blob })); - }) + repository.download(binaryFileResource); - it('should call httpClient', () => { - const requestOptions = {}; - repository.buildRequestOptions = jest.fn(); - (<any>repository.buildRequestOptions).mockReturnValue(requestOptions); + expect(httpClient.get).toHaveBeenCalledWith( + getUrl(binaryFileResource, BinaryFileLinkRel.DOWNLOAD), + requestOptions, + ); + }); - repository.download(binaryFileResource); + it('should return value', () => { + const result = repository.download(binaryFileResource); - expect(httpClient.get).toHaveBeenCalledWith(getUrl(binaryFileResource, BinaryFileLinkRel.DOWNLOAD), requestOptions); - }) + expect(result).toBeObservable(cold('b', { b: blob })); + }); - it('should return value', () => { - const result = repository.download(binaryFileResource); + describe('buildRequestOptions', () => { + it('should return httpHeaders', () => { + const result: GetRequestOptions = repository.buildRequestOptions(); - expect(result).toBeObservable(cold('b', { b: blob })); - }) + expect(result.responseType).toEqual('blob'); + }); - describe('buildRequestOptions', () => { + it('should return responseType', () => { + const result: GetRequestOptions = repository.buildRequestOptions(); - it('should return httpHeaders', () => { - const result: GetRequestOptions = repository.buildRequestOptions(); + expect(result.headers).toEqual(getExpectedRequestOptions()); + }); + }); - expect(result.responseType).toEqual('blob'); - }) + function getExpectedRequestOptions(): HttpHeaders { + let headers = new HttpHeaders(); + headers = headers.set('Accept', [ContentType.APPLICATION_ALL, ContentType.IMAGES_ALL]); + return headers; + } + }); - it('should return responseType', () => { - const result: GetRequestOptions = repository.buildRequestOptions(); + describe('downloadPdf', () => { + const blob = {}; + const uri: ResourceUri = faker.internet.url(); - expect(result.headers).toEqual(getExpectedRequestOptions()); - }) - }) + beforeEach(() => { + httpClient.get.mockReturnValue(hot('a', { a: blob })); + }); - function getExpectedRequestOptions(): HttpHeaders { - let headers = new HttpHeaders(); - headers = headers.set('Accept', [ContentType.APPLICATION_ALL, ContentType.IMAGES_ALL]); - return headers; - } - }) + it('should call httpClient', () => { + const requestOptions = {}; + repository.buildPdfRequestOptions = jest.fn(); + (<any>repository.buildPdfRequestOptions).mockReturnValue(requestOptions); - describe('downloadPdf', () => { + repository.downloadPdf(uri); - const blob = {}; - const uri: ResourceUri = faker.internet.url(); + expect(httpClient.get).toHaveBeenCalledWith(uri, requestOptions); + }); - beforeEach(() => { - httpClient.get.mockReturnValue(hot('a', { a: blob })); - }) + it('should return value', () => { + const result = repository.downloadPdf(uri); - it('should call httpClient', () => { - const requestOptions = {}; - repository.buildPdfRequestOptions = jest.fn(); - (<any>repository.buildPdfRequestOptions).mockReturnValue(requestOptions); + expect(result).toBeObservable(cold('b', { b: blob })); + }); - repository.downloadPdf(uri); + describe('buildPdfRequestOptions', () => { + it('should return httpHeaders', () => { + const result: GetRequestOptions = repository.buildPdfRequestOptions(); - expect(httpClient.get).toHaveBeenCalledWith(uri, requestOptions); - }) + expect(result.responseType).toEqual('blob'); + }); - it('should return value', () => { - const result = repository.downloadPdf(uri); + it('should return responseType', () => { + const result: GetRequestOptions = repository.buildPdfRequestOptions(); - expect(result).toBeObservable(cold('b', { b: blob })); - }) + expect(result.headers).toEqual(getExpectedRequestOptions()); + }); + }); - describe('buildPdfRequestOptions', () => { + function getExpectedRequestOptions(): HttpHeaders { + return new HttpHeaders().set('Accept', [ + ContentType.APPLICATION_PDF, + ContentType.APPLICATION_JSON, + ]); + } + }); - it('should return httpHeaders', () => { - const result: GetRequestOptions = repository.buildPdfRequestOptions(); + describe('get file', () => { + const uri: ResourceUri = faker.internet.url(); - expect(result.responseType).toEqual('blob'); - }) + it('should call repository factory', () => { + repository.getFile(uri); - it('should return responseType', () => { - const result: GetRequestOptions = repository.buildPdfRequestOptions(); + expect(resourceFactory.fromId).toHaveBeenCalledWith(uri); + }); - expect(result.headers).toEqual(getExpectedRequestOptions()); - }) - }) + it('should call repository wrapper', () => { + repository.getFile(uri); - function getExpectedRequestOptions(): HttpHeaders { - return new HttpHeaders() - .set('Accept', [ContentType.APPLICATION_PDF, ContentType.APPLICATION_JSON]); - } - }) + expect(resourceWrapper.get).toHaveBeenCalled(); + }); + }); - describe('get file', () => { + describe('get files', () => { + const resource: Resource = createDummyResource([DummyLinkRel.DUMMY]); + const listResource: ListResource = createDummyListResource(); - const uri: ResourceUri = faker.internet.url(); + beforeEach(() => { + resourceWrapper.get.mockReturnValue(cold('a', { a: listResource })); + }); - it('should call repository factory', () => { - repository.getFile(uri); + it('should call resource factory', () => { + repository.getFiles(resource, DummyLinkRel.DUMMY); - expect(resourceFactory.fromId).toHaveBeenCalledWith(uri); - }) + expect(resourceFactory.from).toHaveBeenCalledWith(resource); + }); - it('should call repository wrapper', () => { - repository.getFile(uri); + it('should call resource wrapper get with linkRel', () => { + repository.getFiles(resource, DummyLinkRel.DUMMY); - expect(resourceWrapper.get).toHaveBeenCalled(); - }) - }) - - describe('get files', () => { - - const resource: Resource = createDummyResource([DummyLinkRel.DUMMY]); - const listResource: ListResource = createDummyListResource(); - - beforeEach(() => { - resourceWrapper.get.mockReturnValue(cold('a', { a: listResource })); - }) - - it('should call resource factory', () => { - repository.getFiles(resource, DummyLinkRel.DUMMY); - - expect(resourceFactory.from).toHaveBeenCalledWith(resource); - }) - - it('should call resource wrapper get with linkRel', () => { - repository.getFiles(resource, DummyLinkRel.DUMMY); - - expect(resourceWrapper.get).toHaveBeenCalledWith(DummyLinkRel.DUMMY); - }) - }) -}) \ No newline at end of file + expect(resourceWrapper.get).toHaveBeenCalledWith(DummyLinkRel.DUMMY); + }); + }); +}); diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.ts index c5b71b4fb1f4efc1392959bf11afc7bd18e62950..9e2d3f4548b00e0fbbe64f7971b4af6c44356479 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.repository.ts @@ -23,7 +23,12 @@ */ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { ContentType, GetRequestOptions, HttpHeader, SkipInterceptor } from '@alfa-client/tech-shared'; +import { + ContentType, + GetRequestOptions, + HttpHeader, + SkipInterceptor, +} from '@alfa-client/tech-shared'; import { Resource, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest'; import { Observable } from 'rxjs'; import { BinaryFileLinkRel } from './binary-file.linkrel'; @@ -31,49 +36,57 @@ import { BinaryFileListResource, BinaryFileResource } from './binary-file.model' @Injectable({ providedIn: 'root' }) export class BinaryFileRepository { + constructor( + private httpClient: HttpClient, + private resourceFactory: ResourceFactory, + ) {} - constructor(private httpClient: HttpClient, private resourceFactory: ResourceFactory) { } + public uploadFile(resource: Resource, linkRel: string, file: File): Observable<any> { + const formData: FormData = new FormData(); - public uploadFile(resource: Resource, linkRel: string, file: File): Observable<any> { - const formData: FormData = new FormData(); + formData.append('file', file, file.name); - formData.append('file', file, file.name); + return this.httpClient.post(getUrl(resource, linkRel), formData, { observe: 'response' }); + } - return this.httpClient.post(getUrl(resource, linkRel), formData, { observe: 'response' }); - } + public download(fileResource: BinaryFileResource): Observable<Blob> { + return this.doDownload( + getUrl(fileResource, BinaryFileLinkRel.DOWNLOAD), + this.buildRequestOptions(), + ); + } - public download(fileResource: BinaryFileResource): Observable<Blob> { - return this.doDownload(getUrl(fileResource, BinaryFileLinkRel.DOWNLOAD), this.buildRequestOptions()); - } + buildRequestOptions(): GetRequestOptions { + return this.buildBaseRequestOptions([ContentType.APPLICATION_ALL, ContentType.IMAGES_ALL]); + } - buildRequestOptions(): GetRequestOptions { - return this.buildBaseRequestOptions([ContentType.APPLICATION_ALL, ContentType.IMAGES_ALL]); - } + @SkipInterceptor() + public downloadPdf(uri: ResourceUri): Observable<Blob> { + return this.doDownload(uri, this.buildPdfRequestOptions()); + } - @SkipInterceptor() - public downloadPdf(uri: ResourceUri): Observable<Blob> { - return this.doDownload(uri, this.buildPdfRequestOptions()); - } + private doDownload(uri: ResourceUri, requestOptions: GetRequestOptions): Observable<Blob> { + return this.httpClient.get<Blob>(uri, requestOptions); + } - private doDownload(uri: ResourceUri, requestOptions: GetRequestOptions): Observable<Blob> { - return this.httpClient.get<Blob>(uri, requestOptions); - } + buildPdfRequestOptions(): GetRequestOptions { + return this.buildBaseRequestOptions([ + ContentType.APPLICATION_PDF, + ContentType.APPLICATION_JSON, + ]); + } - buildPdfRequestOptions(): GetRequestOptions { - return this.buildBaseRequestOptions([ContentType.APPLICATION_PDF, ContentType.APPLICATION_JSON]); - } + buildBaseRequestOptions(contentTypes: ContentType[]): GetRequestOptions { + let headers = new HttpHeaders(); + headers = headers.set(HttpHeader.ACCEPT, contentTypes); + return { headers, responseType: 'blob' as 'json' }; + } - buildBaseRequestOptions(contentTypes: ContentType[]): GetRequestOptions { - let headers = new HttpHeaders(); - headers = headers.set(HttpHeader.ACCEPT, contentTypes); - return { headers, responseType: 'blob' as 'json' }; - } + public getFile(fileUri: ResourceUri): Observable<BinaryFileResource> { + return this.resourceFactory.fromId(fileUri).get(); + } - public getFile(fileUri: ResourceUri): Observable<BinaryFileResource> { - return this.resourceFactory.fromId(fileUri).get(); - } - - public getFiles(resource: Resource, linkRel: string): Observable<BinaryFileListResource> { - return this.resourceFactory.from(resource).get(linkRel); - } -} \ No newline at end of file + public getFiles(resource: Resource, linkRel: string): Observable<BinaryFileListResource> { + return this.resourceFactory.from(resource).get(linkRel); + } +} diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.spec.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.spec.ts index 343d584903298fe14e8d9912bcbab23d56e0d175..dd1eb565f4a402534ffccdbcbbebe89d2978e5b3 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.spec.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.spec.ts @@ -23,13 +23,20 @@ */ import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { faker } from '@faker-js/faker'; -import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { SnackBarService } from '@alfa-client/ui'; import { Resource } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; import { createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; -import { ValidationMessageCode, VALIDATION_MESSAGES } from 'libs/tech-shared/src/lib/validation/tech.validation.messages'; +import { + ValidationMessageCode, + VALIDATION_MESSAGES, +} from 'libs/tech-shared/src/lib/validation/tech.validation.messages'; import { DummyLinkRel } from 'libs/tech-shared/test/dummy'; import { createDummyResource } from 'libs/tech-shared/test/resource'; import { of } from 'rxjs'; @@ -38,149 +45,171 @@ import { BinaryFileRepository } from './binary-file.repository'; import { BinaryFileService } from './binary-file.service'; describe('BinaryFileService', () => { - let service: BinaryFileService; + let service: BinaryFileService; - let repository: Mock<BinaryFileRepository> - let snackBarService: Mock<SnackBarService>; + let repository: Mock<BinaryFileRepository>; + let snackBarService: Mock<SnackBarService>; - beforeEach(() => { - repository = mock(BinaryFileRepository); - snackBarService = mock(SnackBarService); + beforeEach(() => { + repository = mock(BinaryFileRepository); + snackBarService = mock(SnackBarService); - service = new BinaryFileService(useFromMock(repository), useFromMock(snackBarService)); - }) - - it('should created', () => { - expect(service).toBeTruthy(); - }) - - describe('download file', () => { - - const binaryFileResource: BinaryFileResource = createBinaryFileResource(); - const downloadNamePrefix: string = 'VorgangsNummerAsPrefix'; - - const blob = {}; - - beforeEach(() => { - service.save = jest.fn(); - repository.download.mockReturnValue(hot('a', { a: blob })); - }) - - it('should call repository', () => { - service.downloadFile(binaryFileResource, downloadNamePrefix); - - expect(repository.download).toHaveBeenCalledWith(binaryFileResource); - }) - - describe('save file', () => { - - describe('on existing response', () => { - - it('should save file without prefix', () => { - service.saveBinaryFile(blob, binaryFileResource, undefined); - - expect(service.save).toHaveBeenCalledWith(blob, binaryFileResource.name); - }) - - it('should save file with prefix', () => { - service.saveBinaryFile(blob, binaryFileResource, downloadNamePrefix); - - expect(service.save).toHaveBeenCalledWith(blob, downloadNamePrefix + '_' + binaryFileResource.name); - }) - - it('should return loaded stateResource', () => { - const result: StateResource<Blob> = service.saveBinaryFile(blob, binaryFileResource, downloadNamePrefix); - - expect(result).toEqual(createStateResource(blob)); - }) - }) - - describe('on non existing response', () => { - - it('should return loading stateResource', () => { - const result: StateResource<Blob> = service.saveBinaryFile(undefined, binaryFileResource, downloadNamePrefix); - - expect(result).toEqual(createEmptyStateResource(true)); - }) - }) - }) - }) - - describe('upload file', () => { - - const dummyResource: Resource = createDummyResource(); - const dummyLinkRel: string = DummyLinkRel.DUMMY; - - const fileLocation: string = 'fileLocation'; - const uploadFileResponse: HttpResponse<void> = <any>{ response: { headers: { ['Location']: fileLocation } } }; - - const testFile: any = {}; - const returnFile: any = {}; - - beforeEach(() => { - repository.uploadFile.mockReturnValue(hot('-a', { a: uploadFileResponse })); - repository.getFile.mockReturnValue(of(returnFile)); - }) - - it('should call repository', () => { - service.uploadFile(dummyResource, dummyLinkRel, testFile) - - expect(repository.uploadFile).toHaveBeenCalledWith(dummyResource, dummyLinkRel, testFile); - }) - - it.skip('FIXME: should call get file', () => { - repository.uploadFile.mockReturnValue(of(uploadFileResponse)); - repository.getFile.mockReturnValue(of(returnFile)); - - service.uploadFile(dummyResource, dummyLinkRel, testFile); - - expect(repository.getFile).toHaveBeenCalledWith(fileLocation); - }) - - describe('handleErrorByStaus', () => { - - it('should show snackbar on ' + ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED + ' error', () => { - const response: HttpErrorResponse = buildErrorResponse(ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED); - - service.handleErrorByStatus(response); - - expect(snackBarService.showError).toHaveBeenCalledWith(VALIDATION_MESSAGES[ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED]); - }) - - it('should not call snackbar on other error', () => { - const response: HttpErrorResponse = buildErrorResponse(ValidationMessageCode.VALIDATION_FIELD_EMPTY); - - service.handleErrorByStatus(response); - - expect(snackBarService.showError).not.toHaveBeenCalled(); - }) - - function buildErrorResponse(messageCode: string): HttpErrorResponse { - return <HttpErrorResponse>{ status: 422, error: { issues: [{ messageCode, parameters: [] }] } } - } - }) - }) - - describe('get file', () => { - - const responseResource: Resource = createDummyResource(); - - const uri: string = faker.internet.url(); - - beforeEach(() => { - repository.getFile.mockReturnValue(hot('-a', { a: responseResource })); - }) - - it('should call repository', () => { - service.getFile(uri); - - expect(repository.getFile).toHaveBeenCalledWith(uri); - }) - - it('should return value', () => { - const fileList = service.getFile(uri); - - expect(fileList).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: createStateResource(responseResource) })); - }) - }) -}) \ No newline at end of file + service = new BinaryFileService(useFromMock(repository), useFromMock(snackBarService)); + }); + + it('should created', () => { + expect(service).toBeTruthy(); + }); + + describe('download file', () => { + const binaryFileResource: BinaryFileResource = createBinaryFileResource(); + const downloadNamePrefix: string = 'VorgangsNummerAsPrefix'; + + const blob = {}; + + beforeEach(() => { + service.save = jest.fn(); + repository.download.mockReturnValue(hot('a', { a: blob })); + }); + + it('should call repository', () => { + service.downloadFile(binaryFileResource, downloadNamePrefix); + + expect(repository.download).toHaveBeenCalledWith(binaryFileResource); + }); + + describe('save file', () => { + describe('on existing response', () => { + it('should save file without prefix', () => { + service.saveBinaryFile(blob, binaryFileResource, undefined); + + expect(service.save).toHaveBeenCalledWith(blob, binaryFileResource.name); + }); + + it('should save file with prefix', () => { + service.saveBinaryFile(blob, binaryFileResource, downloadNamePrefix); + + expect(service.save).toHaveBeenCalledWith( + blob, + downloadNamePrefix + '_' + binaryFileResource.name, + ); + }); + + it('should return loaded stateResource', () => { + const result: StateResource<Blob> = service.saveBinaryFile( + blob, + binaryFileResource, + downloadNamePrefix, + ); + + expect(result).toEqual(createStateResource(blob)); + }); + }); + + describe('on non existing response', () => { + it('should return loading stateResource', () => { + const result: StateResource<Blob> = service.saveBinaryFile( + undefined, + binaryFileResource, + downloadNamePrefix, + ); + + expect(result).toEqual(createEmptyStateResource(true)); + }); + }); + }); + }); + + describe('upload file', () => { + const dummyResource: Resource = createDummyResource(); + const dummyLinkRel: string = DummyLinkRel.DUMMY; + + const fileLocation: string = 'fileLocation'; + const uploadFileResponse: HttpResponse<void> = <any>{ + response: { headers: { ['Location']: fileLocation } }, + }; + + const testFile: any = {}; + const returnFile: any = {}; + + beforeEach(() => { + repository.uploadFile.mockReturnValue(hot('-a', { a: uploadFileResponse })); + repository.getFile.mockReturnValue(of(returnFile)); + }); + + it('should call repository', () => { + service.uploadFile(dummyResource, dummyLinkRel, testFile); + + expect(repository.uploadFile).toHaveBeenCalledWith(dummyResource, dummyLinkRel, testFile); + }); + + it.skip('FIXME: should call get file', () => { + repository.uploadFile.mockReturnValue(of(uploadFileResponse)); + repository.getFile.mockReturnValue(of(returnFile)); + + service.uploadFile(dummyResource, dummyLinkRel, testFile); + + expect(repository.getFile).toHaveBeenCalledWith(fileLocation); + }); + + describe('handleErrorByStaus', () => { + it( + 'should show snackbar on ' + + ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED + + ' error', + () => { + const response: HttpErrorResponse = buildErrorResponse( + ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED, + ); + + service.handleErrorByStatus(response); + + expect(snackBarService.showError).toHaveBeenCalledWith( + VALIDATION_MESSAGES[ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED], + ); + }, + ); + + it('should not call snackbar on other error', () => { + const response: HttpErrorResponse = buildErrorResponse( + ValidationMessageCode.VALIDATION_FIELD_EMPTY, + ); + + service.handleErrorByStatus(response); + + expect(snackBarService.showError).not.toHaveBeenCalled(); + }); + + function buildErrorResponse(messageCode: string): HttpErrorResponse { + return <HttpErrorResponse>{ + status: 422, + error: { issues: [{ messageCode, parameters: [] }] }, + }; + } + }); + }); + + describe('get file', () => { + const responseResource: Resource = createDummyResource(); + + const uri: string = faker.internet.url(); + + beforeEach(() => { + repository.getFile.mockReturnValue(hot('-a', { a: responseResource })); + }); + + it('should call repository', () => { + service.getFile(uri); + + expect(repository.getFile).toHaveBeenCalledWith(uri); + }); + + it('should return value', () => { + const fileList = service.getFile(uri); + + expect(fileList).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: createStateResource(responseResource) }), + ); + }); + }); +}); diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.ts index 33f0a15ebb51d77c71997773d0998bb582489a61..7c690c1edebd65d060b86b299e636ea98ca905f4 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.service.ts @@ -23,7 +23,18 @@ */ import { HttpErrorResponse, HttpResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { createEmptyStateResource, createErrorStateResource, createStateResource, EMPTY_STRING, getMessageForIssue, isNotNil, isUnprocessableEntity, isValidationFieldFileSizeExceedError, sanitizeFileName, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createErrorStateResource, + createStateResource, + EMPTY_STRING, + getMessageForIssue, + isNotNil, + isUnprocessableEntity, + isValidationFieldFileSizeExceedError, + sanitizeFileName, + StateResource, +} from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; import { Resource, ResourceUri } from '@ngxp/rest'; import { saveAs } from 'file-saver'; @@ -35,62 +46,78 @@ import { BinaryFileRepository } from './binary-file.repository'; @Injectable({ providedIn: 'root' }) export class BinaryFileService { + constructor( + private repository: BinaryFileRepository, + private snackbarService: SnackBarService, + ) {} - constructor(private repository: BinaryFileRepository, private snackbarService: SnackBarService) { } + public uploadFile( + resource: Resource, + linkRel: string, + file: File, + ): Observable<StateResource<BinaryFileResource>> { + return this.repository.uploadFile(resource, linkRel, file).pipe( + mergeMap((response: HttpResponse<void>) => this.getFile(response.headers.get('Location'))), + catchError((errorResponse) => this.handleError(errorResponse.error)), + startWith(createEmptyStateResource<BinaryFileResource>(true)), + ); + } - public uploadFile(resource: Resource, linkRel: string, file: File): Observable<StateResource<BinaryFileResource>> { - return this.repository.uploadFile(resource, linkRel, file).pipe( - mergeMap((response: HttpResponse<void>) => this.getFile(response.headers.get('Location'))), - catchError(errorResponse => this.handleError(errorResponse.error)), - startWith(createEmptyStateResource<BinaryFileResource>(true))); - } + private handleError(errorResponse: HttpErrorResponse): Observable<StateResource<any>> { + return of(this.handleErrorByStatus(errorResponse)); + } - private handleError(errorResponse: HttpErrorResponse): Observable<StateResource<any>> { - return of(this.handleErrorByStatus(errorResponse)); - } + handleErrorByStatus(error: HttpErrorResponse): StateResource<any> { + if (isUnprocessableEntity(error.status) && isValidationFieldFileSizeExceedError(error.error)) { + this.snackbarService.showError(getMessageForIssue(EMPTY_STRING, error.error.issues[0])); + return createErrorStateResource(error.error); + } + throwError({ error }); + } - handleErrorByStatus(error: HttpErrorResponse): StateResource<any> { - if (isUnprocessableEntity(error.status) && isValidationFieldFileSizeExceedError(error.error)) { - this.snackbarService.showError(getMessageForIssue(EMPTY_STRING, error.error.issues[0])); - return createErrorStateResource(error.error); - } - throwError({ error }); - } + public downloadFile( + file: BinaryFileResource, + fileNamePrefix: string, + ): Observable<StateResource<any>> { + return this.repository.download(file).pipe( + map((data) => this.saveBinaryFile(data, file, fileNamePrefix)), + startWith(createEmptyStateResource(true)), + ); + } - public downloadFile(file: BinaryFileResource, fileNamePrefix: string): Observable<StateResource<any>> { - return this.repository.download(file).pipe( - map(data => this.saveBinaryFile(data, file, fileNamePrefix)), - startWith(createEmptyStateResource(true))); - } + saveBinaryFile(data: any, file: BinaryFileResource, fileNamePrefix: string): StateResource<Blob> { + if (isNil(data)) { + return createEmptyStateResource(true); + } + this.save(data, this.buildFileName(file, fileNamePrefix)); + return createStateResource(data); + } - saveBinaryFile(data: any, file: BinaryFileResource, fileNamePrefix: string): StateResource<Blob> { - if (isNil(data)) { - return createEmptyStateResource(true); - } - this.save(data, this.buildFileName(file, fileNamePrefix)); - return createStateResource(data); - } + private buildFileName(file: BinaryFileResource, fileNamePrefix: string): string { + if (isNotNil(fileNamePrefix)) { + return sanitizeFileName(`${fileNamePrefix}_${file.name}`); + } + return file.name; + } - private buildFileName(file: BinaryFileResource, fileNamePrefix: string): string { - if(isNotNil(fileNamePrefix)){ - return sanitizeFileName(`${fileNamePrefix}_${file.name}`); - } - return file.name; - } + save(data: any, fileName: string): void { + saveAs(data, fileName); + } - save(data: any, fileName: string): void { - saveAs(data, fileName) - } + getFile(uri: ResourceUri): Observable<StateResource<BinaryFileResource>> { + return this.repository.getFile(uri).pipe( + map((fileList) => createStateResource(fileList)), + startWith(createEmptyStateResource<any>(true)), + ); + } - getFile(uri: ResourceUri): Observable<StateResource<BinaryFileResource>> { - return this.repository.getFile(uri).pipe( - map(fileList => createStateResource(fileList)), - startWith(createEmptyStateResource<any>(true))); - } - - public getFiles(resource: Resource, linkRel: string): Observable<StateResource<BinaryFileListResource>> { - return this.repository.getFiles(resource, linkRel).pipe( - map(fileList => createStateResource(fileList)), - startWith(createEmptyStateResource<BinaryFileListResource>(true))); - } -} \ No newline at end of file + public getFiles( + resource: Resource, + linkRel: string, + ): Observable<StateResource<BinaryFileListResource>> { + return this.repository.getFiles(resource, linkRel).pipe( + map((fileList) => createStateResource(fileList)), + startWith(createEmptyStateResource<BinaryFileListResource>(true)), + ); + } +} diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.util.spec.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.util.spec.ts index 1267eab9251fc3765e25564ed54bd360adaf59e6..18931f0e3a25958fdd2680bde6c1a8c7e4ca51c1 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.util.spec.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.util.spec.ts @@ -1,19 +1,21 @@ import { StateResource, createStateResource } from '@alfa-client/tech-shared'; -import { createBinaryFileListResource, createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; +import { + createBinaryFileListResource, + createBinaryFileResource, +} from 'libs/binary-file-shared/test/binary-file'; import { BinaryFileListResource, BinaryFileResource } from './binary-file.model'; import { getBinaryFiles } from './binary-file.util'; describe('BinaryFile Util', () => { + describe('getBinaryFiles', () => { + it('should extract resource', () => { + const binaryFileResources: BinaryFileResource[] = [createBinaryFileResource()]; + const binaryFileListStateResource: StateResource<BinaryFileListResource> = + createStateResource(createBinaryFileListResource(binaryFileResources)); - describe('getBinaryFiles', () => { + const resources: BinaryFileResource[] = getBinaryFiles(binaryFileListStateResource); - it('should extract resource', () => { - const binaryFileResources: BinaryFileResource[] = [createBinaryFileResource()]; - const binaryFileListStateResource: StateResource<BinaryFileListResource> = createStateResource(createBinaryFileListResource(binaryFileResources)); - - const resources: BinaryFileResource[] = getBinaryFiles(binaryFileListStateResource); - - expect(resources).toEqual(binaryFileResources); - }) - }) -}) \ No newline at end of file + expect(resources).toEqual(binaryFileResources); + }); + }); +}); diff --git a/alfa-client/libs/binary-file-shared/src/lib/binary-file.util.ts b/alfa-client/libs/binary-file-shared/src/lib/binary-file.util.ts index 4a6bc70278d499e18d90738f330aab48bacc1c6d..b34aefb261df45052ef6492127c733afdd513d87 100644 --- a/alfa-client/libs/binary-file-shared/src/lib/binary-file.util.ts +++ b/alfa-client/libs/binary-file-shared/src/lib/binary-file.util.ts @@ -2,6 +2,8 @@ import { StateResource, getEmbeddedResources } from '@alfa-client/tech-shared'; import { BinaryFileListLinkRel } from './binary-file.linkrel'; import { BinaryFileListResource, BinaryFileResource } from './binary-file.model'; -export function getBinaryFiles(binaryFileListResource: StateResource<BinaryFileListResource>): BinaryFileResource[] { - return getEmbeddedResources(binaryFileListResource, BinaryFileListLinkRel.FILE_LIST); -} \ No newline at end of file +export function getBinaryFiles( + binaryFileListResource: StateResource<BinaryFileListResource>, +): BinaryFileResource[] { + return getEmbeddedResources(binaryFileListResource, BinaryFileListLinkRel.FILE_LIST); +} diff --git a/alfa-client/libs/binary-file-shared/src/test-setup.ts b/alfa-client/libs/binary-file-shared/src/test-setup.ts index cbeefdc58031f06c736e48411560272e35e07476..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/binary-file-shared/src/test-setup.ts +++ b/alfa-client/libs/binary-file-shared/src/test-setup.ts @@ -24,15 +24,14 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); \ No newline at end of file +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/binary-file-shared/test/binary-file.ts b/alfa-client/libs/binary-file-shared/test/binary-file.ts index 018383998564b1087d28001dd32ec715d0eb0686..21634f60e75bd90eec611239f9f1ea4152ed21b5 100644 --- a/alfa-client/libs/binary-file-shared/test/binary-file.ts +++ b/alfa-client/libs/binary-file-shared/test/binary-file.ts @@ -23,28 +23,35 @@ */ import { faker } from '@faker-js/faker'; import { BinaryFileListLinkRel } from 'libs/binary-file-shared/src/lib/binary-file.linkrel'; -import { BinaryFile, BinaryFileListResource, BinaryFileResource } from 'libs/binary-file-shared/src/lib/binary-file.model'; +import { + BinaryFile, + BinaryFileListResource, + BinaryFileResource, +} from 'libs/binary-file-shared/src/lib/binary-file.model'; import { toResource } from 'libs/tech-shared/test/resource'; import { times } from 'lodash-es'; export function createBinaryFile(): BinaryFile { - return { - name: faker.lorem.slug(10), - size: faker.datatype.number({ min: 1024, max: 10000000000 }), - contentType: faker.lorem.word() - } + return { + name: faker.lorem.slug(10), + size: faker.datatype.number({ min: 1024, max: 10000000000 }), + contentType: faker.lorem.word(), + }; } export function createBinaryFileResource(linkRelations: string[] = []): BinaryFileResource { - return toResource(createBinaryFile(), linkRelations); + return toResource(createBinaryFile(), linkRelations); } export function createBinaryFileResources(linkRelations: string[] = []): BinaryFileResource[] { - return times(10, () => toResource(createBinaryFileResource(), [...linkRelations])); + return times(10, () => toResource(createBinaryFileResource(), [...linkRelations])); } -export function createBinaryFileListResource(resources?: BinaryFileResource[], linkRelations: string[] = []): BinaryFileListResource { - return toResource({}, [...linkRelations], { - [BinaryFileListLinkRel.FILE_LIST]: resources ? resources : createBinaryFileResources() - }) +export function createBinaryFileListResource( + resources?: BinaryFileResource[], + linkRelations: string[] = [], +): BinaryFileListResource { + return toResource({}, [...linkRelations], { + [BinaryFileListLinkRel.FILE_LIST]: resources ? resources : createBinaryFileResources(), + }); } diff --git a/alfa-client/libs/binary-file-shared/tsconfig.json b/alfa-client/libs/binary-file-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/binary-file-shared/tsconfig.json +++ b/alfa-client/libs/binary-file-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/binary-file-shared/tsconfig.lib.json b/alfa-client/libs/binary-file-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/binary-file-shared/tsconfig.lib.json +++ b/alfa-client/libs/binary-file-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/binary-file-shared/tsconfig.spec.json b/alfa-client/libs/binary-file-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/binary-file-shared/tsconfig.spec.json +++ b/alfa-client/libs/binary-file-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/binary-file/.eslintrc.json b/alfa-client/libs/binary-file/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/binary-file/.eslintrc.json +++ b/alfa-client/libs/binary-file/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/binary-file/jest.config.ts b/alfa-client/libs/binary-file/jest.config.ts index b18a65a9c2f26b346b7cdb4391016cf40cf47312..38dc28229798307d31c30307dde1920d6312fec1 100644 --- a/alfa-client/libs/binary-file/jest.config.ts +++ b/alfa-client/libs/binary-file/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'binary-file', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/binary-file', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'binary-file', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/binary-file', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/binary-file/project.json b/alfa-client/libs/binary-file/project.json index 7ab083e37819ddef4f46394b0b979dee64c46ebd..5ef325574bcf04cc4729f75a744e77960be14aa8 100644 --- a/alfa-client/libs/binary-file/project.json +++ b/alfa-client/libs/binary-file/project.json @@ -1,29 +1,26 @@ { - "name": "binary-file", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/binary-file/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/binary-file"], - "options": { - "tsConfig": "libs//binary-file/tsconfig.spec.json", - "jestConfig": "libs/binary-file/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/binary-file/src/**/*.ts", - "libs/binary-file/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [] + "name": "binary-file", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/binary-file/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/binary-file"], + "options": { + "tsConfig": "libs//binary-file/tsconfig.spec.json", + "jestConfig": "libs/binary-file/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/binary-file/src/**/*.ts", "libs/binary-file/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [] } diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.html index e28204da7e022b58ba432ab2cb94c2572534f267..bb866a347f0ddd4518b3bf25f14837a5d2da0a74 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.html +++ b/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.html @@ -24,15 +24,21 @@ --> <div class="binary-file-list" data-test-id="file-list"> - <alfa-binary-file-container *ngFor="let file of fileList" - [file]="file" [deletable]="true" - (startDelete)="deleteAttachment($event)"> - </alfa-binary-file-container> + <alfa-binary-file-container + *ngFor="let file of fileList" + [file]="file" + [deletable]="true" + (startDelete)="deleteAttachment($event)" + > + </alfa-binary-file-container> </div> -<ozgcloud-file-upload-editor *ngIf="uploadStateResource.resource | hasLink: linkRelUploadAttachment" data-test-id="binary-file-upload" - [parentFormArrayName]="formArrayName" - [fileLinkList]="getFileUriList()" - [uploadInProgress]="uploadInProgress$ | async" - (newFile)="uploadFile($event)"> +<ozgcloud-file-upload-editor + *ngIf="uploadStateResource.resource | hasLink: linkRelUploadAttachment" + data-test-id="binary-file-upload" + [parentFormArrayName]="formArrayName" + [fileLinkList]="getFileUriList()" + [uploadInProgress]="uploadInProgress$ | async" + (newFile)="uploadFile($event)" +> </ozgcloud-file-upload-editor> diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.scss b/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.scss index 39d68cc46d548a63cb44d429a2129b0786e216b3..04336e235cf89d46e2e0f2c7cafc5924313c72cf 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.scss +++ b/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.scss @@ -22,12 +22,12 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host ::ng-deep alfa-binary-file .container { - width: auto; - max-width: inherit; + width: auto; + max-width: inherit; } .binary-file-list { - display: flex; - flex-wrap: wrap; - max-width: 100%; -} \ No newline at end of file + display: flex; + flex-wrap: wrap; + max-width: 100%; +} diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.spec.ts index 4ee5cb37e6a1b56e350f8c72752bbb538803df6e..a6bbba00ac80710e27f88848304cf8d711146830 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.spec.ts @@ -23,7 +23,12 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { BinaryFileResource, BinaryFileService } from '@alfa-client/binary-file-shared'; -import { HasLinkPipe, StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + HasLinkPipe, + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; import { createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; import { FileUploadEditorComponent } from 'libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component'; @@ -33,128 +38,131 @@ import { BinaryFileContainerComponent } from './../binary-file-container/binary- import { BinaryFileAttachmentContainerComponent } from './binary-file-attachment-container.component'; describe('BinaryFileAttachmentContainerComponent', () => { - let component: BinaryFileAttachmentContainerComponent; - let fixture: ComponentFixture<BinaryFileAttachmentContainerComponent>; - - const binaryFileService = mock(BinaryFileService); - const binaryFile: BinaryFileResource = createBinaryFileResource(); - const linkRelUploadAttachment: string = 'test'; + let component: BinaryFileAttachmentContainerComponent; + let fixture: ComponentFixture<BinaryFileAttachmentContainerComponent>; + + const binaryFileService = mock(BinaryFileService); + const binaryFile: BinaryFileResource = createBinaryFileResource(); + const linkRelUploadAttachment: string = 'test'; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + BinaryFileAttachmentContainerComponent, + HasLinkPipe, + MockComponent(BinaryFileContainerComponent), + MockComponent(FileUploadEditorComponent), + ], + providers: [ + { + provide: BinaryFileService, + useValue: binaryFileService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BinaryFileAttachmentContainerComponent); + component = fixture.componentInstance; + component.uploadStateResource = createStateResource(binaryFile); + component.linkRelUploadAttachment = linkRelUploadAttachment; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('existing files', () => { + it('should show existing files', () => { + const binaryFile2: BinaryFileResource = createBinaryFileResource(); + + component.existFiles = [binaryFile2, binaryFile]; + fixture.detectChanges(); + + expect(component.fileList).toHaveLength(2); + expect(component.fileList[0]).toBe(binaryFile2); + expect(component.fileList[1]).toBe(binaryFile); + }); + }); + + describe('upload file', () => { + const file: File = <any>{ name: 'TestDatei' }; + + it('should call uploadAndGetFile', () => { + component.uploadAndGetFile = jest.fn(); + + component.uploadFile(file); + + expect(component.uploadAndGetFile).toHaveBeenCalledWith(file); + }); + }); + + describe('upload and get file', () => { + const file: File = <any>{ name: 'TestDatei' }; + const responseStateResource: StateResource<BinaryFileResource> = + createStateResource(binaryFile); + + beforeEach(() => { + binaryFileService.uploadFile.mockReturnValue(of(responseStateResource)); + }); + + it('should call service', () => { + component.uploadFile(file); + + expect(binaryFileService.uploadFile).toHaveBeenCalledWith( + binaryFile, + linkRelUploadAttachment, + file, + ); + }); + + it('should call doAfterFileUpload', (done) => { + component.doAfterFileUpload = jest.fn(); + + component.uploadAndGetFile(file).subscribe(() => { + expect(component.doAfterFileUpload).toHaveBeenCalledWith(responseStateResource); + done(); + }); + + component.uploadFile(file); + }); + }); + + describe('doAfterFileUpload', () => { + it('should add binaryFile', () => { + component.doAfterFileUpload(createStateResource(binaryFile)); + + expect(component.fileList).toHaveLength(1); + expect(component.fileList[0]).toBe(binaryFile); + }); + + it('should NOT add binaryFile', () => { + component.doAfterFileUpload(createEmptyStateResource()); + + expect(component.fileList).toHaveLength(0); + }); + }); + + describe('delete attachment', () => { + const existingFile: BinaryFileResource = createBinaryFileResource(); + + beforeEach(() => { + component.fileList = [existingFile]; + }); + + it('should remove binaryFile', () => { + component.deleteAttachment(existingFile); + + expect(component.fileList).toHaveLength(0); + }); + + it('should NOT remove binaryFile', () => { + component.deleteAttachment(createBinaryFileResource()); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - BinaryFileAttachmentContainerComponent, - HasLinkPipe, - MockComponent(BinaryFileContainerComponent), - MockComponent(FileUploadEditorComponent) - ], - providers: [ - { - provide: BinaryFileService, - useValue: binaryFileService - } - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(BinaryFileAttachmentContainerComponent); - component = fixture.componentInstance; - component.uploadStateResource = createStateResource(binaryFile); - component.linkRelUploadAttachment = linkRelUploadAttachment; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }) - - describe('existing files', () => { - it('should show existing files', () => { - const binaryFile2: BinaryFileResource = createBinaryFileResource(); - - component.existFiles = [binaryFile2, binaryFile]; - fixture.detectChanges(); - - expect(component.fileList).toHaveLength(2); - expect(component.fileList[0]).toBe(binaryFile2); - expect(component.fileList[1]).toBe(binaryFile); - }) - }) - - describe('upload file', () => { - const file: File = <any>{ name: 'TestDatei' }; - - it('should call uploadAndGetFile', () => { - component.uploadAndGetFile = jest.fn(); - - component.uploadFile(file) - - expect(component.uploadAndGetFile).toHaveBeenCalledWith(file); - }) - }) - - describe('upload and get file', () => { - const file: File = <any>{ name: 'TestDatei' }; - const responseStateResource: StateResource<BinaryFileResource> = createStateResource(binaryFile); - - beforeEach(() => { - binaryFileService.uploadFile.mockReturnValue(of(responseStateResource)); - }) - - it('should call service', () => { - component.uploadFile(file) - - expect(binaryFileService.uploadFile).toHaveBeenCalledWith(binaryFile, linkRelUploadAttachment, file); - }) - - it('should call doAfterFileUpload', (done) => { - component.doAfterFileUpload = jest.fn(); - - component.uploadAndGetFile(file).subscribe(() => { - expect(component.doAfterFileUpload).toHaveBeenCalledWith(responseStateResource); - done(); - }); - - component.uploadFile(file); - }) - }) - - describe('doAfterFileUpload', () => { - - it('should add binaryFile', () => { - component.doAfterFileUpload(createStateResource(binaryFile)); - - expect(component.fileList).toHaveLength(1); - expect(component.fileList[0]).toBe(binaryFile); - }) - - it('should NOT add binaryFile', () => { - component.doAfterFileUpload(createEmptyStateResource()); - - expect(component.fileList).toHaveLength(0); - }) - }) - - describe('delete attachment', () => { - - const existingFile: BinaryFileResource = createBinaryFileResource(); - - beforeEach(() => { - component.fileList = [existingFile]; - }) - - it('should remove binaryFile', () => { - component.deleteAttachment(existingFile); - - expect(component.fileList).toHaveLength(0); - }) - - it('should NOT remove binaryFile', () => { - component.deleteAttachment(createBinaryFileResource()); - - expect(component.fileList).toHaveLength(1) - expect(component.fileList[0]).toBe(existingFile); - }) - }) -}) \ No newline at end of file + expect(component.fileList).toHaveLength(1); + expect(component.fileList[0]).toBe(existingFile); + }); + }); +}); diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.ts b/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.ts index 890bad52d01ba378ff9f6bed43948706ff8af257..2fff5602416987f040d3987c1c6502102366ed70 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-attachment-container/binary-file-attachment-container.component.ts @@ -23,50 +23,61 @@ */ import { Component, Input } from '@angular/core'; import { BinaryFileResource, BinaryFileService } from '@alfa-client/binary-file-shared'; -import { EMPTY_ARRAY, StateResource, createEmptyStateResource, doOnValidStateResource, isNotNil } from '@alfa-client/tech-shared'; +import { + EMPTY_ARRAY, + StateResource, + createEmptyStateResource, + doOnValidStateResource, + isNotNil, +} from '@alfa-client/tech-shared'; import { Resource, getUrl } from '@ngxp/rest'; import { Observable, of } from 'rxjs'; import { tap } from 'rxjs/operators'; @Component({ - selector: 'alfa-binary-file-attachment-container', - templateUrl: './binary-file-attachment-container.component.html', - styleUrls: ['./binary-file-attachment-container.component.scss'], + selector: 'alfa-binary-file-attachment-container', + templateUrl: './binary-file-attachment-container.component.html', + styleUrls: ['./binary-file-attachment-container.component.scss'], }) export class BinaryFileAttachmentContainerComponent { + @Input() formArrayName: string; + @Input() uploadStateResource: StateResource<Resource>; + @Input() linkRelUploadAttachment: string; + @Input() set existFiles(value: BinaryFileResource[]) { + this.fileList = isNotNil(value) ? value : EMPTY_ARRAY; + } - @Input() formArrayName: string; - @Input() uploadStateResource: StateResource<Resource>; - @Input() linkRelUploadAttachment: string; - @Input() set existFiles(value: BinaryFileResource[]) { - this.fileList = isNotNil(value) ? value : EMPTY_ARRAY; - } + uploadInProgress$: Observable<StateResource<Resource>> = of(createEmptyStateResource<Resource>()); + fileList: BinaryFileResource[] = EMPTY_ARRAY; - uploadInProgress$: Observable<StateResource<Resource>> = of(createEmptyStateResource<Resource>()); - fileList: BinaryFileResource[] = EMPTY_ARRAY + constructor(private binaryFileService: BinaryFileService) {} - constructor(private binaryFileService: BinaryFileService) { } + public getFileUriList(): string[] { + return this.fileList.map((file) => getUrl(file)); + } - public getFileUriList(): string[] { - return this.fileList.map(file => getUrl(file)); - } + public uploadFile(file: File): void { + this.uploadInProgress$ = this.uploadAndGetFile(file); + } - public uploadFile(file: File): void { - this.uploadInProgress$ = this.uploadAndGetFile(file); - } + uploadAndGetFile(file: File): Observable<StateResource<BinaryFileResource>> { + return this.binaryFileService + .uploadFile(this.uploadStateResource.resource, this.linkRelUploadAttachment, file) + .pipe( + tap((stateResource: StateResource<BinaryFileResource>) => + this.doAfterFileUpload(stateResource), + ), + ); + } - uploadAndGetFile(file: File): Observable<StateResource<BinaryFileResource>> { - return this.binaryFileService.uploadFile(this.uploadStateResource.resource, this.linkRelUploadAttachment, file).pipe( - tap((stateResource: StateResource<BinaryFileResource>) => this.doAfterFileUpload(stateResource)) - ); - } + doAfterFileUpload(stateResource: StateResource<BinaryFileResource>): void { + doOnValidStateResource( + stateResource, + () => (this.fileList = [...this.fileList, stateResource.resource]), + ); + } - doAfterFileUpload(stateResource: StateResource<BinaryFileResource>): void { - doOnValidStateResource(stateResource, () => this.fileList = [...this.fileList, stateResource.resource]); - } - - public deleteAttachment(binaryFile: BinaryFileResource): void { - this.fileList = this.fileList.filter(file => getUrl(file) !== getUrl(binaryFile)); - } + public deleteAttachment(binaryFile: BinaryFileResource): void { + this.fileList = this.fileList.filter((file) => getUrl(file) !== getUrl(binaryFile)); + } } - diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.html index 448273ead64a0a01eb811144091ce26e98f70a4c..6d7bf293b7940940041a4bfab72a4effa98df82c 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.html +++ b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.html @@ -23,7 +23,14 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-binary-file [attr.data-test-id]="(file.name | convertForDataTest) + '-file-item'" - [file]="file" [stateResource]="fileStateResource$ | async" [deletable]="deletable" [downloadToken]="downloadToken$ | async" - (startDownload)="startDownload($event)" (startDelete)="startDelete.emit($event)" (getDownloadToken)="getDownloadToken()"> +<alfa-binary-file + [attr.data-test-id]="(file.name | convertForDataTest) + '-file-item'" + [file]="file" + [stateResource]="fileStateResource$ | async" + [deletable]="deletable" + [downloadToken]="downloadToken$ | async" + (startDownload)="startDownload($event)" + (startDelete)="startDelete.emit($event)" + (getDownloadToken)="getDownloadToken()" +> </alfa-binary-file> diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.scss b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.scss index f7cea7f72fa34961976b4a37f49e9fbbe4a4cec9..7dcaaf304d76dd842af6bcbcc811021fa5c8904f 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.scss +++ b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.scss @@ -22,8 +22,8 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - position: relative; - max-width: 100%; - padding: 4px 0; - font-size: 14px; -} \ No newline at end of file + position: relative; + max-width: 100%; + padding: 4px 0; + font-size: 14px; +} diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.spec.ts index a0061d0ea505c1d1aef4e98ef1bace0ef63c951b..f06f8dea0ea49372966c98ec32375bfdc763d8da 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.spec.ts @@ -33,65 +33,63 @@ import { BinaryFileContainerComponent } from './binary-file-container.component' import { BinaryFileComponent } from './binary-file/binary-file.component'; describe('BinaryFileContainerComponent', () => { - let component: BinaryFileContainerComponent; - let fixture: ComponentFixture<BinaryFileContainerComponent>; + let component: BinaryFileContainerComponent; + let fixture: ComponentFixture<BinaryFileContainerComponent>; - const service = mock(BinaryFileService); - const apiRootService = mock(ApiRootService); + const service = mock(BinaryFileService); + const apiRootService = mock(ApiRootService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - BinaryFileContainerComponent, - ConvertForDataTestPipe, - MockComponent(BinaryFileComponent) - ], - providers: [ - { - provide: BinaryFileService, - useValue: service - }, - { - provide: ApiRootService, - useValue: apiRootService - } - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + BinaryFileContainerComponent, + ConvertForDataTestPipe, + MockComponent(BinaryFileComponent), + ], + providers: [ + { + provide: BinaryFileService, + useValue: service, + }, + { + provide: ApiRootService, + useValue: apiRootService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(BinaryFileContainerComponent); - component = fixture.componentInstance; - component.file = createBinaryFileResource(); + beforeEach(() => { + fixture = TestBed.createComponent(BinaryFileContainerComponent); + component = fixture.componentInstance; + component.file = createBinaryFileResource(); - fixture.detectChanges(); - }); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('start download', () => { + describe('start download', () => { + const file: BinaryFileResource = createBinaryFileResource(); + const fileNameDownloadPrefix: string = 'FileNamePrefixDummy'; - const file: BinaryFileResource = createBinaryFileResource(); - const fileNameDownloadPrefix: string = 'FileNamePrefixDummy'; + it('should call file service downloadFile', () => { + component.downloadFileNamePrefix = fileNameDownloadPrefix; - it('should call file service downloadFile', () => { - component.downloadFileNamePrefix = fileNameDownloadPrefix; + component.startDownload(file); - component.startDownload(file); + expect(service.downloadFile).toHaveBeenCalledWith(file, fileNameDownloadPrefix); + }); + }); - expect(service.downloadFile).toHaveBeenCalledWith(file, fileNameDownloadPrefix); - }) - }) + describe('get download token', () => { + it('should call ApiRootService.getDownloadToken()', () => { + apiRootService.getDownloadToken.mockReturnValue(of('')); + component.getDownloadToken(); - describe('get download token', () => { - it('should call ApiRootService.getDownloadToken()', () => { - apiRootService.getDownloadToken.mockReturnValue(of('')); - component.getDownloadToken(); - - expect(apiRootService.getDownloadToken).toHaveBeenCalled(); - }); - }); + expect(apiRootService.getDownloadToken).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.ts b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.ts index b0432cd5c6fd084257fdbbbe8fc2661819a90e5c..1579dfd2c29c042b39493c32757dd7abc0ca8c13 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file-container.component.ts @@ -28,30 +28,33 @@ import { StateResource } from '@alfa-client/tech-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-binary-file-container', - templateUrl: './binary-file-container.component.html', - styleUrls: ['./binary-file-container.component.scss'] + selector: 'alfa-binary-file-container', + templateUrl: './binary-file-container.component.html', + styleUrls: ['./binary-file-container.component.scss'], }) export class BinaryFileContainerComponent { + @Input() file: BinaryFileResource; + @Input() downloadFileNamePrefix: string; + @Input() deletable: boolean = false; - @Input() file: BinaryFileResource; - @Input() downloadFileNamePrefix: string; - @Input() deletable: boolean = false; + @Output() startDelete: EventEmitter<BinaryFileResource> = new EventEmitter(); - @Output() startDelete: EventEmitter<BinaryFileResource> = new EventEmitter(); + fileStateResource$: Observable<StateResource<any>>; + downloadToken$: Observable<ApiDownloadToken>; - fileStateResource$: Observable<StateResource<any>> - downloadToken$: Observable<ApiDownloadToken>; + constructor( + private binaryFileService: BinaryFileService, + private apiRootService: ApiRootService, + ) {} - constructor( - private binaryFileService: BinaryFileService, - private apiRootService: ApiRootService) { } + startDownload(file: BinaryFileResource): void { + this.fileStateResource$ = this.binaryFileService.downloadFile( + file, + this.downloadFileNamePrefix, + ); + } - startDownload(file: BinaryFileResource): void { - this.fileStateResource$ = this.binaryFileService.downloadFile(file, this.downloadFileNamePrefix); - } - - getDownloadToken(): void { - this.downloadToken$ = this.apiRootService.getDownloadToken(this.file); - } + getDownloadToken(): void { + this.downloadToken$ = this.apiRootService.getDownloadToken(this.file); + } } diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/_binary-file.theme.scss b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/_binary-file.theme.scss index 91cdf4699a5f313d0e69d0c5c8443bb9f01ae7e9..e6d9065d440c325e320291030be9d8acf17d223f 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/_binary-file.theme.scss +++ b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/_binary-file.theme.scss @@ -22,29 +22,29 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ alfa-binary-file { - .container { - background-color: rgba(#000, 0.04); + .container { + background-color: rgba(#000, 0.04); - &:focus-within { - background-color: rgba(#000, 0.08); - } - } + &:focus-within { + background-color: rgba(#000, 0.08); + } + } - .size { - color: #666; - } + .size { + color: #666; + } } .dark alfa-binary-file { - .container { - background-color: rgba(#fff, 0.04); + .container { + background-color: rgba(#fff, 0.04); - &:focus-within { - background-color: rgba(#fff, 0.08); - } - } + &:focus-within { + background-color: rgba(#fff, 0.08); + } + } - .size { - color: #eee; - } -} \ No newline at end of file + .size { + color: #eee; + } +} diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.html index 7d8145ff264cae7adf203b8f92f4568e575ba536..d1c510213d046c8c2d3df788ef3fcea8fbeb2746 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.html +++ b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.html @@ -23,24 +23,45 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<div class="container" [class.deletable]="deletable" [matTooltip]="file.name" matTooltipClass="word-break"> +<div + class="container" + [class.deletable]="deletable" + [matTooltip]="file.name" + matTooltipClass="word-break" +> + <div + class="download-container" + [class.downloadable]="file | hasLink: fileLinkRel.DOWNLOAD" + draggable="true" + (dragstart)="dragStart($event)" + (dragend)="dragEnd($event)" + (mousedown)="getNewDownloadToken()" + > + <button + type="button" + class="file" + data-test-class="download-file-button" + [attr.aria-label]="'Anhang: Dateiname: ' + file.name" + [disabled]="isDisabled" + (click)="downloadFile()" + > + <mat-icon>file_present</mat-icon> + <span class="name">{{ file.name }}</span> + <span class="size" [innerHTML]="file.size | fileSize"></span> - <div class="download-container" [class.downloadable]="file | hasLink:fileLinkRel.DOWNLOAD" draggable="true" - (dragstart)="dragStart($event)" (dragend)="dragEnd($event)" (mousedown)="getNewDownloadToken()"> + <ozgcloud-spinner + [diameter]="22" + padding="0" + [stateResource]="getStateResource()" + class="spinner" + ></ozgcloud-spinner> + </button> + </div> - <button type="button" class="file" data-test-class="download-file-button" - [attr.aria-label]="'Anhang: Dateiname: ' + file.name" - [disabled]="isDisabled" - (click)="downloadFile()"> - - <mat-icon>file_present</mat-icon> - <span class="name">{{ file.name }}</span> - <span class="size" [innerHTML]="file.size | fileSize"></span> - - <ozgcloud-spinner [diameter]="22" padding="0" [stateResource]="getStateResource()" class="spinner"></ozgcloud-spinner> - </button> - - </div> - - <ozgcloud-icon-button-with-spinner *ngIf="deletable" icon="close" (clickEmitter)="deleteFile()" data-test-class="delete-file-button"></ozgcloud-icon-button-with-spinner> + <ozgcloud-icon-button-with-spinner + *ngIf="deletable" + icon="close" + (clickEmitter)="deleteFile()" + data-test-class="delete-file-button" + ></ozgcloud-icon-button-with-spinner> </div> diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.scss b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.scss index 8e240f33238c85813aec9d5d0ced579992755c91..fb3024df1b4d16d68a56c7751548f96af38dabbd 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.scss +++ b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.scss @@ -23,116 +23,116 @@ */ .container { - display: flex; - border-radius: 18px; - align-items: center; + display: flex; + border-radius: 18px; + align-items: center; } .download-container { - width: 100%; - pointer-events: none; - flex-shrink: 1; - overflow: hidden; - &.downloadable { - pointer-events: all; - .file { - cursor: pointer; - } - } + width: 100%; + pointer-events: none; + flex-shrink: 1; + overflow: hidden; + &.downloadable { + pointer-events: all; + .file { + cursor: pointer; + } + } } .file { - background-color: transparent; - padding: 0; - border-radius: 14px; - line-height: 26px; - white-space: nowrap; - display: flex; - align-items: center; - text-decoration: none; - color: inherit; - border: 0; - width: 100%; - cursor: auto; - - &:disabled { - cursor: auto; - pointer-events: none; - - .mat-icon { - visibility: hidden; - } - - .name, - .size { - opacity: 0.4; - } - } - - &:focus-within { - outline: 0; - } + background-color: transparent; + padding: 0; + border-radius: 14px; + line-height: 26px; + white-space: nowrap; + display: flex; + align-items: center; + text-decoration: none; + color: inherit; + border: 0; + width: 100%; + cursor: auto; + + &:disabled { + cursor: auto; + pointer-events: none; + + .mat-icon { + visibility: hidden; + } + + .name, + .size { + opacity: 0.4; + } + } + + &:focus-within { + outline: 0; + } } .mat-icon { - padding: 0 4px; - transform: scale(0.9); - display: flex; - align-items: center; - color: #888; + padding: 0 4px; + transform: scale(0.9); + display: flex; + align-items: center; + color: #888; } .name { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .size { - font-size: 12px; - flex-shrink: 0; - margin-right: 4px; - - ::ng-deep { - .unit { - margin-left: 2px; - } - } + font-size: 12px; + flex-shrink: 0; + margin-right: 4px; + + ::ng-deep { + .unit { + margin-left: 2px; + } + } } .mat-icon, .size, .name { - padding: 2px; + padding: 2px; } .spinner { - position: absolute; - top: 0; - left: 5px; - display: flex; - height: 100%; - width: 100%; - justify-content: flex-start; - align-items: center; + position: absolute; + top: 0; + left: 5px; + display: flex; + height: 100%; + width: 100%; + justify-content: flex-start; + align-items: center; } ozgcloud-icon-button-with-spinner { - display: block; - margin: -12px 0; + display: block; + margin: -12px 0; } .deletable { - .container { - border-radius: 16px; - } - - .file { - line-height: 32px; - } - - .mat-icon { - width: 32px; - padding: 6px; - } -} \ No newline at end of file + .container { + border-radius: 16px; + } + + .file { + line-height: 32px; + } + + .mat-icon { + width: 32px; + padding: 6px; + } +} diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.spec.ts index 1dc770bfd61b46f8f7d0af9bf126adc55f3d04e5..7accc9f495a262685793bd3e50f34d5b96bcf712 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.spec.ts @@ -28,132 +28,130 @@ import { ApiDownloadToken } from '@alfa-client/api-root-shared'; import { BinaryFileLinkRel, BinaryFileResource } from '@alfa-client/binary-file-shared'; import { createEmptyStateResource, FileSizePipe, HasLinkPipe } from '@alfa-client/tech-shared'; import { getElementFromFixture } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, MatTooltipDirective, SpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + MatTooltipDirective, + SpinnerComponent, +} from '@alfa-client/ui'; import { createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; import { getDataTestClassOf } from 'libs/tech-shared/test/data-test'; import { MockComponent, MockDirective } from 'ng-mocks'; import { BinaryFileComponent } from './binary-file.component'; describe('BinaryFileComponent', () => { - let component: BinaryFileComponent; - let fixture: ComponentFixture<BinaryFileComponent>; - - const file: BinaryFileResource = createBinaryFileResource([BinaryFileLinkRel.DOWNLOAD]); - const downloadButton: string = getDataTestClassOf('download-file-button'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - BinaryFileComponent, - MatIcon, - FileSizePipe, - HasLinkPipe, - MockDirective(MatTooltipDirective), - MockComponent(SpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent) - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(BinaryFileComponent); - component = fixture.componentInstance; - component.file = file; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('Button', () => { - it('should NOT disabled initial', () => { - component.stateResource = createEmptyStateResource(); - fixture.detectChanges(); - - const button = getElementFromFixture(fixture, downloadButton); - - expect(button).not.toBeDisabled() - }); - - it('should disabled if loading', () => { - component.stateResource = createEmptyStateResource(true); - fixture.detectChanges(); - - const button = getElementFromFixture(fixture, downloadButton); - - expect(button).toBeDisabled(); - }); - }) - - describe('click on download button', () => { - - it('should emit download if link exists', () => { - jest.spyOn(component.startDownload, 'emit'); - component.file = createBinaryFileResource([BinaryFileLinkRel.DOWNLOAD]); - - component.downloadFile(); - - expect(component.startDownload.emit).toHaveBeenCalledWith(component.file); - }) - }) - - describe('click and hold download button', () => { - - it('should call getNewDownloadToken', () => { - jest.spyOn(component.getDownloadToken, 'emit'); - component.file = createBinaryFileResource(); - - component.getNewDownloadToken(); - //TODO: Test mit onmousedown - //const button: HTMLElement = getElementFromFixture(fixture, buttonSelector); - //const mousedown = new MouseEvent('mousedown'); - //button.dispatchEvent(mousedown); - - expect(component.getDownloadToken.emit).toHaveBeenCalled(); - }); - - }); - - describe('click on delete button', () => { - - it('should emit delete', () => { - jest.spyOn(component.startDelete, 'emit'); - component.file = createBinaryFileResource(); - - component.deleteFile(); - - expect(component.startDelete.emit).toHaveBeenCalledWith(component.file); - }) - }) - - describe('create download url', () => { - - it('should return a DownloadURL', () => { - component.downloadToken = { token: faker.random.alpha({ count: 30 }) } as ApiDownloadToken; - const pattern = `^[^:]+:[^:]+:http.+\\?token=${component.downloadToken.token}$`; - const regex = new RegExp(pattern); - - const downloadUrl = component.createDownloadUrl(); - - expect(downloadUrl).toMatch(regex); - }); - }); - - describe('handle spinner for drag end', () => { - - it('should set state resource loading', () => { - component.handleSpinnerForDragEnd(); - - expect(component.stateResource.loading).toBeTruthy(); - }) - - it('should unset state resource loading', fakeAsync(() => { - component.handleSpinnerForDragEnd(); - - tick(3000); - - expect(component.stateResource.loading).toBeFalsy(); - })) - }) + let component: BinaryFileComponent; + let fixture: ComponentFixture<BinaryFileComponent>; + + const file: BinaryFileResource = createBinaryFileResource([BinaryFileLinkRel.DOWNLOAD]); + const downloadButton: string = getDataTestClassOf('download-file-button'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + BinaryFileComponent, + MatIcon, + FileSizePipe, + HasLinkPipe, + MockDirective(MatTooltipDirective), + MockComponent(SpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BinaryFileComponent); + component = fixture.componentInstance; + component.file = file; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('Button', () => { + it('should NOT disabled initial', () => { + component.stateResource = createEmptyStateResource(); + fixture.detectChanges(); + + const button = getElementFromFixture(fixture, downloadButton); + + expect(button).not.toBeDisabled(); + }); + + it('should disabled if loading', () => { + component.stateResource = createEmptyStateResource(true); + fixture.detectChanges(); + + const button = getElementFromFixture(fixture, downloadButton); + + expect(button).toBeDisabled(); + }); + }); + + describe('click on download button', () => { + it('should emit download if link exists', () => { + jest.spyOn(component.startDownload, 'emit'); + component.file = createBinaryFileResource([BinaryFileLinkRel.DOWNLOAD]); + + component.downloadFile(); + + expect(component.startDownload.emit).toHaveBeenCalledWith(component.file); + }); + }); + + describe('click and hold download button', () => { + it('should call getNewDownloadToken', () => { + jest.spyOn(component.getDownloadToken, 'emit'); + component.file = createBinaryFileResource(); + + component.getNewDownloadToken(); + //TODO: Test mit onmousedown + //const button: HTMLElement = getElementFromFixture(fixture, buttonSelector); + //const mousedown = new MouseEvent('mousedown'); + //button.dispatchEvent(mousedown); + + expect(component.getDownloadToken.emit).toHaveBeenCalled(); + }); + }); + + describe('click on delete button', () => { + it('should emit delete', () => { + jest.spyOn(component.startDelete, 'emit'); + component.file = createBinaryFileResource(); + + component.deleteFile(); + + expect(component.startDelete.emit).toHaveBeenCalledWith(component.file); + }); + }); + + describe('create download url', () => { + it('should return a DownloadURL', () => { + component.downloadToken = { token: faker.random.alpha({ count: 30 }) } as ApiDownloadToken; + const pattern = `^[^:]+:[^:]+:http.+\\?token=${component.downloadToken.token}$`; + const regex = new RegExp(pattern); + + const downloadUrl = component.createDownloadUrl(); + + expect(downloadUrl).toMatch(regex); + }); + }); + + describe('handle spinner for drag end', () => { + it('should set state resource loading', () => { + component.handleSpinnerForDragEnd(); + + expect(component.stateResource.loading).toBeTruthy(); + }); + + it('should unset state resource loading', fakeAsync(() => { + component.handleSpinnerForDragEnd(); + + tick(3000); + + expect(component.stateResource.loading).toBeFalsy(); + })); + }); }); diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.ts b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.ts index a0e350a254ca884cfe7fdfcebe318c8c07874153..a62077cd33ccb0ea50a9f6ae4bdaa1e47489f948 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file-container/binary-file/binary-file.component.ts @@ -30,75 +30,75 @@ import { getUrl, Resource } from '@ngxp/rest'; import { isEmpty, isNil } from 'lodash-es'; @Component({ - selector: 'alfa-binary-file', - templateUrl: './binary-file.component.html', - styleUrls: ['./binary-file.component.scss'] + selector: 'alfa-binary-file', + templateUrl: './binary-file.component.html', + styleUrls: ['./binary-file.component.scss'], }) export class BinaryFileComponent { - - @Input() file: BinaryFileResource; - @Input() stateResource: StateResource<Resource>; - @Input() deletable: boolean = false; - @Input() downloadToken: ApiDownloadToken = <ApiDownloadToken>{}; - - readonly fileLinkRel = BinaryFileLinkRel; - - @Output() public startDownload: EventEmitter<BinaryFileResource> = new EventEmitter<BinaryFileResource>(); - @Output() public startDelete: EventEmitter<BinaryFileResource> = new EventEmitter<BinaryFileResource>(); - @Output() public getDownloadToken: EventEmitter<void> = new EventEmitter<void>(); - - get isDisabled(): boolean { - return this.getStateResource().loading; - } - - getStateResource(): StateResource<Resource> { - return isNil(this.stateResource) ? createEmptyStateResource<Resource>() : this.stateResource; - } - - downloadFile(): void { - this.startDownload.emit(this.file); - } - - deleteFile(): void { - this.startDelete.emit(this.file); - } - - getNewDownloadToken(): void { - this.getDownloadToken.emit(); - } - - dragStart(event: DragEvent): void { - event.dataTransfer.setData('DownloadURL', this.createDownloadUrl()); - } - - dragEnd(event: DragEvent): void { - if (this.isValidDrop(event)) { - this.handleSpinnerForDragEnd(); - } - } - - private isValidDrop(event: DragEvent): boolean { - return event.dataTransfer.dropEffect !== 'none'; - } - - handleSpinnerForDragEnd(): void { - this.stateResource = { ...this.stateResource, loading: true }; - setTimeout(() => this.stateResource = { ...this.stateResource, loading: false }, 3000); - } - - createDownloadUrl(): string { - return `${this.getContentType()}:${this.file.name}:${this.createRemoteUrl()}`; - } - - private getContentType(): string { - return isEmpty(this.file.contentType) ? 'application/octet-stream' : this.file.contentType; - } - - private createRemoteUrl(): string { - let getParam = new HttpParams(); - getParam = getParam.set('token', this.downloadToken?.token); - - return getUrl(this.file, BinaryFileLinkRel.DOWNLOAD) + '?' + getParam.toString(); - } - + @Input() file: BinaryFileResource; + @Input() stateResource: StateResource<Resource>; + @Input() deletable: boolean = false; + @Input() downloadToken: ApiDownloadToken = <ApiDownloadToken>{}; + + readonly fileLinkRel = BinaryFileLinkRel; + + @Output() public startDownload: EventEmitter<BinaryFileResource> = + new EventEmitter<BinaryFileResource>(); + @Output() public startDelete: EventEmitter<BinaryFileResource> = + new EventEmitter<BinaryFileResource>(); + @Output() public getDownloadToken: EventEmitter<void> = new EventEmitter<void>(); + + get isDisabled(): boolean { + return this.getStateResource().loading; + } + + getStateResource(): StateResource<Resource> { + return isNil(this.stateResource) ? createEmptyStateResource<Resource>() : this.stateResource; + } + + downloadFile(): void { + this.startDownload.emit(this.file); + } + + deleteFile(): void { + this.startDelete.emit(this.file); + } + + getNewDownloadToken(): void { + this.getDownloadToken.emit(); + } + + dragStart(event: DragEvent): void { + event.dataTransfer.setData('DownloadURL', this.createDownloadUrl()); + } + + dragEnd(event: DragEvent): void { + if (this.isValidDrop(event)) { + this.handleSpinnerForDragEnd(); + } + } + + private isValidDrop(event: DragEvent): boolean { + return event.dataTransfer.dropEffect !== 'none'; + } + + handleSpinnerForDragEnd(): void { + this.stateResource = { ...this.stateResource, loading: true }; + setTimeout(() => (this.stateResource = { ...this.stateResource, loading: false }), 3000); + } + + createDownloadUrl(): string { + return `${this.getContentType()}:${this.file.name}:${this.createRemoteUrl()}`; + } + + private getContentType(): string { + return isEmpty(this.file.contentType) ? 'application/octet-stream' : this.file.contentType; + } + + private createRemoteUrl(): string { + let getParam = new HttpParams(); + getParam = getParam.set('token', this.downloadToken?.token); + + return getUrl(this.file, BinaryFileLinkRel.DOWNLOAD) + '?' + getParam.toString(); + } } diff --git a/alfa-client/libs/binary-file/src/lib/binary-file.module.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file.module.spec.ts index 9b10852397184a17bfb6c3dec186ec3f61486f49..cb37386bd65e4e048e29a11dfbb3fa8d61a1f48d 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file.module.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { BinaryFileModule } from './binary-file.module'; describe('BinaryFileModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [BinaryFileModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [BinaryFileModule], + }).compileComponents(); + }); - it('should create', () => { - expect(BinaryFileModule).toBeDefined(); - }); + it('should create', () => { + expect(BinaryFileModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/binary-file/src/lib/binary-file.module.ts b/alfa-client/libs/binary-file/src/lib/binary-file.module.ts index ebad687a1a58fd86acef3b391bae2736245acc88..b71b9994e43c405867bafdc5a0f597ffcb605bfa 100644 --- a/alfa-client/libs/binary-file/src/lib/binary-file.module.ts +++ b/alfa-client/libs/binary-file/src/lib/binary-file.module.ts @@ -32,23 +32,19 @@ import { HorizontalBinaryFileListComponent } from './horizontal-binary-file-list import { VerticalBinaryFileListComponent } from './vertical-binary-file-list/vertical-binary-file-list.component'; @NgModule({ - imports: [ - CommonModule, - UiModule, - TechSharedModule - ], - declarations: [ - BinaryFileAttachmentContainerComponent, - BinaryFileComponent, - BinaryFileContainerComponent, - HorizontalBinaryFileListComponent, - VerticalBinaryFileListComponent - ], - exports: [ - BinaryFileAttachmentContainerComponent, - BinaryFileContainerComponent, - HorizontalBinaryFileListComponent, - VerticalBinaryFileListComponent - ] + imports: [CommonModule, UiModule, TechSharedModule], + declarations: [ + BinaryFileAttachmentContainerComponent, + BinaryFileComponent, + BinaryFileContainerComponent, + HorizontalBinaryFileListComponent, + VerticalBinaryFileListComponent, + ], + exports: [ + BinaryFileAttachmentContainerComponent, + BinaryFileContainerComponent, + HorizontalBinaryFileListComponent, + VerticalBinaryFileListComponent, + ], }) -export class BinaryFileModule { } \ No newline at end of file +export class BinaryFileModule {} diff --git a/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.html b/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.html index 07f0939e478bb347b741daaf9fa2fb011f0c200d..ba9f2eb0dc3b447bba2908a1795658f98d767837 100644 --- a/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.html +++ b/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.html @@ -24,13 +24,15 @@ --> <ozgcloud-spinner [stateResource]="fileListResource"> - - <div class="horizontal" data-test-id="file-list"> - <alfa-binary-file-container - *ngFor="let binaryFileResource of (fileListResource.resource | toEmbeddedResources: fileListRel.FILE_LIST)" - [file]="binaryFileResource" - [deletable]="deletable"> - </alfa-binary-file-container> - </div> - -</ozgcloud-spinner> \ No newline at end of file + <div class="horizontal" data-test-id="file-list"> + <alfa-binary-file-container + *ngFor=" + let binaryFileResource of fileListResource.resource + | toEmbeddedResources: fileListRel.FILE_LIST + " + [file]="binaryFileResource" + [deletable]="deletable" + > + </alfa-binary-file-container> + </div> +</ozgcloud-spinner> diff --git a/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.scss b/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.scss index a21d4ffd42a97a55201dc3370cb827aa7d22e56c..2967debdeaf89c2589a854e7b623805847557bd6 100644 --- a/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.scss +++ b/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.scss @@ -22,8 +22,8 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .horizontal { - max-width: 100%; - display: inline-flex; - flex-wrap: wrap; - gap: 4px; -} \ No newline at end of file + max-width: 100%; + display: inline-flex; + flex-wrap: wrap; + gap: 4px; +} diff --git a/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.spec.ts b/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.spec.ts index 8d47e82adb9df5e77ffd6ff0e651550bd053e75c..c11e5848f4f6210a01cad17d9f77eaf969964e22 100644 --- a/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.spec.ts @@ -29,28 +29,28 @@ import { BinaryFileContainerComponent } from './../binary-file-container/binary- import { HorizontalBinaryFileListComponent } from './horizontal-binary-file-list.component'; describe('HorizontalBinaryFileListComponent', () => { - let component: HorizontalBinaryFileListComponent; - let fixture: ComponentFixture<HorizontalBinaryFileListComponent>; + let component: HorizontalBinaryFileListComponent; + let fixture: ComponentFixture<HorizontalBinaryFileListComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HorizontalBinaryFileListComponent, - ToEmbeddedResourcesPipe, - MockComponent(BinaryFileContainerComponent), - MockComponent(SpinnerComponent) - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HorizontalBinaryFileListComponent, + ToEmbeddedResourcesPipe, + MockComponent(BinaryFileContainerComponent), + MockComponent(SpinnerComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HorizontalBinaryFileListComponent); - component = fixture.componentInstance; - component.fileListResource = createEmptyStateResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HorizontalBinaryFileListComponent); + component = fixture.componentInstance; + component.fileListResource = createEmptyStateResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.ts b/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.ts index c434898df4b4db85834df88cd785df79a40e853a..7548eeafe9af4b857e981e10ac5d56e200ae3883 100644 --- a/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.ts +++ b/alfa-client/libs/binary-file/src/lib/horizontal-binary-file-list/horizontal-binary-file-list.component.ts @@ -26,14 +26,14 @@ import { BinaryFileListLinkRel, BinaryFileListResource } from '@alfa-client/bina import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-horizontal-binary-file-list', - templateUrl: './horizontal-binary-file-list.component.html', - styleUrls: ['./horizontal-binary-file-list.component.scss'] + selector: 'alfa-horizontal-binary-file-list', + templateUrl: './horizontal-binary-file-list.component.html', + styleUrls: ['./horizontal-binary-file-list.component.scss'], }) export class HorizontalBinaryFileListComponent { + @Input() fileListResource: StateResource<BinaryFileListResource> = + createEmptyStateResource<BinaryFileListResource>(); + @Input() deletable: boolean = false; - @Input() fileListResource: StateResource<BinaryFileListResource> = createEmptyStateResource<BinaryFileListResource>(); - @Input() deletable: boolean = false; - - readonly fileListRel = BinaryFileListLinkRel; -} \ No newline at end of file + readonly fileListRel = BinaryFileListLinkRel; +} diff --git a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.html b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.html index b262532f32de1f54cac47d19917fc4b92ac45f96..fbea31c02eff3f5d30abd9cf1c1ff7a73447f716 100644 --- a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.html +++ b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.html @@ -24,11 +24,16 @@ --> <ozgcloud-spinner [stateResource]="fileListResource"> - <div class="vertical" data-test-id="file-list"> - <alfa-binary-file-container - *ngFor="let binaryFileResource of fileListResource.resource | toEmbeddedResources: fileListRel.FILE_LIST" - [file]="binaryFileResource" [deletable]="deletable" - [downloadFileNamePrefix]="downloadFileNamePrefix"> - </alfa-binary-file-container> - </div> + <div class="vertical" data-test-id="file-list"> + <alfa-binary-file-container + *ngFor=" + let binaryFileResource of fileListResource.resource + | toEmbeddedResources: fileListRel.FILE_LIST + " + [file]="binaryFileResource" + [deletable]="deletable" + [downloadFileNamePrefix]="downloadFileNamePrefix" + > + </alfa-binary-file-container> + </div> </ozgcloud-spinner> diff --git a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.scss b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.scss index 2913e5e2bc5e6cfeee0a366c3991351da7966725..1212c1617eca6dd57a7d70ae7069d282a3611ea7 100644 --- a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.scss +++ b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.scss @@ -22,10 +22,10 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .vertical { - display: flex; - flex-direction: column; - max-width: 100%; - align-items: flex-start; - margin: 0 -4px; - margin-top: 1rem; -} \ No newline at end of file + display: flex; + flex-direction: column; + max-width: 100%; + align-items: flex-start; + margin: 0 -4px; + margin-top: 1rem; +} diff --git a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.spec.ts b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.spec.ts index aaccaae9f42825ff64e7deb279181e8bac399d5b..07c0a783352ebfa2a91827c1216b71ca1736baae 100644 --- a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.spec.ts +++ b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.spec.ts @@ -29,28 +29,28 @@ import { BinaryFileContainerComponent } from './../binary-file-container/binary- import { VerticalBinaryFileListComponent } from './vertical-binary-file-list.component'; describe('VerticalBinaryFileListComponent', () => { - let component: VerticalBinaryFileListComponent; - let fixture: ComponentFixture<VerticalBinaryFileListComponent>; + let component: VerticalBinaryFileListComponent; + let fixture: ComponentFixture<VerticalBinaryFileListComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VerticalBinaryFileListComponent, - ToEmbeddedResourcesPipe, - MockComponent(BinaryFileContainerComponent), - MockComponent(SpinnerComponent) - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VerticalBinaryFileListComponent, + ToEmbeddedResourcesPipe, + MockComponent(BinaryFileContainerComponent), + MockComponent(SpinnerComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VerticalBinaryFileListComponent); - component = fixture.componentInstance; - component.fileListResource = createEmptyStateResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VerticalBinaryFileListComponent); + component = fixture.componentInstance; + component.fileListResource = createEmptyStateResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.ts b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.ts index aee772b2e0025368f11a33407ad829f37d79eb33..3eb9096547a466caf4ac3b11ee935f728bee1745 100644 --- a/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.ts +++ b/alfa-client/libs/binary-file/src/lib/vertical-binary-file-list/vertical-binary-file-list.component.ts @@ -26,15 +26,15 @@ import { BinaryFileListLinkRel, BinaryFileListResource } from '@alfa-client/bina import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-vertical-binary-file-list', - templateUrl: './vertical-binary-file-list.component.html', - styleUrls: ['./vertical-binary-file-list.component.scss'], + selector: 'alfa-vertical-binary-file-list', + templateUrl: './vertical-binary-file-list.component.html', + styleUrls: ['./vertical-binary-file-list.component.scss'], }) export class VerticalBinaryFileListComponent { + @Input() fileListResource: StateResource<BinaryFileListResource> = + createEmptyStateResource<BinaryFileListResource>(); + @Input() downloadFileNamePrefix: string; + @Input() deletable: boolean = false; - @Input() fileListResource: StateResource<BinaryFileListResource> = createEmptyStateResource<BinaryFileListResource>(); - @Input() downloadFileNamePrefix: string; - @Input() deletable: boolean = false; - - readonly fileListRel = BinaryFileListLinkRel; -} \ No newline at end of file + readonly fileListRel = BinaryFileListLinkRel; +} diff --git a/alfa-client/libs/binary-file/src/test-setup.ts b/alfa-client/libs/binary-file/src/test-setup.ts index dc74cf29206a7ce287ef667322818782b2ba86b4..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/binary-file/src/test-setup.ts +++ b/alfa-client/libs/binary-file/src/test-setup.ts @@ -25,15 +25,14 @@ import '@testing-library/jest-dom'; import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/binary-file/tsconfig.json b/alfa-client/libs/binary-file/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/binary-file/tsconfig.json +++ b/alfa-client/libs/binary-file/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/binary-file/tsconfig.lib.json b/alfa-client/libs/binary-file/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/binary-file/tsconfig.lib.json +++ b/alfa-client/libs/binary-file/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/binary-file/tsconfig.spec.json b/alfa-client/libs/binary-file/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/binary-file/tsconfig.spec.json +++ b/alfa-client/libs/binary-file/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/command-shared/.eslintrc.json b/alfa-client/libs/command-shared/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/command-shared/.eslintrc.json +++ b/alfa-client/libs/command-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/command-shared/jest.config.ts b/alfa-client/libs/command-shared/jest.config.ts index 92848bb9669f53801488465236e528c95df973f7..4e577294c16792b942ad085344e4a20fc0647029 100644 --- a/alfa-client/libs/command-shared/jest.config.ts +++ b/alfa-client/libs/command-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'command-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/command-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'command-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/command-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/command-shared/project.json b/alfa-client/libs/command-shared/project.json index d9465c5137493e19adb4816ad82cff356330e938..a542bb015df57ab9cb82bfbb86f261d4a85744ee 100644 --- a/alfa-client/libs/command-shared/project.json +++ b/alfa-client/libs/command-shared/project.json @@ -1,34 +1,31 @@ { - "name": "command-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/command-shared/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/command-shared/src/**/*.ts", - "libs/command-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/command-shared/tsconfig.spec.json", - "jestConfig": "libs/command-shared/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/command-shared"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "command-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/command-shared/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/command-shared/src/**/*.ts", "libs/command-shared/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/command-shared/tsconfig.spec.json", + "jestConfig": "libs/command-shared/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/command-shared"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/command-shared/src/lib/+state/command.actions.ts b/alfa-client/libs/command-shared/src/lib/+state/command.actions.ts index 64dff05f17713b9505ba72555c1c2b1c88f812eb..a2b1275623715c695aaba76ce95e90c7f9740ba8 100644 --- a/alfa-client/libs/command-shared/src/lib/+state/command.actions.ts +++ b/alfa-client/libs/command-shared/src/lib/+state/command.actions.ts @@ -21,57 +21,101 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { ApiError, ApiErrorAction, StateResource, TypedActionCreator, TypedActionCreatorWithProps } from '@alfa-client/tech-shared'; +import { + ApiError, + ApiErrorAction, + StateResource, + TypedActionCreator, + TypedActionCreatorWithProps, +} from '@alfa-client/tech-shared'; import { createAction, props } from '@ngrx/store'; import { TypedAction } from '@ngrx/store/src/models'; import { Resource } from '@ngxp/rest'; -import { CommandListResource, CommandResource, CreateCommand, CreateCommandProps } from '../command.model'; +import { + CommandListResource, + CommandResource, + CreateCommand, + CreateCommandProps, +} from '../command.model'; -export const publishConcurrentModificationAction: TypedActionCreator = createAction('[Command/API] Concurrent Modification'); +export const publishConcurrentModificationAction: TypedActionCreator = createAction( + '[Command/API] Concurrent Modification', +); export interface CommandStateResourceProps { - commandStateResource: StateResource<CommandResource> + commandStateResource: StateResource<CommandResource>; } export interface LoadCommandListSuccessProps { - commandList: CommandListResource + commandList: CommandListResource; } export interface LoadCommandListProps { - resource: Resource, - linkRel: string, - successAction: (commandList: CommandListResource) => LoadCommandListSuccessProps & TypedAction<string>, - failureAction: (apiError: ApiError) => ApiErrorAction & TypedAction<string> + resource: Resource; + linkRel: string; + successAction: ( + commandList: CommandListResource, + ) => LoadCommandListSuccessProps & TypedAction<string>; + failureAction: (apiError: ApiError) => ApiErrorAction & TypedAction<string>; } -export const loadCommandList: TypedActionCreatorWithProps<LoadCommandListProps> = createAction('[Command] Load pending commands', props<LoadCommandListProps>()); +export const loadCommandList: TypedActionCreatorWithProps<LoadCommandListProps> = createAction( + '[Command] Load pending commands', + props<LoadCommandListProps>(), +); export interface CommandProps { - command: CommandResource + command: CommandResource; } export interface PollCommandProps { - command: CommandResource + command: CommandResource; } export interface RevokeCommandFailureProps { - command: CommandResource, - error: ApiError | unknown + command: CommandResource; + error: ApiError | unknown; } export interface CreateCommandFailureProps { - command: CreateCommand, - error: ApiError | unknown + command: CreateCommand; + error: ApiError | unknown; } -export const createCommand: TypedActionCreatorWithProps<CreateCommandProps> = createAction('[Command] Create command', props<CreateCommandProps>()); -export const createCommandSuccess: TypedActionCreatorWithProps<CommandProps> = createAction('[Command] Create command Success', props<CommandProps>()); -export const createCommandFailure: TypedActionCreatorWithProps<CreateCommandFailureProps> = createAction('[Command] Create command Failure', props<CreateCommandFailureProps>()); -export const pollCreatedCommand: TypedActionCreatorWithProps<PollCommandProps> = createAction('[Command] Poll created command', props<PollCommandProps>()); +export const createCommand: TypedActionCreatorWithProps<CreateCommandProps> = createAction( + '[Command] Create command', + props<CreateCommandProps>(), +); +export const createCommandSuccess: TypedActionCreatorWithProps<CommandProps> = createAction( + '[Command] Create command Success', + props<CommandProps>(), +); +export const createCommandFailure: TypedActionCreatorWithProps<CreateCommandFailureProps> = + createAction('[Command] Create command Failure', props<CreateCommandFailureProps>()); +export const pollCreatedCommand: TypedActionCreatorWithProps<PollCommandProps> = createAction( + '[Command] Poll created command', + props<PollCommandProps>(), +); -export const showRevokeSnackbar: TypedActionCreatorWithProps<CommandProps> = createAction('[Command] Show Revoke Snackbar', props<CommandProps>()); -export const showSnackbar: TypedActionCreatorWithProps<CommandProps> = createAction('[Command] Show Snackbar', props<CommandProps>()); +export const showRevokeSnackbar: TypedActionCreatorWithProps<CommandProps> = createAction( + '[Command] Show Revoke Snackbar', + props<CommandProps>(), +); +export const showSnackbar: TypedActionCreatorWithProps<CommandProps> = createAction( + '[Command] Show Snackbar', + props<CommandProps>(), +); -export const revokeCommand: TypedActionCreatorWithProps<CommandProps> = createAction('[Command] Revoke command', props<CommandProps>()); -export const revokeCommandSuccess: TypedActionCreatorWithProps<CommandProps> = createAction('[Command] Revoke command Success', props<CommandProps>()); -export const revokeCommandFailure: TypedActionCreatorWithProps<RevokeCommandFailureProps> = createAction('[Command] Revoke command Failure', props<RevokeCommandFailureProps>()); -export const pollRevokedCommand: TypedActionCreatorWithProps<PollCommandProps> = createAction('[Command] Poll revoked command', props<PollCommandProps>()); \ No newline at end of file +export const revokeCommand: TypedActionCreatorWithProps<CommandProps> = createAction( + '[Command] Revoke command', + props<CommandProps>(), +); +export const revokeCommandSuccess: TypedActionCreatorWithProps<CommandProps> = createAction( + '[Command] Revoke command Success', + props<CommandProps>(), +); +export const revokeCommandFailure: TypedActionCreatorWithProps<RevokeCommandFailureProps> = + createAction('[Command] Revoke command Failure', props<RevokeCommandFailureProps>()); +export const pollRevokedCommand: TypedActionCreatorWithProps<PollCommandProps> = createAction( + '[Command] Poll revoked command', + props<PollCommandProps>(), +); diff --git a/alfa-client/libs/command-shared/src/lib/+state/command.effects.spec.ts b/alfa-client/libs/command-shared/src/lib/+state/command.effects.spec.ts index c90ed3ac4c44e43b28cb726b603800d46610d919..ab275cec4c942927c5b2c1e366ff9005932fdcac 100644 --- a/alfa-client/libs/command-shared/src/lib/+state/command.effects.spec.ts +++ b/alfa-client/libs/command-shared/src/lib/+state/command.effects.spec.ts @@ -9,7 +9,11 @@ import { provideMockStore } from '@ngrx/store/testing'; import { Resource } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; import { ColdObservable } from 'jest-marbles/typings/src/rxjs/cold-observable'; -import { createCommand, createCommandListResource, createCommandResource } from 'libs/command-shared/test/command'; +import { + createCommand, + createCommandListResource, + createCommandResource, +} from 'libs/command-shared/test/command'; import { createApiError } from 'libs/tech-shared/test/error'; import { Observable, of } from 'rxjs'; import { TestScheduler } from 'rxjs/testing'; @@ -23,346 +27,374 @@ import { CommandEffects } from './command.effects'; import * as CommandActions from './command.actions'; describe('CommandEffects', () => { - let actions: Observable<Action>; - let effects: CommandEffects; + let actions: Observable<Action>; + let effects: CommandEffects; + + const repository: Mock<CommandRepository> = mock(CommandRepository); + const snackBarService: Mock<SnackBarService> = mock(SnackBarService); + const store: Mock<SnackBarService> = mock(SnackBarService); + + let testScheduler: TestScheduler; + + beforeEach(() => { + testScheduler = new TestScheduler((actual, expected) => expect(actual).toEqual(expected)); + + TestBed.configureTestingModule({ + providers: [ + CommandEffects, + provideMockActions(() => actions), + provideMockStore(), + { + provide: CommandRepository, + useValue: repository, + }, + { + provide: SnackBarService, + useValue: snackBarService, + }, + { + provide: Store, + useValue: store, + }, + ], + }); + + effects = TestBed.inject(CommandEffects); + }); + + describe('loadCommandList', () => { + const resource: Resource = createCommandResource(); + const linkRel: string = 'LinkRelationOfResource'; + + const loadSuccess: TypedActionCreatorWithProps<LoadCommandListSuccessProps> = createAction( + '[Test Action] Load Success', + props<LoadCommandListSuccessProps>(), + ); + const loadFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[Test Action] Load Failure', + props<ApiErrorAction>(), + ); + + const loadCommandList: TypedAction<string> = CommandActions.loadCommandList({ + resource, + linkRel, + successAction: (commandList) => loadSuccess({ commandList }), + failureAction: (apiError) => loadFailure({ apiError }), + }); + + const commandListResource: CommandListResource = createCommandListResource(); + + beforeEach(() => { + repository.getPendingCommands.mockReturnValue(of(commandListResource)); + }); + + it('should call repository', () => { + actions = of(loadCommandList); + + effects.loadCommandList$.subscribe(); - const repository: Mock<CommandRepository> = mock(CommandRepository); - const snackBarService: Mock<SnackBarService> = mock(SnackBarService); - const store: Mock<SnackBarService> = mock(SnackBarService); + expect(repository.getPendingCommands).toHaveBeenCalledWith(resource, linkRel); + }); + + it('should dispatch success action on no error', () => { + actions = hot('-a', { a: loadCommandList }); + + const expected: ColdObservable = cold('-b', { + b: loadSuccess({ commandList: commandListResource }), + }); + expect(effects.loadCommandList$).toBeObservable(expected); + }); - let testScheduler: TestScheduler; + it('should dispatch failure action on error', () => { + const apiError: ApiError = createApiError(); + const error = { error: apiError }; + const errorResponse = cold('-#', {}, error); + repository.getPendingCommands = jest.fn(() => errorResponse); + + actions = hot('-a', { a: loadCommandList }); + + const expected: ColdObservable = cold('--b', { b: loadFailure({ apiError }) }); + expect(effects.loadCommandList$).toBeObservable(expected); + }); + }); - beforeEach(() => { - testScheduler = new TestScheduler((actual, expected) => expect(actual).toEqual(expected)); + describe('createCommand', () => { + const resource: Resource = createCommandResource(); + const linkRel: string = 'LinkRelationOfResource'; + const command: CreateCommand = createCommand(); + + const createCommandAction: TypedAction<string> = CommandActions.createCommand({ + resource, + linkRel, + command, + }); + + const commandResource: CommandResource = createCommandResource(); + + beforeEach(() => { + repository.createCommand.mockReturnValue(of(commandResource)); + }); + + it('should call repository', () => { + actions = of(createCommandAction); + + effects.createCommand$.subscribe(); + + expect(repository.createCommand).toHaveBeenCalledWith(resource, linkRel, command); + }); + + it('should handle createdCommand on success', () => { + effects.handleCreatedCommand = jest.fn(); + + actions = of(createCommandAction); + + effects.createCommand$.subscribe(); - TestBed.configureTestingModule({ - providers: [ - CommandEffects, - provideMockActions(() => actions), - provideMockStore(), - { - provide: CommandRepository, - useValue: repository - }, - { - provide: SnackBarService, - useValue: snackBarService - }, - { - provide: Store, - useValue: store - } - ], - }); + expect(effects.handleCreatedCommand).toHaveBeenCalledWith(commandResource); + }); - effects = TestBed.inject(CommandEffects); - }); + it('should dispatch failure action on error', () => { + const error = { error: {} }; + const errorResponse = cold('-#', {}, error); + repository.createCommand = jest.fn(() => errorResponse); - describe('loadCommandList', () => { + actions = hot('-a', { a: createCommandAction }); - const resource: Resource = createCommandResource(); - const linkRel: string = 'LinkRelationOfResource'; + const expected: ColdObservable = cold('--b', { + b: CommandActions.createCommandFailure({ error, command }), + }); + expect(effects.createCommand$).toBeObservable(expected); + }); + }); - const loadSuccess: TypedActionCreatorWithProps<LoadCommandListSuccessProps> = createAction('[Test Action] Load Success', props<LoadCommandListSuccessProps>()); - const loadFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Test Action] Load Failure', props<ApiErrorAction>()); + describe('handleCreatedCommand', () => { + it('should return pollCreatedCommand action on pending command', () => { + const command: CommandResource = createCommandResource([CommandLinkRel.UPDATE]); - const loadCommandList: TypedAction<string> = CommandActions.loadCommandList({ resource, linkRel, successAction: (commandList) => loadSuccess({ commandList }), failureAction: (apiError) => loadFailure({ apiError })}); + const actions: TypedAction<string>[] = effects.handleCreatedCommand(command); - const commandListResource: CommandListResource = createCommandListResource(); + expect(actions.length).toBe(1); + expect(actions[0].type).toBe(CommandActions.pollCreatedCommand.type); + expect((<any>actions[0]).command).toBe(command); + }); - beforeEach(() => { - repository.getPendingCommands.mockReturnValue(of(commandListResource)); - }) + it('should call handleCreateCommandSuccess on NOT pending command', () => { + effects.handleCreateCommandSuccess = jest.fn(); + const command: CommandResource = createCommandResource(); - it('should call repository', () => { - actions = of(loadCommandList); + effects.handleCreatedCommand(command); - effects.loadCommandList$.subscribe(); + expect(effects.handleCreateCommandSuccess).toHaveBeenCalledWith(command); + }); + }); - expect(repository.getPendingCommands).toHaveBeenCalledWith(resource, linkRel); - }); + describe.skip('FIXME: pollCreatedCommand', () => { + const delay: string = CommandEffects.POLL_DELAY + 'ms'; - it('should dispatch success action on no error', () => { - actions = hot('-a', { a: loadCommandList }); + const command: CommandResource = createCommandResource(); - const expected: ColdObservable = cold('-b', { b: loadSuccess({ commandList: commandListResource })}); - expect(effects.loadCommandList$).toBeObservable(expected); - }); + const pollCreateCommandAction: TypedAction<string> = CommandActions.pollCreatedCommand({ + command, + }); + + beforeEach(() => { + repository.getCommand.mockReturnValue(of(command)); + }); - it('should dispatch failure action on error', () => { - const apiError: ApiError = createApiError() - const error = { error: apiError }; - const errorResponse = cold('-#', {}, error); - repository.getPendingCommands = jest.fn(() => errorResponse); + it('should call repository', () => { + actions = hot('-a', { a: pollCreateCommandAction }); - actions = hot('-a', { a: loadCommandList }); + effects.pollCreatedCommand$.subscribe(() => { + console.info('Call repo!?'); + // expect(repository.getCommand).toHaveBeenCalledWith(command); + fail(); + }); + }); - const expected: ColdObservable = cold('--b', { b: loadFailure({ apiError }) }); - expect(effects.loadCommandList$).toBeObservable(expected); - }) - }); + it('should handle createdCommand on no error and pending command', () => { + // testScheduler.run((helpers) => { + // const { hot, cold } = helpers; + repository.getCommand.mockReturnValue(cold('-b|', { b: command })); - describe('createCommand', () => { + effects.handleCreatedCommand = jest.fn(); - const resource: Resource = createCommandResource(); - const linkRel: string = 'LinkRelationOfResource'; - const command: CreateCommand = createCommand(); + actions = hot('-a', { a: pollCreateCommandAction }); - const createCommandAction: TypedAction<string> = CommandActions.createCommand({ resource, linkRel, command }); + effects.createCommand$.subscribe(() => { + console.info('Call handleCreatedCommand!?'); + expect(effects.handleCreatedCommand).toHaveBeenCalledWith(command); + }); + // }); + }); - const commandResource: CommandResource = createCommandResource(); + it('should dispatch failure action on error', () => { + testScheduler.run((helpers) => { + const { hot, cold, expectObservable } = helpers; + const error = { error: {} }; + const errorResponse = cold('-#', {}, error); + repository.getCommand = jest.fn(() => errorResponse); - beforeEach(() => { - repository.createCommand.mockReturnValue(of(commandResource)); - }) + actions = hot('-a', { a: pollCreateCommandAction }); - it('should call repository', () => { - actions = of(createCommandAction); + expectObservable(effects.pollCreatedCommand$).toBe(delay + ' --c', { + c: createCommandFailure({ command, error }), + }); + }); + }); + }); - effects.createCommand$.subscribe(); + describe('handleCreateCommandSuccess', () => { + it('should return createCommandSuccess action and showSnackbar', () => { + const command: CommandResource = createCommandResource(); - expect(repository.createCommand).toHaveBeenCalledWith(resource, linkRel, command); - }); + const actions: TypedAction<string>[] = effects.handleCreateCommandSuccess(command); - it('should handle createdCommand on success', () => { - effects.handleCreatedCommand = jest.fn(); + expect(actions.length).toBe(2); + expect(actions[0].type).toBe(CommandActions.createCommandSuccess.type); + expect((<any>actions[0]).command).toBe(command); + expect(actions[1].type).toBe(CommandActions.showSnackbar.type); + expect((<any>actions[1]).command).toBe(command); + }); - actions = of(createCommandAction); + it('should return createCommandSuccess action and showRevokeSnackbar on revokeable command', () => { + const command: CommandResource = createCommandResource([CommandLinkRel.REVOKE]); - effects.createCommand$.subscribe(); + const actions: TypedAction<string>[] = effects.handleCreateCommandSuccess(command); - expect(effects.handleCreatedCommand).toHaveBeenCalledWith(commandResource); - }) + expect(actions.length).toBe(2); + expect(actions[0].type).toBe(CommandActions.createCommandSuccess.type); + expect((<any>actions[0]).command).toBe(command); + expect(actions[1].type).toBe(CommandActions.showRevokeSnackbar.type); + expect((<any>actions[1]).command).toBe(command); + }); - it('should dispatch failure action on error', () => { - const error = { error: {} }; - const errorResponse = cold('-#', {}, error); - repository.createCommand = jest.fn(() => errorResponse); + describe('on error', () => { + it('should show snackbar with error', () => { + const command: CommandResource = { + ...createCommandResource(), + errorMessage: CommandErrorMessage.CONCURRENT_MODIFICATION, + }; - actions = hot('-a', { a: createCommandAction }); + effects.handleCreateCommandSuccess(command); - const expected: ColdObservable = cold('--b', { b: CommandActions.createCommandFailure({ error, command }) }); - expect(effects.createCommand$).toBeObservable(expected); - }) - }); + expect(snackBarService.showError).toHaveBeenCalledWith( + 'Der Vorgang wurde zwischenzeitlich verändert und wurde neu geladen.', + ); + }); - describe('handleCreatedCommand', () => { + it('should return createCommandSuccess and publishConcurrentModificationAction', () => { + const command: CommandResource = { + ...createCommandResource(), + errorMessage: CommandErrorMessage.CONCURRENT_MODIFICATION, + }; - it('should return pollCreatedCommand action on pending command', () => { - const command: CommandResource = createCommandResource([CommandLinkRel.UPDATE]); + const actions: TypedAction<string>[] = effects.handleCreateCommandSuccess(command); - const actions: TypedAction<string>[] = effects.handleCreatedCommand(command); + expect(actions.length).toBe(2); + expect(actions[0].type).toBe(CommandActions.createCommandSuccess.type); + expect((<any>actions[0]).command).toBe(command); + expect(actions[1].type).toBe(CommandActions.publishConcurrentModificationAction.type); + }); + }); + }); - expect(actions.length).toBe(1); - expect(actions[0].type).toBe(CommandActions.pollCreatedCommand.type); - expect((<any>actions[0]).command).toBe(command); - }) + describe('showRevokeSnackbar', () => { + const command: CommandResource = createCommandResource(); - it('should call handleCreateCommandSuccess on NOT pending command', () => { - effects.handleCreateCommandSuccess = jest.fn(); - const command: CommandResource = createCommandResource(); + const showRevokeSnackbarAction: TypedAction<string> = CommandActions.showRevokeSnackbar({ + command, + }); - effects.handleCreatedCommand(command); + it('should show snackbar', () => { + actions = of(showRevokeSnackbarAction); - expect(effects.handleCreateCommandSuccess).toHaveBeenCalledWith(command); - }) - }) + effects.showRevokeSnackbar$.subscribe(); - describe.skip('FIXME: pollCreatedCommand', () => { + expect(snackBarService.show).toHaveBeenCalled(); + }); + }); - const delay: string = CommandEffects.POLL_DELAY + 'ms'; + describe('showSnackbar', () => { + const command: CommandResource = createCommandResource(); - const command: CommandResource = createCommandResource(); + const showSnackbarAction: TypedAction<string> = CommandActions.showSnackbar({ command }); - const pollCreateCommandAction: TypedAction<string> = CommandActions.pollCreatedCommand({ command }); + it('should show snackbar', () => { + actions = of(showSnackbarAction); - beforeEach(() => { - repository.getCommand.mockReturnValue(of(command)); - }) + effects.showSnackbar$.subscribe(); - it('should call repository', () => { - actions = hot('-a', { a: pollCreateCommandAction }); + expect(snackBarService.show).toHaveBeenCalledWith( + command, + CREATE_COMMAND_MESSAGE_BY_ORDER[command.order], + ); + }); + }); - effects.pollCreatedCommand$.subscribe(() => { - console.info('Call repo!?'); - // expect(repository.getCommand).toHaveBeenCalledWith(command); - fail(); - }); - }); + describe('revokeCommand', () => { + const command: CommandResource = createCommandResource(); + const revokeCommandAction: TypedAction<string> = CommandActions.revokeCommand({ command }); - it('should handle createdCommand on no error and pending command', () => { - // testScheduler.run((helpers) => { - // const { hot, cold } = helpers; - repository.getCommand.mockReturnValue(cold('-b|', { b: command })); + const getCommand: CommandResource = createCommandResource(); - effects.handleCreatedCommand = jest.fn(); + beforeEach(() => { + repository.revokeCommand.mockReturnValue(of(getCommand)); + }); - actions = hot('-a', { a: pollCreateCommandAction }); + it('should call repository', () => { + actions = of(revokeCommandAction); - effects.createCommand$.subscribe(() => { - console.info('Call handleCreatedCommand!?'); - expect(effects.handleCreatedCommand).toHaveBeenCalledWith(command); - }); - // }); - }); + effects.revokeCommand$.subscribe(); - it('should dispatch failure action on error', () => { - testScheduler.run((helpers) => { - const { hot, cold, expectObservable } = helpers; - const error = { error: {} }; - const errorResponse = cold('-#', {}, error); - repository.getCommand = jest.fn(() => errorResponse); + expect(repository.revokeCommand).toHaveBeenCalledWith(command); + }); - actions = hot('-a', { a: pollCreateCommandAction }); + it('should handle revokeCommand', () => { + effects.handleRevokeCommand = jest.fn(); - expectObservable(effects.pollCreatedCommand$).toBe(delay + ' --c', { c: createCommandFailure({ command, error }) }); - }); - }) - }); + actions = of(revokeCommandAction); + effects.revokeCommand$.subscribe(); - describe('handleCreateCommandSuccess', () => { + expect(effects.handleRevokeCommand).toHaveBeenCalledWith(getCommand); + }); - it('should return createCommandSuccess action and showSnackbar', () => { - const command: CommandResource = createCommandResource(); + it('should dispatch failure action on error', () => { + const error = { error: {} }; + const errorResponse = cold('-#', {}, error); + repository.revokeCommand = jest.fn(() => errorResponse); - const actions: TypedAction<string>[] = effects.handleCreateCommandSuccess(command); + actions = hot('-a', { a: revokeCommandAction }); - expect(actions.length).toBe(2); - expect(actions[0].type).toBe(CommandActions.createCommandSuccess.type); - expect((<any>actions[0]).command).toBe(command); - expect(actions[1].type).toBe(CommandActions.showSnackbar.type); - expect((<any>actions[1]).command).toBe(command); - }) + const expected: ColdObservable = cold('--b', { + b: CommandActions.revokeCommandFailure({ command, error }), + }); + expect(effects.revokeCommand$).toBeObservable(expected); + }); + }); - it('should return createCommandSuccess action and showRevokeSnackbar on revokeable command', () => { - const command: CommandResource = createCommandResource([CommandLinkRel.REVOKE]); + describe.skip('pollRevokedCommand', () => { + //TODO Test fuer pollRevokedCommand + }); - const actions: TypedAction<string>[] = effects.handleCreateCommandSuccess(command); + describe('handleRevokeCommand', () => { + it('should return revokeCommandSuccess action', () => { + const command: CommandResource = createCommandResource(); - expect(actions.length).toBe(2); - expect(actions[0].type).toBe(CommandActions.createCommandSuccess.type); - expect((<any>actions[0]).command).toBe(command); - expect(actions[1].type).toBe(CommandActions.showRevokeSnackbar.type); - expect((<any>actions[1]).command).toBe(command); - }) + const actions: (CommandProps & TypedAction<string>)[] = effects.handleRevokeCommand(command); - describe('on error', () => { + expect(actions.length).toBe(1); + expect(actions[0].type).toBe(CommandActions.revokeCommandSuccess.type); + expect(actions[0].command).toBe(command); + }); - it('should show snackbar with error', () => { - const command: CommandResource = { ...createCommandResource(), errorMessage: CommandErrorMessage.CONCURRENT_MODIFICATION }; + it('should return pollRevokedCommand action on pending command', () => { + const command: CommandResource = createCommandResource([CommandLinkRel.UPDATE]); - effects.handleCreateCommandSuccess(command); + const actions: (CommandProps & TypedAction<string>)[] = effects.handleRevokeCommand(command); - expect(snackBarService.showError).toHaveBeenCalledWith('Der Vorgang wurde zwischenzeitlich verändert und wurde neu geladen.'); - }) - - it('should return createCommandSuccess and publishConcurrentModificationAction', () => { - const command: CommandResource = { ...createCommandResource(), errorMessage: CommandErrorMessage.CONCURRENT_MODIFICATION }; - - const actions: TypedAction<string>[] = effects.handleCreateCommandSuccess(command); - - expect(actions.length).toBe(2); - expect(actions[0].type).toBe(CommandActions.createCommandSuccess.type); - expect((<any>actions[0]).command).toBe(command); - expect(actions[1].type).toBe(CommandActions.publishConcurrentModificationAction.type); - }) - }) - }) - - describe('showRevokeSnackbar', () => { - - const command: CommandResource = createCommandResource(); - - const showRevokeSnackbarAction: TypedAction<string> = CommandActions.showRevokeSnackbar({ command }); - - it('should show snackbar', () => { - actions = of(showRevokeSnackbarAction); - - effects.showRevokeSnackbar$.subscribe(); - - expect(snackBarService.show).toHaveBeenCalled(); - }) - }) - - describe('showSnackbar', () => { - - const command: CommandResource = createCommandResource(); - - const showSnackbarAction: TypedAction<string> = CommandActions.showSnackbar({ command }); - - it('should show snackbar', () => { - actions = of(showSnackbarAction); - - effects.showSnackbar$.subscribe(); - - expect(snackBarService.show).toHaveBeenCalledWith(command, CREATE_COMMAND_MESSAGE_BY_ORDER[command.order]); - }) - }) - - describe('revokeCommand', () => { - - const command: CommandResource = createCommandResource(); - const revokeCommandAction: TypedAction<string> = CommandActions.revokeCommand({ command }); - - const getCommand: CommandResource = createCommandResource(); - - beforeEach(() => { - repository.revokeCommand.mockReturnValue(of(getCommand)); - }) - - it('should call repository', () => { - actions = of(revokeCommandAction); - - effects.revokeCommand$.subscribe(); - - expect(repository.revokeCommand).toHaveBeenCalledWith(command); - }) - - it('should handle revokeCommand', () => { - effects.handleRevokeCommand = jest.fn(); - - actions = of(revokeCommandAction); - effects.revokeCommand$.subscribe(); - - expect(effects.handleRevokeCommand).toHaveBeenCalledWith(getCommand); - }) - - it('should dispatch failure action on error', () => { - const error = { error: {} }; - const errorResponse = cold('-#', {}, error); - repository.revokeCommand = jest.fn(() => errorResponse); - - actions = hot('-a', { a: revokeCommandAction }); - - const expected: ColdObservable = cold('--b', { b: CommandActions.revokeCommandFailure({ command, error }) }); - expect(effects.revokeCommand$).toBeObservable(expected); - }) - }) - - describe.skip('pollRevokedCommand', () => { - //TODO Test fuer pollRevokedCommand - }) - - describe('handleRevokeCommand', () => { - - it('should return revokeCommandSuccess action', () => { - const command: CommandResource = createCommandResource(); - - const actions: (CommandProps & TypedAction<string>)[] = effects.handleRevokeCommand(command); - - expect(actions.length).toBe(1); - expect(actions[0].type).toBe(CommandActions.revokeCommandSuccess.type); - expect(actions[0].command).toBe(command); - }) - - it('should return pollRevokedCommand action on pending command', () => { - const command: CommandResource = createCommandResource([CommandLinkRel.UPDATE]); - - const actions: (CommandProps & TypedAction<string>)[] = effects.handleRevokeCommand(command); - - expect(actions.length).toBe(1); - expect(actions[0].type).toBe(CommandActions.pollRevokedCommand.type); - expect(actions[0].command).toBe(command); - }) - }) -}) \ No newline at end of file + expect(actions.length).toBe(1); + expect(actions[0].type).toBe(CommandActions.pollRevokedCommand.type); + expect(actions[0].command).toBe(command); + }); + }); +}); diff --git a/alfa-client/libs/command-shared/src/lib/+state/command.effects.ts b/alfa-client/libs/command-shared/src/lib/+state/command.effects.ts index 47999c94a1e58d1684c2980aaab8b8dbc5db2480..cfa9a24d55c3f94feb5d2726ecd7349b2347f5f5 100644 --- a/alfa-client/libs/command-shared/src/lib/+state/command.effects.ts +++ b/alfa-client/libs/command-shared/src/lib/+state/command.effects.ts @@ -9,90 +9,156 @@ import { COMMAND_ERROR_MESSAGES, CREATE_COMMAND_MESSAGE_BY_ORDER } from '../comm import { CommandListResource, CommandResource, CreateCommandProps } from '../command.model'; import { CommandRepository } from '../command.repository'; import { hasError, isConcurrentModification, isPending, isRevokeable } from '../command.util'; -import { CommandProps, LoadCommandListProps, PollCommandProps, createCommand, createCommandFailure, createCommandSuccess, loadCommandList, pollCreatedCommand, pollRevokedCommand, publishConcurrentModificationAction, revokeCommand, revokeCommandFailure, revokeCommandSuccess, showRevokeSnackbar, showSnackbar } from './command.actions'; +import { + CommandProps, + LoadCommandListProps, + PollCommandProps, + createCommand, + createCommandFailure, + createCommandSuccess, + loadCommandList, + pollCreatedCommand, + pollRevokedCommand, + publishConcurrentModificationAction, + revokeCommand, + revokeCommandFailure, + revokeCommandSuccess, + showRevokeSnackbar, + showSnackbar, +} from './command.actions'; @Injectable() export class CommandEffects { + static readonly POLL_DELAY: number = 500; - static readonly POLL_DELAY: number = 500; + constructor( + private readonly actions$: Actions, + private store$: Store, + private readonly repository: CommandRepository, + private snackbarService: SnackBarService, + ) {} - constructor(private readonly actions$: Actions, private store$: Store, private readonly repository: CommandRepository, private snackbarService: SnackBarService) { } + loadCommandList$ = createEffect(() => + this.actions$.pipe( + ofType(loadCommandList), + switchMap((props: LoadCommandListProps) => + this.repository.getPendingCommands(props.resource, props.linkRel).pipe( + map((commandList: CommandListResource) => props.successAction(commandList)), + catchError((error) => of(props.failureAction(error.error))), + ), + ), + ), + ); - loadCommandList$ = createEffect(() => this.actions$.pipe(ofType(loadCommandList), - switchMap((props: LoadCommandListProps) => this.repository.getPendingCommands(props.resource, props.linkRel).pipe( - map((commandList: CommandListResource) => props.successAction(commandList)), - catchError(error => of(props.failureAction(error.error))) - )) - )); + createCommand$ = createEffect(() => + this.actions$.pipe( + ofType(createCommand), + switchMap((props: CreateCommandProps) => + this.repository.createCommand(props.resource, props.linkRel, props.command).pipe( + mergeMap((command: CommandResource) => this.handleCreatedCommand(command)), + catchError((error) => of(createCommandFailure({ error, command: props.command }))), + ), + ), + ), + ); - createCommand$ = createEffect(() => this.actions$.pipe(ofType(createCommand), - switchMap((props: CreateCommandProps) => this.repository.createCommand(props.resource, props.linkRel, props.command).pipe( - mergeMap((command: CommandResource) => this.handleCreatedCommand(command)), - catchError(error => of(createCommandFailure({ error, command: props.command}))) - )) - )); + pollCreatedCommand$ = createEffect(() => + this.actions$.pipe( + ofType(pollCreatedCommand), + delay(CommandEffects.POLL_DELAY), + switchMap((props: PollCommandProps) => + this.repository.getCommand(props.command).pipe( + mergeMap((command: CommandResource) => this.handleCreatedCommand(command)), + catchError((error) => of(createCommandFailure({ command: props.command, error }))), + ), + ), + ), + ); - pollCreatedCommand$ = createEffect(() => this.actions$.pipe(ofType(pollCreatedCommand), - delay(CommandEffects.POLL_DELAY), - switchMap((props: PollCommandProps) => this.repository.getCommand(props.command).pipe( - mergeMap((command: CommandResource) => this.handleCreatedCommand(command)), - catchError(error => of(createCommandFailure({ command: props.command, error }))) - )) - )); + handleCreatedCommand(command: CommandResource): TypedAction<string>[] { + if (isPending(command)) { + return [pollCreatedCommand({ command })]; + } + return this.handleCreateCommandSuccess(command); + } - handleCreatedCommand(command: CommandResource): TypedAction<string>[] { - if(isPending(command)){ - return [pollCreatedCommand({ command })]; - } - return this.handleCreateCommandSuccess(command); - } + handleCreateCommandSuccess(command: CommandResource): TypedAction<string>[] { + if (isRevokeable(command)) { + return [createCommandSuccess({ command }), showRevokeSnackbar({ command })]; + } + if (hasError(command) && isConcurrentModification(command.errorMessage)) { + this.showError(command); + return [createCommandSuccess({ command }), publishConcurrentModificationAction()]; + } + return [createCommandSuccess({ command }), showSnackbar({ command })]; + } - handleCreateCommandSuccess(command: CommandResource): TypedAction<string>[] { - if(isRevokeable(command)){ - return [createCommandSuccess({ command }), showRevokeSnackbar({ command })]; - } - if(hasError(command) && isConcurrentModification(command.errorMessage)){ - this.showError(command); - return [createCommandSuccess({ command }), publishConcurrentModificationAction()]; - } - return [createCommandSuccess({ command }), showSnackbar({ command })]; - } + private showError(command: CommandResource): void { + this.snackbarService.showError(COMMAND_ERROR_MESSAGES[command.errorMessage]); + } - private showError(command: CommandResource): void { - this.snackbarService.showError(COMMAND_ERROR_MESSAGES[command.errorMessage]); - } + showRevokeSnackbar$ = createEffect( + () => + this.actions$.pipe( + ofType(showRevokeSnackbar), + tap((props: CommandProps) => + this.snackbarService.show( + props.command, + CREATE_COMMAND_MESSAGE_BY_ORDER[props.command.order], + this.buildRevokeFunction(props.command), + ), + ), + ), + { dispatch: false }, + ); - showRevokeSnackbar$ = createEffect(() => this.actions$.pipe(ofType(showRevokeSnackbar), - tap((props: CommandProps) => this.snackbarService.show(props.command, CREATE_COMMAND_MESSAGE_BY_ORDER[props.command.order], this.buildRevokeFunction(props.command))) - ), { dispatch: false }); + buildRevokeFunction(command: CommandResource) { + return () => this.store$.dispatch(revokeCommand({ command })); + } - buildRevokeFunction(command: CommandResource) { - return () => this.store$.dispatch(revokeCommand({ command })); - } + showSnackbar$ = createEffect( + () => + this.actions$.pipe( + ofType(showSnackbar), + tap((props: CommandProps) => + this.snackbarService.show( + props.command, + CREATE_COMMAND_MESSAGE_BY_ORDER[props.command.order], + ), + ), + ), + { dispatch: false }, + ); - showSnackbar$ = createEffect(() => this.actions$.pipe(ofType(showSnackbar), - tap((props: CommandProps) => this.snackbarService.show(props.command, CREATE_COMMAND_MESSAGE_BY_ORDER[props.command.order])) - ), { dispatch: false }); + revokeCommand$ = createEffect(() => + this.actions$.pipe( + ofType(revokeCommand), + switchMap((props: CommandProps) => + this.repository.revokeCommand(props.command).pipe( + mergeMap((command: CommandResource) => this.handleRevokeCommand(command)), + catchError((error) => of(revokeCommandFailure({ command: props.command, error }))), + ), + ), + ), + ); - revokeCommand$ = createEffect(() => this.actions$.pipe(ofType(revokeCommand), - switchMap((props: CommandProps) => this.repository.revokeCommand(props.command).pipe( - mergeMap((command: CommandResource) => this.handleRevokeCommand(command)), - catchError(error => of(revokeCommandFailure({ command: props.command, error }))) - )) - )); + pollRevokedCommand$ = createEffect(() => + this.actions$.pipe( + ofType(pollRevokedCommand), + delay(CommandEffects.POLL_DELAY), + switchMap((props: PollCommandProps) => + this.repository.getCommand(props.command).pipe( + mergeMap((command: CommandResource) => this.handleRevokeCommand(command)), + catchError((error) => of(revokeCommandFailure({ command: props.command, error }))), + ), + ), + ), + ); - pollRevokedCommand$ = createEffect(() => this.actions$.pipe(ofType(pollRevokedCommand), - delay(CommandEffects.POLL_DELAY), - switchMap((props: PollCommandProps) => this.repository.getCommand(props.command).pipe( - mergeMap((command: CommandResource) => this.handleRevokeCommand(command)), - catchError(error => of(revokeCommandFailure({ command: props.command, error }))) - )) - )); - - handleRevokeCommand(command: CommandResource): (CommandProps & TypedAction<string>)[] { - if(isPending(command)){ - return [pollRevokedCommand({ command })]; - } - return [revokeCommandSuccess({ command })]; - } -} \ No newline at end of file + handleRevokeCommand(command: CommandResource): (CommandProps & TypedAction<string>)[] { + if (isPending(command)) { + return [pollRevokedCommand({ command })]; + } + return [revokeCommandSuccess({ command })]; + } +} diff --git a/alfa-client/libs/command-shared/src/lib/+state/command.reducer.spec.ts b/alfa-client/libs/command-shared/src/lib/+state/command.reducer.spec.ts index b14286f2dde954c20301355bb4d4b4b833bf0d35..23d124005f3e72cc6ff3daa1eb2244acb4fb5dea 100644 --- a/alfa-client/libs/command-shared/src/lib/+state/command.reducer.spec.ts +++ b/alfa-client/libs/command-shared/src/lib/+state/command.reducer.spec.ts @@ -1,5 +1,10 @@ import { CommandResource, CreateCommand } from '@alfa-client/command-shared'; -import { ApiError, createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + ApiError, + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Action } from '@ngrx/store'; import { Resource, ResourceUri } from '@ngxp/rest'; import { createCommandResource, createCreateCommand } from 'libs/command-shared/test/command'; @@ -12,57 +17,52 @@ import faker from '@faker-js/faker'; import * as CommandActions from '@alfa-client/command-shared'; describe('Command Reducer', () => { + describe('unknown action', () => { + it('should return current state', () => { + const action: Action = {} as Action; - describe('unknown action', () => { + const result: any = reducer(initialState, action); - it('should return current state', () => { - const action: Action = {} as Action; + expect(result).toBe(initialState); + }); + }); - const result: any = reducer(initialState, action); + describe('createCommand', () => { + const resource: Resource = createDummyResource(); + const linkRel: ResourceUri = faker.internet.url(); + const command: CreateCommand = createCreateCommand(); - expect(result).toBe(initialState); - }) - }) + it('should create empty loading map entry', () => { + const action = CommandActions.createCommand({ resource, linkRel, command }); - describe('createCommand', () => { + const state: CommandState = reducer(initialState, action); - const resource: Resource = createDummyResource(); - const linkRel: ResourceUri = faker.internet.url(); - const command: CreateCommand = createCreateCommand(); + expect(state.commandByOrderMap[command.order]).toEqual(createEmptyStateResource(true)); + }); + }); - it('should create empty loading map entry', () => { - const action = CommandActions.createCommand({ resource, linkRel, command }); + describe('createCommandSuccess', () => { + const command: CommandResource = createCommandResource(); - const state: CommandState = reducer(initialState, action); + it('should create stateResource entry by loaded resource', () => { + const action = CommandActions.createCommandSuccess({ command }); - expect(state.commandByOrderMap[command.order]).toEqual(createEmptyStateResource(true)); - }) - }) + const state: CommandState = reducer(initialState, action); - describe('createCommandSuccess', () => { + expect(state.commandByOrderMap[command.order]).toEqual(createStateResource(command)); + }); + }); - const command: CommandResource = createCommandResource(); + describe('createCommandFailure', () => { + const command: CommandResource = createCommandResource(); + const error: ApiError = createApiError(); - it('should create stateResource entry by loaded resource', () => { - const action = CommandActions.createCommandSuccess({ command }); + it('should create errorStateResource entry by occured error', () => { + const action = CommandActions.createCommandFailure({ command, error }); - const state: CommandState = reducer(initialState, action); + const state: CommandState = reducer(initialState, action); - expect(state.commandByOrderMap[command.order]).toEqual(createStateResource(command)); - }) - }) - - describe('createCommandFailure', () => { - - const command: CommandResource = createCommandResource(); - const error: ApiError = createApiError(); - - it('should create errorStateResource entry by occured error', () => { - const action = CommandActions.createCommandFailure({ command, error }); - - const state: CommandState = reducer(initialState, action); - - expect(state.commandByOrderMap[command.order]).toEqual(createErrorStateResource(error)); - }) - }) -}); \ No newline at end of file + expect(state.commandByOrderMap[command.order]).toEqual(createErrorStateResource(error)); + }); + }); +}); diff --git a/alfa-client/libs/command-shared/src/lib/+state/command.reducer.ts b/alfa-client/libs/command-shared/src/lib/+state/command.reducer.ts index 268673e6ced198daf248dfbeb17a08401af054b8..2820b1f4cc0be849fcb1811e7c1c100f974c47eb 100644 --- a/alfa-client/libs/command-shared/src/lib/+state/command.reducer.ts +++ b/alfa-client/libs/command-shared/src/lib/+state/command.reducer.ts @@ -1,4 +1,9 @@ -import { StateResource, createAnyErrorStateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + StateResource, + createAnyErrorStateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Action, ActionReducer, createReducer, on } from '@ngrx/store'; import { CommandResource, CreateCommandProps } from '../command.model'; @@ -7,33 +12,51 @@ import * as Actions from './command.actions'; export const COMMAND_FEATURE_KEY = 'CommandState'; export interface CommandPartialState { - readonly [COMMAND_FEATURE_KEY]: CommandState; + readonly [COMMAND_FEATURE_KEY]: CommandState; } export interface CommandState { - commandByOrderMap: {[order: string]: StateResource<CommandResource>}; + commandByOrderMap: { [order: string]: StateResource<CommandResource> }; } export const initialState: CommandState = { - commandByOrderMap: {}, + commandByOrderMap: {}, }; const commandReducer: ActionReducer<CommandState, Action> = createReducer( - initialState, - on(Actions.createCommand, (state: CommandState, props: CreateCommandProps): CommandState => ({ - ...state, - commandByOrderMap: { ...state.commandByOrderMap, [props.command.order]: createEmptyStateResource(true) } - })), - on(Actions.createCommandSuccess, (state: CommandState, props: Actions.CommandProps): CommandState => ({ - ...state, - commandByOrderMap: { ...state.commandByOrderMap, [props.command.order]: createStateResource(props.command) } - })), - on(Actions.createCommandFailure, (state: CommandState, props: Actions.CreateCommandFailureProps): CommandState => ({ - ...state, - commandByOrderMap: { ...state.commandByOrderMap, [props.command.order]: createAnyErrorStateResource(props.error) } - })) + initialState, + on( + Actions.createCommand, + (state: CommandState, props: CreateCommandProps): CommandState => ({ + ...state, + commandByOrderMap: { + ...state.commandByOrderMap, + [props.command.order]: createEmptyStateResource(true), + }, + }), + ), + on( + Actions.createCommandSuccess, + (state: CommandState, props: Actions.CommandProps): CommandState => ({ + ...state, + commandByOrderMap: { + ...state.commandByOrderMap, + [props.command.order]: createStateResource(props.command), + }, + }), + ), + on( + Actions.createCommandFailure, + (state: CommandState, props: Actions.CreateCommandFailureProps): CommandState => ({ + ...state, + commandByOrderMap: { + ...state.commandByOrderMap, + [props.command.order]: createAnyErrorStateResource(props.error), + }, + }), + ), ); export function reducer(state: CommandState, action: Action): CommandState { - return commandReducer(state, action); + return commandReducer(state, action); } diff --git a/alfa-client/libs/command-shared/src/lib/+state/command.selectors.spec.ts b/alfa-client/libs/command-shared/src/lib/+state/command.selectors.spec.ts index 3812810b85afdd3c118d7c782102933d30d1cdab..324049591ade7dc760e543965e00eeabfed3ec60 100644 --- a/alfa-client/libs/command-shared/src/lib/+state/command.selectors.spec.ts +++ b/alfa-client/libs/command-shared/src/lib/+state/command.selectors.spec.ts @@ -6,43 +6,43 @@ import { CommandPartialState, initialState } from './command.reducer'; import * as Selectors from './command.selectors'; describe('Command Selectors', () => { - - let state: CommandPartialState; - - const commandInState: CreateCommand = createCreateCommand(); - const commandInStateOrder: CommandOrder = CommandOrder.VORGANG_ANNEHMEN; - const commandByOrderMap: any = { [commandInStateOrder]: commandInState }; - - beforeEach(() => { - state = { - CommandState: { - ...initialState, - commandByOrderMap - } - }; - }); - - describe('commandByOrderMap', () => { - - it('should select commandByOrderMap', () => { - const result: any = Selectors.commandByOrderMap.projector(state.CommandState); - - expect(result).toBe(commandByOrderMap); - }) - }) - - describe('commandByOrder', () => { - - it('should return command from map by order', () => { - const result: StateResource<CommandResource> = Selectors.commandByOrder(commandInStateOrder).projector(commandByOrderMap); - - expect(result).toBe(commandInState); - }) - - it('should return empty state resource on empty object', () => { - const result: StateResource<CommandResource> = Selectors.commandByOrder(commandInStateOrder).projector({}); - - expect(result).toEqual(createEmptyStateResource()); - }) - }) -}); \ No newline at end of file + let state: CommandPartialState; + + const commandInState: CreateCommand = createCreateCommand(); + const commandInStateOrder: CommandOrder = CommandOrder.VORGANG_ANNEHMEN; + const commandByOrderMap: any = { [commandInStateOrder]: commandInState }; + + beforeEach(() => { + state = { + CommandState: { + ...initialState, + commandByOrderMap, + }, + }; + }); + + describe('commandByOrderMap', () => { + it('should select commandByOrderMap', () => { + const result: any = Selectors.commandByOrderMap.projector(state.CommandState); + + expect(result).toBe(commandByOrderMap); + }); + }); + + describe('commandByOrder', () => { + it('should return command from map by order', () => { + const result: StateResource<CommandResource> = + Selectors.commandByOrder(commandInStateOrder).projector(commandByOrderMap); + + expect(result).toBe(commandInState); + }); + + it('should return empty state resource on empty object', () => { + const result: StateResource<CommandResource> = Selectors.commandByOrder( + commandInStateOrder, + ).projector({}); + + expect(result).toEqual(createEmptyStateResource()); + }); + }); +}); diff --git a/alfa-client/libs/command-shared/src/lib/+state/command.selectors.ts b/alfa-client/libs/command-shared/src/lib/+state/command.selectors.ts index 0d056bfee116ae083e0e6dac38e01437663bddd6..65ab3989b73be46cc1631f535d6655981426aacd 100644 --- a/alfa-client/libs/command-shared/src/lib/+state/command.selectors.ts +++ b/alfa-client/libs/command-shared/src/lib/+state/command.selectors.ts @@ -4,7 +4,16 @@ import { MemoizedSelector, createFeatureSelector, createSelector } from '@ngrx/s import { isUndefined } from 'lodash-es'; import { COMMAND_FEATURE_KEY, CommandState } from './command.reducer'; -const getCommandState: MemoizedSelector<object, CommandState> = createFeatureSelector<CommandState>(COMMAND_FEATURE_KEY); +const getCommandState: MemoizedSelector<object, CommandState> = + createFeatureSelector<CommandState>(COMMAND_FEATURE_KEY); -export const commandByOrderMap: MemoizedSelector<CommandState, any> = createSelector(getCommandState, (state: CommandState) => state.commandByOrderMap); -export const commandByOrder = (order: CommandOrder) => createSelector(commandByOrderMap, (commandByOrderMapInState: any) => isUndefined(commandByOrderMapInState[order]) ? createEmptyStateResource(): commandByOrderMapInState[order]); \ No newline at end of file +export const commandByOrderMap: MemoizedSelector<CommandState, any> = createSelector( + getCommandState, + (state: CommandState) => state.commandByOrderMap, +); +export const commandByOrder = (order: CommandOrder) => + createSelector(commandByOrderMap, (commandByOrderMapInState: any) => + isUndefined(commandByOrderMapInState[order]) ? + createEmptyStateResource() + : commandByOrderMapInState[order], + ); diff --git a/alfa-client/libs/command-shared/src/lib/command-shared.module.spec.ts b/alfa-client/libs/command-shared/src/lib/command-shared.module.spec.ts index 3db51028826ad6f2cd63b382728bd8599ff14ece..83f7d38cd8c5037eeeb240c5561f6bee390aca48 100644 --- a/alfa-client/libs/command-shared/src/lib/command-shared.module.spec.ts +++ b/alfa-client/libs/command-shared/src/lib/command-shared.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { CommandSharedModule } from './command-shared.module'; describe('CommandSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [CommandSharedModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [CommandSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(CommandSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(CommandSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/command-shared/src/lib/command-shared.module.ts b/alfa-client/libs/command-shared/src/lib/command-shared.module.ts index caca088980a5b39a59710d707537f1aec3b3a2f1..2748c246343de67cd80c8db792c9edbc6333a07d 100644 --- a/alfa-client/libs/command-shared/src/lib/command-shared.module.ts +++ b/alfa-client/libs/command-shared/src/lib/command-shared.module.ts @@ -29,10 +29,10 @@ import { CommandEffects } from './+state/command.effects'; import { COMMAND_FEATURE_KEY, reducer } from './+state/command.reducer'; @NgModule({ - imports: [ - CommonModule, - StoreModule.forFeature(COMMAND_FEATURE_KEY, reducer), - EffectsModule.forFeature([CommandEffects]) - ] + imports: [ + CommonModule, + StoreModule.forFeature(COMMAND_FEATURE_KEY, reducer), + EffectsModule.forFeature([CommandEffects]), + ], }) -export class CommandSharedModule { } +export class CommandSharedModule {} diff --git a/alfa-client/libs/command-shared/src/lib/command.linkrel.ts b/alfa-client/libs/command-shared/src/lib/command.linkrel.ts index 57a6fcf77367415f95659d82ef4bc1c31aa63e48..7bb6215cbbdf7b476f59e170a1a8800f65ed2eab 100644 --- a/alfa-client/libs/command-shared/src/lib/command.linkrel.ts +++ b/alfa-client/libs/command-shared/src/lib/command.linkrel.ts @@ -22,13 +22,13 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum CommandLinkRel { - CREATED_BY = 'createdBy', - EFFECTED_RESOURCE = 'effected_resource', - REVOKE = 'revoke', - SELF = 'self', - UPDATE = 'update' + CREATED_BY = 'createdBy', + EFFECTED_RESOURCE = 'effected_resource', + REVOKE = 'revoke', + SELF = 'self', + UPDATE = 'update', } export enum CommandListLinkRel { - COMMAND_LIST = 'commandList' + COMMAND_LIST = 'commandList', } diff --git a/alfa-client/libs/command-shared/src/lib/command.message.ts b/alfa-client/libs/command-shared/src/lib/command.message.ts index 1f364268465f8ea66fdb34339330a067fa8d2ff3..bd479e500a774c13cb37e1188886f86664713ab1 100644 --- a/alfa-client/libs/command-shared/src/lib/command.message.ts +++ b/alfa-client/libs/command-shared/src/lib/command.message.ts @@ -1,28 +1,32 @@ import { CommandOrder } from './command.model'; export enum CommandErrorMessage { - CONCURRENT_MODIFICATION = 'concurrent_modification' + CONCURRENT_MODIFICATION = 'concurrent_modification', } export const COMMAND_ERROR_MESSAGES: { [code: string]: string } = { - [CommandErrorMessage.CONCURRENT_MODIFICATION]: 'Der Vorgang wurde zwischenzeitlich verändert und wurde neu geladen.', -} + [CommandErrorMessage.CONCURRENT_MODIFICATION]: + 'Der Vorgang wurde zwischenzeitlich verändert und wurde neu geladen.', +}; export const CREATE_COMMAND_MESSAGE_BY_ORDER: { [order: string]: string } = { - [CommandOrder.VORGANG_ANNEHMEN]: 'Der Vorgang wurde angenommen.', - [CommandOrder.VORGANG_BEARBEITEN]: 'Der Vorgang wurde in die Bearbeitung übernommen.', - [CommandOrder.VORGANG_BESCHEIDEN]: 'Der Vorgang wurde beschieden.', - [CommandOrder.VORGANG_ZURUECKHOLEN]: 'Der Vorgang wurde zurückgeholt.', - [CommandOrder.VORGANG_ZURUECKSTELLEN]: 'Der Vorgang wurde zurückgestellt.', - [CommandOrder.VORGANG_ABSCHLIESSEN]: 'Der Vorgang wurde abgeschlossen.', - [CommandOrder.VORGANG_WIEDEREROEFFNEN]: 'Der Vorgang wurde wiedereröffnet.', - [CommandOrder.VORGANG_VERWERFEN]: 'Der Vorgang wurde verworfen.', - [CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN]: 'Für den Vorgang wurde eine Löschanforderung gestellt.', - [CommandOrder.VORGANG_LOESCHEN]: 'Der Vorgang wurde gelöscht.', - [CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN]: 'Für den Vorgang wurde die Löschanforderung zurückgenommen.', - [CommandOrder.ASSIGN_USER]: 'Dem Vorgang wurde eine bearbeitende Person zugewiesen.', - [CommandOrder.CREATE_BESCHEID]: 'Es wurde ein Bescheid erstellt.', - [CommandOrder.PROCESS_VORGANG]: 'Vorgang vorprüfen erfolgreich.' -} + [CommandOrder.VORGANG_ANNEHMEN]: 'Der Vorgang wurde angenommen.', + [CommandOrder.VORGANG_BEARBEITEN]: 'Der Vorgang wurde in die Bearbeitung übernommen.', + [CommandOrder.VORGANG_BESCHEIDEN]: 'Der Vorgang wurde beschieden.', + [CommandOrder.VORGANG_ZURUECKHOLEN]: 'Der Vorgang wurde zurückgeholt.', + [CommandOrder.VORGANG_ZURUECKSTELLEN]: 'Der Vorgang wurde zurückgestellt.', + [CommandOrder.VORGANG_ABSCHLIESSEN]: 'Der Vorgang wurde abgeschlossen.', + [CommandOrder.VORGANG_WIEDEREROEFFNEN]: 'Der Vorgang wurde wiedereröffnet.', + [CommandOrder.VORGANG_VERWERFEN]: 'Der Vorgang wurde verworfen.', + [CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN]: + 'Für den Vorgang wurde eine Löschanforderung gestellt.', + [CommandOrder.VORGANG_LOESCHEN]: 'Der Vorgang wurde gelöscht.', + [CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN]: + 'Für den Vorgang wurde die Löschanforderung zurückgenommen.', + [CommandOrder.ASSIGN_USER]: 'Dem Vorgang wurde eine bearbeitende Person zugewiesen.', + [CommandOrder.CREATE_BESCHEID]: 'Es wurde ein Bescheid erstellt.', + [CommandOrder.PROCESS_VORGANG]: 'Vorgang vorprüfen erfolgreich.', +}; -export const LOESCH_ANFORDERUNG_ZURUECKNEHMEN_CONCURRENT_TO_DELETE_VORGANG_MESSAGE: string = 'Der Vorgang wurde zwischenzeitlich gelöscht.'; \ No newline at end of file +export const LOESCH_ANFORDERUNG_ZURUECKNEHMEN_CONCURRENT_TO_DELETE_VORGANG_MESSAGE: string = + 'Der Vorgang wurde zwischenzeitlich gelöscht.'; diff --git a/alfa-client/libs/command-shared/src/lib/command.model.ts b/alfa-client/libs/command-shared/src/lib/command.model.ts index 99257455963929e8757f07ee36f1f85877bad8df..1dbd3046f91c9e6079ad54cf6ccdd3ec7712ac0e 100644 --- a/alfa-client/libs/command-shared/src/lib/command.model.ts +++ b/alfa-client/libs/command-shared/src/lib/command.model.ts @@ -25,20 +25,20 @@ import { ListResource } from '@alfa-client/tech-shared'; import { Resource } from '@ngxp/rest'; export interface CreateCommand { - order: CommandOrder | any - body?: any | CommandBody + order: CommandOrder | any; + body?: any | CommandBody; } export interface CommandBody { - item: any + item: any; } export interface Command extends CreateCommand { - createdAt: Date, - createdByName?: string, - status: CommandStatus, - finishedAt: Date, - errorMessage: string + createdAt: Date; + createdByName?: string; + status: CommandStatus; + finishedAt: Date; + errorMessage: string; } export interface CommandResource extends Command, Resource {} @@ -46,83 +46,83 @@ export interface CommandResource extends Command, Resource {} export interface CommandListResource extends ListResource {} export enum CommandStatus { - FINISHED = 'FINISHED', - PENDING = 'PENDING', - REVOKED = 'REVOKED', - ERROR = 'ERROR' + FINISHED = 'FINISHED', + PENDING = 'PENDING', + REVOKED = 'REVOKED', + ERROR = 'ERROR', } export enum CommandOrder { - ASSIGN_USER = 'ASSIGN_USER', - CREATE_KOMMENTAR = 'CREATE_KOMMENTAR', - EDIT_KOMMENTAR = 'EDIT_KOMMENTAR', - CREATE_WIEDERVORLAGE = 'CREATE_WIEDERVORLAGE', - EDIT_WIEDERVORLAGE = 'EDIT_WIEDERVORLAGE', - FORWARD_FAILED = 'FORWARD_FAILED', - REDIRECT_VORGANG = 'REDIRECT_VORGANG', - FORWARD_SUCCESSFULL = 'FORWARD_SUCCESSFULL', - PROCESS_VORGANG = 'PROCESS_VORGANG', - SEND_POSTFACH_NACHRICHT = 'SEND_POSTFACH_NACHRICHT', - RECEIVE_POSTFACH_NACHRICHT = 'RECEIVE_POSTFACH_NACHRICHT', - RESEND_POSTFACH_NACHRICHT = 'RESEND_POSTFACH_MAIL', - WIEDERVORLAGE_ERLEDIGEN = 'WIEDERVORLAGE_ERLEDIGEN', - WIEDERVORLAGE_WIEDEREROEFFNEN = 'WIEDERVORLAGE_WIEDEREROEFFNEN', - VORGANG_ANNEHMEN = 'VORGANG_ANNEHMEN', - VORGANG_VERWERFEN = 'VORGANG_VERWERFEN', - VORGANG_ZURUECKHOLEN = 'VORGANG_ZURUECKHOLEN', - VORGANG_BEARBEITEN = 'VORGANG_BEARBEITEN', - VORGANG_BESCHEIDEN = 'VORGANG_BESCHEIDEN', - VORGANG_ZURUECKSTELLEN = 'VORGANG_ZURUECKSTELLEN', - VORGANG_ABSCHLIESSEN = 'VORGANG_ABSCHLIESSEN', - VORGANG_WIEDEREROEFFNEN = 'VORGANG_WIEDEREROEFFNEN', - VORGANG_ZUM_LOESCHEN_MARKIEREN = 'VORGANG_ZUM_LOESCHEN_MARKIEREN', - VORGANG_LOESCHEN = 'VORGANG_LOESCHEN', - LOESCH_ANFORDERUNG_ZURUECKNEHMEN = 'LOESCH_ANFORDERUNG_ZURUECKNEHMEN', - CREATE_BESCHEID = 'CREATE_BESCHEID', - SET_AKTENZEICHEN = 'SET_AKTENZEICHEN', + ASSIGN_USER = 'ASSIGN_USER', + CREATE_KOMMENTAR = 'CREATE_KOMMENTAR', + EDIT_KOMMENTAR = 'EDIT_KOMMENTAR', + CREATE_WIEDERVORLAGE = 'CREATE_WIEDERVORLAGE', + EDIT_WIEDERVORLAGE = 'EDIT_WIEDERVORLAGE', + FORWARD_FAILED = 'FORWARD_FAILED', + REDIRECT_VORGANG = 'REDIRECT_VORGANG', + FORWARD_SUCCESSFULL = 'FORWARD_SUCCESSFULL', + PROCESS_VORGANG = 'PROCESS_VORGANG', + SEND_POSTFACH_NACHRICHT = 'SEND_POSTFACH_NACHRICHT', + RECEIVE_POSTFACH_NACHRICHT = 'RECEIVE_POSTFACH_NACHRICHT', + RESEND_POSTFACH_NACHRICHT = 'RESEND_POSTFACH_MAIL', + WIEDERVORLAGE_ERLEDIGEN = 'WIEDERVORLAGE_ERLEDIGEN', + WIEDERVORLAGE_WIEDEREROEFFNEN = 'WIEDERVORLAGE_WIEDEREROEFFNEN', + VORGANG_ANNEHMEN = 'VORGANG_ANNEHMEN', + VORGANG_VERWERFEN = 'VORGANG_VERWERFEN', + VORGANG_ZURUECKHOLEN = 'VORGANG_ZURUECKHOLEN', + VORGANG_BEARBEITEN = 'VORGANG_BEARBEITEN', + VORGANG_BESCHEIDEN = 'VORGANG_BESCHEIDEN', + VORGANG_ZURUECKSTELLEN = 'VORGANG_ZURUECKSTELLEN', + VORGANG_ABSCHLIESSEN = 'VORGANG_ABSCHLIESSEN', + VORGANG_WIEDEREROEFFNEN = 'VORGANG_WIEDEREROEFFNEN', + VORGANG_ZUM_LOESCHEN_MARKIEREN = 'VORGANG_ZUM_LOESCHEN_MARKIEREN', + VORGANG_LOESCHEN = 'VORGANG_LOESCHEN', + LOESCH_ANFORDERUNG_ZURUECKNEHMEN = 'LOESCH_ANFORDERUNG_ZURUECKNEHMEN', + CREATE_BESCHEID = 'CREATE_BESCHEID', + SET_AKTENZEICHEN = 'SET_AKTENZEICHEN', } export enum CommandOrderType { - USER = 'User', - FORWARDING = 'Forwarding', - KOMMENTAR = 'Kommentar', - POSTFACH_NACHRICHT = 'PostfachNachricht', - VORGANG = 'Vorgang', - WIEDERVORLAGE = 'Wiedervorlage', - LOESCH_ANFORDERUNG = 'LoeschAnforderung', - SET_AKTENZEICHEN = 'SetAktenzeichen', + USER = 'User', + FORWARDING = 'Forwarding', + KOMMENTAR = 'Kommentar', + POSTFACH_NACHRICHT = 'PostfachNachricht', + VORGANG = 'Vorgang', + WIEDERVORLAGE = 'Wiedervorlage', + LOESCH_ANFORDERUNG = 'LoeschAnforderung', + SET_AKTENZEICHEN = 'SetAktenzeichen', } export const ORDER_TYPE_BY_COMMAND_ORDER = { - [CommandOrder.ASSIGN_USER]: CommandOrderType.USER, - [CommandOrder.CREATE_KOMMENTAR]: CommandOrderType.KOMMENTAR, - [CommandOrder.EDIT_KOMMENTAR]: CommandOrderType.KOMMENTAR, - [CommandOrder.CREATE_WIEDERVORLAGE]: CommandOrderType.WIEDERVORLAGE, - [CommandOrder.EDIT_WIEDERVORLAGE]: CommandOrderType.WIEDERVORLAGE, - [CommandOrder.FORWARD_FAILED]: CommandOrderType.FORWARDING, - [CommandOrder.REDIRECT_VORGANG]: CommandOrderType.FORWARDING, - [CommandOrder.FORWARD_SUCCESSFULL]: CommandOrderType.FORWARDING, - [CommandOrder.SEND_POSTFACH_NACHRICHT]: CommandOrderType.POSTFACH_NACHRICHT, - [CommandOrder.RECEIVE_POSTFACH_NACHRICHT]: CommandOrderType.POSTFACH_NACHRICHT, - [CommandOrder.RESEND_POSTFACH_NACHRICHT]: CommandOrderType.POSTFACH_NACHRICHT, - [CommandOrder.WIEDERVORLAGE_ERLEDIGEN]: CommandOrderType.WIEDERVORLAGE, - [CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN]: CommandOrderType.WIEDERVORLAGE, - [CommandOrder.VORGANG_ANNEHMEN]: CommandOrderType.VORGANG, - [CommandOrder.VORGANG_VERWERFEN]: CommandOrderType.VORGANG, - [CommandOrder.VORGANG_ZURUECKHOLEN]: CommandOrderType.VORGANG, - [CommandOrder.VORGANG_BEARBEITEN]: CommandOrderType.VORGANG, - [CommandOrder.VORGANG_BESCHEIDEN]: CommandOrderType.VORGANG, - [CommandOrder.VORGANG_ZURUECKSTELLEN]: CommandOrderType.VORGANG, - [CommandOrder.VORGANG_ABSCHLIESSEN]: CommandOrderType.VORGANG, - [CommandOrder.VORGANG_WIEDEREROEFFNEN]: CommandOrderType.VORGANG, - [CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN]: CommandOrderType.LOESCH_ANFORDERUNG, - [CommandOrder.VORGANG_LOESCHEN]: CommandOrderType.LOESCH_ANFORDERUNG, - [CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN]: CommandOrderType.LOESCH_ANFORDERUNG, - [CommandOrder.SET_AKTENZEICHEN]: CommandOrderType.SET_AKTENZEICHEN, -} + [CommandOrder.ASSIGN_USER]: CommandOrderType.USER, + [CommandOrder.CREATE_KOMMENTAR]: CommandOrderType.KOMMENTAR, + [CommandOrder.EDIT_KOMMENTAR]: CommandOrderType.KOMMENTAR, + [CommandOrder.CREATE_WIEDERVORLAGE]: CommandOrderType.WIEDERVORLAGE, + [CommandOrder.EDIT_WIEDERVORLAGE]: CommandOrderType.WIEDERVORLAGE, + [CommandOrder.FORWARD_FAILED]: CommandOrderType.FORWARDING, + [CommandOrder.REDIRECT_VORGANG]: CommandOrderType.FORWARDING, + [CommandOrder.FORWARD_SUCCESSFULL]: CommandOrderType.FORWARDING, + [CommandOrder.SEND_POSTFACH_NACHRICHT]: CommandOrderType.POSTFACH_NACHRICHT, + [CommandOrder.RECEIVE_POSTFACH_NACHRICHT]: CommandOrderType.POSTFACH_NACHRICHT, + [CommandOrder.RESEND_POSTFACH_NACHRICHT]: CommandOrderType.POSTFACH_NACHRICHT, + [CommandOrder.WIEDERVORLAGE_ERLEDIGEN]: CommandOrderType.WIEDERVORLAGE, + [CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN]: CommandOrderType.WIEDERVORLAGE, + [CommandOrder.VORGANG_ANNEHMEN]: CommandOrderType.VORGANG, + [CommandOrder.VORGANG_VERWERFEN]: CommandOrderType.VORGANG, + [CommandOrder.VORGANG_ZURUECKHOLEN]: CommandOrderType.VORGANG, + [CommandOrder.VORGANG_BEARBEITEN]: CommandOrderType.VORGANG, + [CommandOrder.VORGANG_BESCHEIDEN]: CommandOrderType.VORGANG, + [CommandOrder.VORGANG_ZURUECKSTELLEN]: CommandOrderType.VORGANG, + [CommandOrder.VORGANG_ABSCHLIESSEN]: CommandOrderType.VORGANG, + [CommandOrder.VORGANG_WIEDEREROEFFNEN]: CommandOrderType.VORGANG, + [CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN]: CommandOrderType.LOESCH_ANFORDERUNG, + [CommandOrder.VORGANG_LOESCHEN]: CommandOrderType.LOESCH_ANFORDERUNG, + [CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN]: CommandOrderType.LOESCH_ANFORDERUNG, + [CommandOrder.SET_AKTENZEICHEN]: CommandOrderType.SET_AKTENZEICHEN, +}; export interface CreateCommandProps { - resource: Resource, - linkRel: string, - command: CreateCommand -} \ No newline at end of file + resource: Resource; + linkRel: string; + command: CreateCommand; +} diff --git a/alfa-client/libs/command-shared/src/lib/command.repository.spec.ts b/alfa-client/libs/command-shared/src/lib/command.repository.spec.ts index dafb7b227a1390a4f97ee3223656fc2626fb18b2..1b90ac82a2d66db52066ddc4ec6af5b775f64f10 100644 --- a/alfa-client/libs/command-shared/src/lib/command.repository.spec.ts +++ b/alfa-client/libs/command-shared/src/lib/command.repository.spec.ts @@ -25,158 +25,162 @@ import { faker } from '@faker-js/faker'; import { mock, useFromMock } from '@alfa-client/test-utils'; import { Resource, ResourceFactory } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; -import { createCommand, createCommandListResource, createCommandResource } from 'libs/command-shared/test/command'; +import { + createCommand, + createCommandListResource, + createCommandResource, +} from 'libs/command-shared/test/command'; import { toResource } from 'libs/tech-shared/test/resource'; import { CommandLinkRel } from './command.linkrel'; import { Command, CommandListResource, CommandResource, CommandStatus } from './command.model'; import { CommandRepository } from './command.repository'; describe('CommandRepository', () => { + let repository: CommandRepository; + let resourceFactory = mock(ResourceFactory); + let resourceWrapper = { post: jest.fn(), get: jest.fn(), patch: jest.fn() }; - let repository: CommandRepository; - let resourceFactory = mock(ResourceFactory); - let resourceWrapper = { post: jest.fn(), get: jest.fn(), patch: jest.fn() }; + const command: Command = createCommand(); + const commandResource: CommandResource = createCommandResource(); + const commandListResource: CommandListResource = createCommandListResource(); + const commandResourceWithPendingCommand: CommandResource = createCommandResource([ + 'pendingCommands', + ]); - const command: Command = createCommand(); - const commandResource: CommandResource = createCommandResource(); - const commandListResource: CommandListResource = createCommandListResource(); - const commandResourceWithPendingCommand: CommandResource = createCommandResource(['pendingCommands']); + beforeEach(() => { + repository = new CommandRepository(useFromMock(resourceFactory)); + resourceFactory.from.mockReturnValue(resourceWrapper); + }); - beforeEach(() => { - repository = new CommandRepository(useFromMock(resourceFactory)); - resourceFactory.from.mockReturnValue(resourceWrapper); - }) + describe('create command', () => { + const linkRel: string = faker.random.word(); + const resource: Resource = toResource({}, [linkRel]); - describe('create command', () => { + beforeEach(() => { + resourceWrapper.post.mockReturnValue(hot('a', { a: commandResource })); + }); - const linkRel: string = faker.random.word(); - const resource: Resource = toResource({}, [linkRel]); + it('should call resourceFactory with resource', () => { + repository.createCommand(resource, linkRel, command); - beforeEach(() => { - resourceWrapper.post.mockReturnValue(hot('a', { a: commandResource })); - }) + expect(resourceFactory.from).toHaveBeenCalledWith(resource); + }); - it('should call resourceFactory with resource', () => { - repository.createCommand(resource, linkRel, command); + it('should call resourceWrapper with linkel and command', () => { + repository.createCommand(resource, linkRel, command); - expect(resourceFactory.from).toHaveBeenCalledWith(resource); - }) + expect(resourceWrapper.post).toHaveBeenCalledWith(linkRel, command); + }); - it('should call resourceWrapper with linkel and command', () => { - repository.createCommand(resource, linkRel, command); + it('should return value', () => { + const expected: CommandResource = commandResource; - expect(resourceWrapper.post).toHaveBeenCalledWith(linkRel, command); - }) + const result = repository.createCommand(resource, linkRel, command); - it('should return value', () => { - const expected: CommandResource = commandResource; + expect(result).toBeObservable(cold('a', { a: expected })); + }); + }); - const result = repository.createCommand(resource, linkRel, command); + describe('get command', () => { + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: commandResource })); + }); - expect(result).toBeObservable(cold('a', { a: expected })); - }) - }) + it('should call resourceFactory with resource', () => { + repository.getCommand(commandResource); - describe('get command', () => { + expect(resourceFactory.from).toHaveBeenCalledWith(commandResource); + }); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: commandResource })); - }) + it('should call resourceWrapper with selfLink', () => { + repository.getCommand(commandResource); - it('should call resourceFactory with resource', () => { - repository.getCommand(commandResource); + expect(resourceWrapper.get).toHaveBeenCalledWith(CommandLinkRel.SELF); + }); - expect(resourceFactory.from).toHaveBeenCalledWith(commandResource); - }) + it('should return value', () => { + const result = repository.getCommand(commandResource); - it('should call resourceWrapper with selfLink', () => { - repository.getCommand(commandResource); + expect(result).toBeObservable(cold('a', { a: commandResource })); + }); + }); - expect(resourceWrapper.get).toHaveBeenCalledWith(CommandLinkRel.SELF); - }) + describe('revoke command', () => { + beforeEach(() => { + resourceWrapper.patch.mockReturnValue(hot('a', { a: commandResource })); + }); - it('should return value', () => { - const result = repository.getCommand(commandResource); + it('should call resourceFactory with Resource', () => { + repository.revokeCommand(commandResource); - expect(result).toBeObservable(cold('a', { a: commandResource })); - }) - }) + expect(resourceFactory.from).toHaveBeenCalledWith(commandResource); + }); - describe('revoke command', () => { + it('should call resourceWrapper with revokeLinkRel and command order', () => { + repository.revokeCommand(commandResource); - beforeEach(() => { - resourceWrapper.patch.mockReturnValue(hot('a', { a: commandResource })); - }) + expect(resourceWrapper.patch).toHaveBeenCalledWith(CommandLinkRel.REVOKE, { + status: CommandStatus.REVOKED, + }); + }); - it('should call resourceFactory with Resource', () => { - repository.revokeCommand(commandResource); + it('should return value', () => { + const result = repository.revokeCommand(commandResource); - expect(resourceFactory.from).toHaveBeenCalledWith(commandResource); - }) + expect(result).toBeObservable(cold('a', { a: commandResource })); + }); + }); - it('should call resourceWrapper with revokeLinkRel and command order', () => { - repository.revokeCommand(commandResource); + describe('get pending commands', () => { + const linkRel = 'pendingCommands'; - expect(resourceWrapper.patch).toHaveBeenCalledWith(CommandLinkRel.REVOKE, { status: CommandStatus.REVOKED }) - }) + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: commandListResource })); + }); - it('should return value', () => { - const result = repository.revokeCommand(commandResource); + it('should call resourceFactory with resource', () => { + repository.getPendingCommands(commandResourceWithPendingCommand, linkRel); - expect(result).toBeObservable(cold('a', { a: commandResource })); - }) - }) + expect(resourceFactory.from).toHaveBeenCalledWith(commandResourceWithPendingCommand); + }); - describe('get pending commands', () => { - const linkRel = 'pendingCommands'; + it('should call resourceWrapper with linkRel', () => { + repository.getPendingCommands(commandResourceWithPendingCommand, linkRel); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: commandListResource })); - }) + expect(resourceWrapper.get).toHaveBeenCalledWith(linkRel); + }); - it('should call resourceFactory with resource', () => { - repository.getPendingCommands(commandResourceWithPendingCommand, linkRel); + it('should return value', () => { + const result = repository.getPendingCommands(commandResourceWithPendingCommand, linkRel); - expect(resourceFactory.from).toHaveBeenCalledWith(commandResourceWithPendingCommand); - }) + expect(result).toBeObservable(cold('a', { a: commandListResource })); + }); + }); - it('should call resourceWrapper with linkRel', () => { - repository.getPendingCommands(commandResourceWithPendingCommand, linkRel); + describe('get effected resource', () => { + const command: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); + const listResource = {}; - expect(resourceWrapper.get).toHaveBeenCalledWith(linkRel); - }) + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: listResource })); + }); - it('should return value', () => { - const result = repository.getPendingCommands(commandResourceWithPendingCommand, linkRel); + it('should call resourceFactory with resource', () => { + repository.getEffectedResource(command); - expect(result).toBeObservable(cold('a', { a: commandListResource })); - }) - }) + expect(resourceFactory.from).toHaveBeenCalledWith(command); + }); - describe('get effected resource', () => { - const command: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); - const listResource = {}; + it('should call resourceWrapper with linkRel', () => { + repository.getEffectedResource(command); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: listResource })); - }) + expect(resourceWrapper.get).toHaveBeenCalledWith(CommandLinkRel.EFFECTED_RESOURCE); + }); - it('should call resourceFactory with resource', () => { - repository.getEffectedResource(command); + it('should return value', () => { + const result = repository.getEffectedResource(command); - expect(resourceFactory.from).toHaveBeenCalledWith(command); - }) - - it('should call resourceWrapper with linkRel', () => { - repository.getEffectedResource(command); - - expect(resourceWrapper.get).toHaveBeenCalledWith(CommandLinkRel.EFFECTED_RESOURCE); - }) - - it('should return value', () => { - const result = repository.getEffectedResource(command); - - expect(result).toBeObservable(cold('a', { a: listResource })); - }) - }) -}) + expect(result).toBeObservable(cold('a', { a: listResource })); + }); + }); +}); diff --git a/alfa-client/libs/command-shared/src/lib/command.repository.ts b/alfa-client/libs/command-shared/src/lib/command.repository.ts index 60b918b6fd9e6fc776294964fb50ba38cb2b6b56..ca605bf9dba6b57c9ebc7a38eacd193459fb4882 100644 --- a/alfa-client/libs/command-shared/src/lib/command.repository.ts +++ b/alfa-client/libs/command-shared/src/lib/command.repository.ts @@ -25,30 +25,40 @@ import { Injectable } from '@angular/core'; import { Resource, ResourceFactory } from '@ngxp/rest'; import { Observable } from 'rxjs'; import { CommandLinkRel } from './command.linkrel'; -import { CommandListResource, CommandResource, CommandStatus, CreateCommand } from './command.model'; +import { + CommandListResource, + CommandResource, + CommandStatus, + CreateCommand, +} from './command.model'; @Injectable({ providedIn: 'root' }) export class CommandRepository { + constructor(private resourceFactory: ResourceFactory) {} - constructor(private resourceFactory: ResourceFactory) { } + public createCommand( + resource: Resource, + linkrel: string, + command: CreateCommand, + ): Observable<CommandResource> { + return this.resourceFactory.from(resource).post(linkrel, command); + } - public createCommand(resource: Resource, linkrel: string, command: CreateCommand): Observable<CommandResource> { - return this.resourceFactory.from(resource).post(linkrel, command); - } + public getCommand(resource: CommandResource): Observable<CommandResource> { + return this.resourceFactory.from(resource).get(CommandLinkRel.SELF); + } - public getCommand(resource: CommandResource): Observable<CommandResource> { - return this.resourceFactory.from(resource).get(CommandLinkRel.SELF); - } + public getPendingCommands(resource: Resource, linkRel: string): Observable<CommandListResource> { + return this.resourceFactory.from(resource).get(linkRel); + } - public getPendingCommands(resource: Resource, linkRel: string): Observable<CommandListResource> { - return this.resourceFactory.from(resource).get(linkRel); - } + public revokeCommand(resource: CommandResource): Observable<CommandResource> { + return this.resourceFactory + .from(resource) + .patch(CommandLinkRel.REVOKE, { status: CommandStatus.REVOKED }); + } - public revokeCommand(resource: CommandResource): Observable<CommandResource> { - return this.resourceFactory.from(resource).patch(CommandLinkRel.REVOKE, { status: CommandStatus.REVOKED }); - } - - public getEffectedResource<T>(command: CommandResource): Observable<T> { - return this.resourceFactory.from(command).get(CommandLinkRel.EFFECTED_RESOURCE); - } -} \ No newline at end of file + public getEffectedResource<T>(command: CommandResource): Observable<T> { + return this.resourceFactory.from(command).get(CommandLinkRel.EFFECTED_RESOURCE); + } +} diff --git a/alfa-client/libs/command-shared/src/lib/command.service.spec.ts b/alfa-client/libs/command-shared/src/lib/command.service.spec.ts index 6774722a794ac78934180a351835fb842b56f7cf..accdc2c0e8e6b6864c828e5074b37922cafff76f 100644 --- a/alfa-client/libs/command-shared/src/lib/command.service.spec.ts +++ b/alfa-client/libs/command-shared/src/lib/command.service.spec.ts @@ -21,7 +21,12 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { StateResource, createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { SnackBarService } from '@alfa-client/ui'; import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; @@ -29,350 +34,382 @@ import { faker } from '@faker-js/faker'; import { Store } from '@ngrx/store'; import { Resource } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; -import { createCommand, createCommandErrorResource, createCommandListResource, createCommandResource, createCreateCommand, createCreateCommandProps } from 'libs/command-shared/test/command'; +import { + createCommand, + createCommandErrorResource, + createCommandListResource, + createCommandResource, + createCreateCommand, + createCreateCommandProps, +} from 'libs/command-shared/test/command'; import { createHttpErrorResponse } from 'libs/tech-shared/test/http'; import { toResource } from 'libs/tech-shared/test/resource'; import { Observable, Subject, of, throwError } from 'rxjs'; import { CommandLinkRel } from './command.linkrel'; import { CommandErrorMessage } from './command.message'; -import { Command, CommandListResource, CommandResource, CreateCommand, CreateCommandProps } from './command.model'; +import { + Command, + CommandListResource, + CommandResource, + CreateCommand, + CreateCommandProps, +} from './command.model'; import { CommandRepository } from './command.repository'; -import { CommandService, IntervallHandleWithTickObservable, startInterval } from './command.service'; +import { + CommandService, + IntervallHandleWithTickObservable, + startInterval, +} from './command.service'; import * as Actions from './+state/command.actions'; import * as Selectors from './+state/command.selectors'; describe('CommandService', () => { - let service: CommandService; - let repository: Mock<CommandRepository>; - let store: Mock<Store>; - let selectionSubject: Subject<any>; + let service: CommandService; + let repository: Mock<CommandRepository>; + let store: Mock<Store>; + let selectionSubject: Subject<any>; - const snackbarService: Mock<SnackBarService> = mock(SnackBarService); + const snackbarService: Mock<SnackBarService> = mock(SnackBarService); - const command: Command = createCommand(); + const command: Command = createCommand(); - const commandResource: CommandResource = createCommandResource(); - const commandStateResource: StateResource<CommandResource> = createStateResource(commandResource); + const commandResource: CommandResource = createCommandResource(); + const commandStateResource: StateResource<CommandResource> = createStateResource(commandResource); - const commandResourceWithUpdateLink: CommandResource = createCommandResource([CommandLinkRel.UPDATE]); + const commandResourceWithUpdateLink: CommandResource = createCommandResource([ + CommandLinkRel.UPDATE, + ]); - beforeEach(() => { - store = mock(Store); - selectionSubject = new Subject(); - store.select.mockReturnValue(selectionSubject); - store.dispatch = jest.fn(); + beforeEach(() => { + store = mock(Store); + selectionSubject = new Subject(); + store.select.mockReturnValue(selectionSubject); + store.dispatch = jest.fn(); - repository = mock(CommandRepository); - service = new CommandService(useFromMock(repository), useFromMock(snackbarService), useFromMock(<any>store)); - }) + repository = mock(CommandRepository); + service = new CommandService( + useFromMock(repository), + useFromMock(snackbarService), + useFromMock(<any>store), + ); + }); - describe('create command', () => { + describe('create command', () => { + const resource: Resource = toResource({}); + const linkRel: string = faker.random.word(); - const resource: Resource = toResource({}); - const linkRel: string = faker.random.word(); + beforeEach(() => { + repository.createCommand.mockReturnValue(cold('a', { a: commandResourceWithUpdateLink })); + }); - beforeEach(() => { - repository.createCommand.mockReturnValue(cold('a', { a: commandResourceWithUpdateLink })); - }) + it('should call repository with resource, linkrel and command', () => { + service.createCommand(resource, linkRel, command); - it('should call repository with resource, linkrel and command', () => { - service.createCommand(resource, linkRel, command); + expect(repository.createCommand).toHaveBeenCalledWith(resource, linkRel, command); + }); + + it('should call handleHttpError', () => { + const errorResponse: HttpErrorResponse = createHttpErrorResponse(); + repository.createCommand.mockReturnValue(throwError(errorResponse)); + service.handleHttpError = jest.fn(); + + service.createCommand(resource, linkRel, command).subscribe(); + + expect(service.handleHttpError).toHaveBeenCalledWith(errorResponse); + }); + + it('should call handleCommand', () => { + repository.createCommand.mockReturnValue(of(commandResource)); + service.handleCommand = jest.fn(); + + service.createCommand(resource, linkRel, command).subscribe(); + + expect(service.handleCommand).toHaveBeenCalledWith(commandResource); + }); + }); + + describe('revoke command', () => { + beforeEach(() => { + repository.revokeCommand.mockReturnValue(cold('a', { a: commandResource })); + }); + + it('should call repository with resource, linkrel and command', () => { + service.revokeCommand(commandResource); + + expect(repository.revokeCommand).toHaveBeenCalledWith(commandResource); + }); + + it('should call handleHttpError', () => { + const errorResponse: HttpErrorResponse = createHttpErrorResponse(); + repository.revokeCommand.mockReturnValue(throwError(errorResponse)); + service.handleHttpError = jest.fn(); + + service.revokeCommand(commandResource).subscribe(); + + expect(service.handleHttpError).toHaveBeenCalledWith(errorResponse); + }); + + it('should call handleCommand', () => { + repository.revokeCommand.mockReturnValue(of(commandResource)); + service.handleCommand = jest.fn(); + + service.revokeCommand(commandResource).subscribe(); + + expect(service.handleCommand).toHaveBeenCalledWith(commandResource); + }); + + describe('process command with status in progress(with update link)', () => { + beforeEach(() => { + repository.revokeCommand.mockReturnValue(cold('a', { a: commandResourceWithUpdateLink })); + service.pollCommand = jest.fn(); + (<any>service.pollCommand).mockReturnValue( + cold('a', { a: createStateResource(commandResourceWithUpdateLink, true) }), + ); + }); + + it('should return value with loading true', () => { + const result = service.revokeCommand(commandResource); + + expect(result).toBeObservable( + hot('a', { a: createStateResource(commandResourceWithUpdateLink, true) }), + ); + }); + }); + + describe('process command with status done(no update link)', () => { + it('should return value with loading false', () => { + const result = service.revokeCommand(commandResource); + + expect(result).toBeObservable(hot('a', { a: commandStateResource })); + }); + }); + }); + + describe('handleCommand', () => { + it.skip('should call handleCommandError', () => { + service.handleCommandError = jest.fn(); + const commandWithError: CommandResource = createCommandErrorResource(); + service.handleCommand(commandWithError); + + expect(service.handleCommandError).toHaveBeenCalledWith(commandWithError); + }); + + it('should call startPolling', () => { + const commandWithoutError: CommandResource = { + ...createCommandResource(), + errorMessage: null, + }; + service.startPolling = jest.fn(); + service.handleCommand(commandWithoutError); - expect(repository.createCommand).toHaveBeenCalledWith(resource, linkRel, command); - }) + expect(service.startPolling).toHaveBeenCalledWith(commandWithoutError); + }); + + describe.skip('handleCommandError', () => { + describe('on concurrent modifiation error', () => { + it('should call snackBarService on concurrentModification error', () => { + service.handleCommandError({ + ...commandResource, + errorMessage: CommandErrorMessage.CONCURRENT_MODIFICATION, + }); + + expect(snackbarService.showError).toHaveBeenCalledWith( + 'Der Vorgang wurde zwischenzeitlich verändert und wurde neu geladen.', + ); + }); + + it('should dispatch "dispatchConcurrentModificationCommand" action', () => { + service.handleCommandError({ + ...commandResource, + errorMessage: CommandErrorMessage.CONCURRENT_MODIFICATION, + }); + + expect(store.dispatch).toHaveBeenCalledWith(Actions.publishConcurrentModificationAction); + }); + }); + + it('should return command as stateResource', () => { + service.handleCommandError(commandResource).subscribe(() => { + expect(commandStateResource).toEqual(createStateResource(commandResource)); + }); + }); + }); + }); + + describe('handle interval', () => { + const interval: IntervallHandleWithTickObservable = { handle: 0, tickObservable: of(null) }; + + beforeEach(() => { + service.clearInterval = jest.fn(); + }); + + it('should call clearInterval', () => { + service.handleInterval(createEmptyStateResource(), interval); + + expect(service.clearInterval).toHaveBeenCalledWith(interval.handle); + }); + + it('should NOT call clearInterval', () => { + service.handleInterval(createEmptyStateResource(true), interval); + + expect(service.clearInterval).not.toHaveBeenCalled(); + }); + }); + + describe('getAndUpdate', () => { + beforeEach(() => { + repository.getCommand.mockReturnValue(cold('a', { a: commandResourceWithUpdateLink })); + }); + + it('should call getCommand', () => { + service.getAndUpdate(commandResource); + + expect(repository.getCommand).toHaveBeenCalled(); + }); - it('should call handleHttpError', () => { - const errorResponse: HttpErrorResponse = createHttpErrorResponse(); - repository.createCommand.mockReturnValue(throwError(errorResponse)); - service.handleHttpError = jest.fn(); + it('should return stateResource still loading', () => { + const result = service.getAndUpdate(commandResource); - service.createCommand(resource, linkRel, command).subscribe(); + expect(result).toBeObservable( + hot('a', { a: createStateResource(commandResourceWithUpdateLink, true) }), + ); + }); - expect(service.handleHttpError).toHaveBeenCalledWith(errorResponse); - }) + describe('command is loaded', () => { + beforeEach(() => { + repository.getCommand.mockReturnValue(cold('a', { a: commandResource })); + }); - it('should call handleCommand', () => { - repository.createCommand.mockReturnValue(of(commandResource)); - service.handleCommand = jest.fn(); + it('should loaded stateResource', () => { + const result = service.getAndUpdate(commandResource); + + expect(result).toBeObservable(hot('a', { a: createStateResource(commandResource) })); + }); + }); + }); - service.createCommand(resource, linkRel, command).subscribe(); + describe('get command', () => { + beforeEach(() => { + repository.getCommand.mockReturnValue(cold('a', { a: commandResource })); + }); - expect(service.handleCommand).toHaveBeenCalledWith(commandResource); - }) - }) + it('should call repository with resource', () => { + service.getCommand(commandResource); - describe('revoke command', () => { + expect(repository.getCommand).toHaveBeenCalledWith(commandResource); + }); - beforeEach(() => { - repository.revokeCommand.mockReturnValue(cold('a', { a: commandResource })); - }) + it('should return value', () => { + const result = service.getCommand(commandResource); - it('should call repository with resource, linkrel and command', () => { - service.revokeCommand(commandResource); + expect(result).toBeObservable(hot('a', { a: commandResource })); + }); + }); - expect(repository.revokeCommand).toHaveBeenCalledWith(commandResource); - }) + describe('get effected resource', () => { + const listResource = {}; + const command: CommandResource = createCommandResource(); - it('should call handleHttpError', () => { - const errorResponse: HttpErrorResponse = createHttpErrorResponse(); - repository.revokeCommand.mockReturnValue(throwError(errorResponse)); - service.handleHttpError = jest.fn(); + beforeEach(() => { + repository.getEffectedResource.mockReturnValue(cold('a', { a: listResource })); + }); - service.revokeCommand(commandResource).subscribe(); + it('should call repository', () => { + service.getEffectedResource(command); - expect(service.handleHttpError).toHaveBeenCalledWith(errorResponse); - }) + expect(repository.getEffectedResource).toHaveBeenCalledWith(command); + }); - it('should call handleCommand', () => { - repository.revokeCommand.mockReturnValue(of(commandResource)); - service.handleCommand = jest.fn(); + it('should return value', () => { + const result = service.getEffectedResource(command); - service.revokeCommand(commandResource).subscribe(); + expect(result).toBeObservable(hot('a', { a: listResource })); + }); + }); - expect(service.handleCommand).toHaveBeenCalledWith(commandResource); - }) + describe('get pending commands', () => { + const commandListResource: CommandListResource = createCommandListResource(); - describe('process command with status in progress(with update link)', () => { + beforeEach(() => { + repository.getPendingCommands.mockReturnValue(cold('a', { a: commandListResource })); + }); - beforeEach(() => { - repository.revokeCommand.mockReturnValue(cold('a', { a: commandResourceWithUpdateLink })); - service.pollCommand = jest.fn(); - (<any>service.pollCommand).mockReturnValue(cold('a', { a: createStateResource(commandResourceWithUpdateLink, true) })); - }) + it('should call repository', () => { + service.getPendingCommands(commandResource, CommandLinkRel.SELF); - it('should return value with loading true', () => { - const result = service.revokeCommand(commandResource); + expect(repository.getPendingCommands).toHaveBeenLastCalledWith( + commandResource, + CommandLinkRel.SELF, + ); + }); + }); - expect(result).toBeObservable(hot('a', { a: createStateResource(commandResourceWithUpdateLink, true) })); - }) - }) + describe('start interval', () => { + const intervall: number = 100; - describe('process command with status done(no update link)', () => { + it('should not be null', () => { + const result = startInterval(intervall); - it('should return value with loading false', () => { - const result = service.revokeCommand(commandResource); + expect(result).not.toBeNull(); + }); - expect(result).toBeObservable(hot('a', { a: commandStateResource })); - }) - }) - }) + it('should have handle not null', () => { + const result = startInterval(intervall); - describe('handleCommand', () => { + expect(result.handle).not.toBeNull(); + }); - it.skip('should call handleCommandError', () => { - service.handleCommandError = jest.fn(); - const commandWithError: CommandResource = createCommandErrorResource(); - service.handleCommand(commandWithError); + it('should have tick as observable', () => { + const result = startInterval(intervall); - expect(service.handleCommandError).toHaveBeenCalledWith(commandWithError); - }) + expect(result.tickObservable).toBeInstanceOf(Observable); + }); + }); - it('should call startPolling', () => { - const commandWithoutError: CommandResource = {...createCommandResource(), errorMessage: null}; - service.startPolling = jest.fn(); - service.handleCommand(commandWithoutError); + describe('handleErrorByStatus', () => { + const errorResponse: HttpErrorResponse = createHttpErrorResponse(); - expect(service.startPolling).toHaveBeenCalledWith(commandWithoutError); - }) + it('should return error state resource on status 422', () => { + const result = service.handleErrorByStatus({ + ...errorResponse, + status: HttpStatusCode.UnprocessableEntity, + }); - describe.skip('handleCommandError', () => { + expect(result).toEqual(createErrorStateResource(errorResponse.error)); + }); + }); - describe('on concurrent modifiation error', () => { - it('should call snackBarService on concurrentModification error', () => { - service.handleCommandError({...commandResource, errorMessage: CommandErrorMessage.CONCURRENT_MODIFICATION}); + describe('createCommandByProps', () => { + const command: CreateCommand = createCreateCommand(); + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + const createCommandProps: CreateCommandProps = { ...createCreateCommandProps(), command }; - expect(snackbarService.showError).toHaveBeenCalledWith('Der Vorgang wurde zwischenzeitlich verändert und wurde neu geladen.'); - }) + it('should dispatch action', () => { + service.createCommandByProps(createCommandProps); - it('should dispatch "dispatchConcurrentModificationCommand" action', () => { - service.handleCommandError({...commandResource, errorMessage: CommandErrorMessage.CONCURRENT_MODIFICATION}); + expect(store.dispatch).toHaveBeenCalledWith(Actions.createCommand(createCommandProps)); + }); - expect(store.dispatch).toHaveBeenCalledWith(Actions.publishConcurrentModificationAction); - }) - }) + it('should call selector', (done) => { + const selectorSpy = jest.spyOn(Selectors, 'commandByOrder'); - it('should return command as stateResource', () => { - service.handleCommandError(commandResource).subscribe(() => { - expect(commandStateResource).toEqual(createStateResource(commandResource)); - }); - }) - }) - }) + service.createCommandByProps(createCommandProps).subscribe(() => { + expect(selectorSpy).toHaveBeenCalledWith(command.order); + done(); + }); - describe('handle interval', () => { + selectionSubject.next(commandStateResource); + }); - const interval: IntervallHandleWithTickObservable = { handle: 0, tickObservable: of(null) }; + it('should return selected command', (done) => { + service.createCommandByProps(createCommandProps).subscribe((selected) => { + expect(selected).toBe(commandStateResource); + done(); + }); - beforeEach(() => { - service.clearInterval = jest.fn(); - }) - - it('should call clearInterval', () => { - service.handleInterval(createEmptyStateResource(), interval); - - expect(service.clearInterval).toHaveBeenCalledWith(interval.handle); - }) - - it('should NOT call clearInterval', () => { - service.handleInterval(createEmptyStateResource(true), interval); - - expect(service.clearInterval).not.toHaveBeenCalled(); - }) - }) - - describe('getAndUpdate', () => { - - beforeEach(() => { - repository.getCommand.mockReturnValue(cold('a', { a: commandResourceWithUpdateLink })); - }) - - it('should call getCommand', () => { - service.getAndUpdate(commandResource); - - expect(repository.getCommand).toHaveBeenCalled(); - }) - - it('should return stateResource still loading', () => { - const result = service.getAndUpdate(commandResource); - - expect(result).toBeObservable(hot('a', { a: createStateResource(commandResourceWithUpdateLink, true) })); - }) - - describe('command is loaded', () => { - - beforeEach(() => { - repository.getCommand.mockReturnValue(cold('a', { a: commandResource })); - }) - - it('should loaded stateResource', () => { - const result = service.getAndUpdate(commandResource); - - expect(result).toBeObservable(hot('a', { a: createStateResource(commandResource) })); - }) - }) - }) - - describe('get command', () => { - - beforeEach(() => { - repository.getCommand.mockReturnValue(cold('a', { a: commandResource })); - }) - - it('should call repository with resource', () => { - service.getCommand(commandResource); - - expect(repository.getCommand).toHaveBeenCalledWith(commandResource); - }) - - it('should return value', () => { - const result = service.getCommand(commandResource); - - expect(result).toBeObservable(hot('a', { a: commandResource })) - }) - }) - - describe('get effected resource', () => { - - const listResource = {}; - const command: CommandResource = createCommandResource(); - - beforeEach(() => { - repository.getEffectedResource.mockReturnValue(cold('a', { a: listResource })); - }) - - it('should call repository', () => { - service.getEffectedResource(command); - - expect(repository.getEffectedResource).toHaveBeenCalledWith(command); - }) - - it('should return value', () => { - const result = service.getEffectedResource(command); - - expect(result).toBeObservable(hot('a', { a: listResource })) - }) - }) - - describe('get pending commands', () => { - - const commandListResource: CommandListResource = createCommandListResource(); - - beforeEach(() => { - repository.getPendingCommands.mockReturnValue(cold('a', { a: commandListResource })); - }) - - it('should call repository', () => { - service.getPendingCommands(commandResource, CommandLinkRel.SELF); - - expect(repository.getPendingCommands).toHaveBeenLastCalledWith(commandResource, CommandLinkRel.SELF); - }) - }) - - describe('start interval', () => { - - const intervall: number = 100; - - it('should not be null', () => { - const result = startInterval(intervall); - - expect(result).not.toBeNull(); - }) - - it('should have handle not null', () => { - const result = startInterval(intervall); - - expect(result.handle).not.toBeNull(); - }) - - it('should have tick as observable', () => { - const result = startInterval(intervall); - - expect(result.tickObservable).toBeInstanceOf(Observable); - }) - }) - - describe('handleErrorByStatus', () => { - - const errorResponse: HttpErrorResponse = createHttpErrorResponse(); - - it('should return error state resource on status 422', () => { - const result = service.handleErrorByStatus({ ...errorResponse, status: HttpStatusCode.UnprocessableEntity }); - - expect(result).toEqual(createErrorStateResource(errorResponse.error)); - }) - }) - - describe('createCommandByProps', () => { - - const command: CreateCommand = createCreateCommand(); - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); - const createCommandProps: CreateCommandProps = { ...createCreateCommandProps(), command }; - - it('should dispatch action', () => { - service.createCommandByProps(createCommandProps); - - expect(store.dispatch).toHaveBeenCalledWith(Actions.createCommand(createCommandProps)); - }) - - it('should call selector', (done) => { - const selectorSpy = jest.spyOn(Selectors, 'commandByOrder'); - - service.createCommandByProps(createCommandProps).subscribe(() => { - expect(selectorSpy).toHaveBeenCalledWith(command.order); - done(); - }); - - selectionSubject.next(commandStateResource); - }) - - it('should return selected command', (done) => { - service.createCommandByProps(createCommandProps).subscribe(selected => { - expect(selected).toBe(commandStateResource); - done(); - }); - - selectionSubject.next(commandStateResource); - }) - }) -}) \ No newline at end of file + selectionSubject.next(commandStateResource); + }); + }); +}); diff --git a/alfa-client/libs/command-shared/src/lib/command.service.ts b/alfa-client/libs/command-shared/src/lib/command.service.ts index ff7d34b74a37491f9436b9fe86a2395c4def139a..4b8d283899be99e2d59c953e71718f2d60dd1c93 100644 --- a/alfa-client/libs/command-shared/src/lib/command.service.ts +++ b/alfa-client/libs/command-shared/src/lib/command.service.ts @@ -21,7 +21,12 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { createErrorStateResource, createStateResource, isUnprocessableEntity, StateResource } from '@alfa-client/tech-shared'; +import { + createErrorStateResource, + createStateResource, + isUnprocessableEntity, + StateResource, +} from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; import { HttpErrorResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; @@ -31,7 +36,12 @@ import { Observable, of, Subject, throwError } from 'rxjs'; import { catchError, map, mergeMap, tap } from 'rxjs/operators'; import { CommandEffects } from './+state/command.effects'; import { COMMAND_ERROR_MESSAGES } from './command.message'; -import { CommandListResource, CommandResource, CreateCommand, CreateCommandProps } from './command.model'; +import { + CommandListResource, + CommandResource, + CreateCommand, + CreateCommandProps, +} from './command.model'; import { CommandRepository } from './command.repository'; import { isConcurrentModification, isPending } from './command.util'; @@ -40,99 +50,118 @@ import * as Selectors from './+state/command.selectors'; @Injectable({ providedIn: 'root' }) export class CommandService { - - intervalTimer: number = CommandEffects.POLL_DELAY; - - constructor(private repository: CommandRepository, private snackBarService: SnackBarService, private store: Store) { } - - public createCommand(resource: Resource, linkRel: string, command: CreateCommand): Observable<StateResource<CommandResource>> { - return this.handleCommandResponse(this.repository.createCommand(resource, linkRel, command)); - } - - public revokeCommand(resource: CommandResource): Observable<StateResource<CommandResource>> { - return this.handleCommandResponse(this.repository.revokeCommand(resource)); - } - - private handleCommandResponse(command$: Observable<CommandResource>): Observable<StateResource<CommandResource>> { - return command$.pipe( - mergeMap(command => this.handleCommand(command)), - catchError(errorResponse => this.handleHttpError(errorResponse))); - } - - handleHttpError(errorResponse: HttpErrorResponse): Observable<StateResource<CommandResource>> { - return of(this.handleErrorByStatus(errorResponse)); - } - - handleErrorByStatus(error: HttpErrorResponse): StateResource<CommandResource> { - if (isUnprocessableEntity(error.status)) { - return createErrorStateResource(error.error); - } - throwError({ error }); - } - - handleCommand(command: CommandResource): Observable<StateResource<CommandResource>> { - return this.startPolling(command); - } - - handleCommandError(command: CommandResource): Observable<StateResource<CommandResource>> { - if(isConcurrentModification(command.errorMessage)){ - this.snackBarService.showError(COMMAND_ERROR_MESSAGES[command.errorMessage]); - this.store.dispatch(Actions.publishConcurrentModificationAction()); - } - return of(createStateResource(command)); - } - - startPolling(commandResource: CommandResource): Observable<StateResource<CommandResource>> { - return isPending(commandResource) ? this.pollCommand(commandResource) : of(createStateResource(commandResource)); - } - - public pollCommand(commandResource: CommandResource): Observable<StateResource<CommandResource>> { - const interval: IntervallHandleWithTickObservable = startInterval(this.intervalTimer); - return interval.tickObservable.pipe( - mergeMap(() => this.getAndUpdate(commandResource)), - tap(stateResource => this.handleInterval(stateResource, interval)) - ) - } - - handleInterval(stateResource: StateResource<CommandResource>, interval: IntervallHandleWithTickObservable): void { - if (!stateResource.loading) this.clearInterval(interval.handle); - } - - getAndUpdate(commandResource: CommandResource): Observable<StateResource<CommandResource>> { - return this.getCommand(commandResource).pipe(map(res => createStateResource(res, isPending(res)))); - } - - getCommand(resource: CommandResource): Observable<CommandResource> { - return this.repository.getCommand(resource); - } - - clearInterval(handler: number): void { - window.clearInterval(handler); - } - - public getPendingCommands(resource: Resource, linkRel: string): Observable<CommandListResource> { - return this.repository.getPendingCommands(resource, linkRel); - } - - public getEffectedResource<T>(command: CommandResource): Observable<T> { - return this.repository.getEffectedResource(command); - } - - public createCommandByProps(createCommandProps: CreateCommandProps): Observable<StateResource<CommandResource>> { - this.store.dispatch(Actions.createCommand(createCommandProps)); - return this.store.select(Selectors.commandByOrder(createCommandProps.command.order)); - } + intervalTimer: number = CommandEffects.POLL_DELAY; + + constructor( + private repository: CommandRepository, + private snackBarService: SnackBarService, + private store: Store, + ) {} + + public createCommand( + resource: Resource, + linkRel: string, + command: CreateCommand, + ): Observable<StateResource<CommandResource>> { + return this.handleCommandResponse(this.repository.createCommand(resource, linkRel, command)); + } + + public revokeCommand(resource: CommandResource): Observable<StateResource<CommandResource>> { + return this.handleCommandResponse(this.repository.revokeCommand(resource)); + } + + private handleCommandResponse( + command$: Observable<CommandResource>, + ): Observable<StateResource<CommandResource>> { + return command$.pipe( + mergeMap((command) => this.handleCommand(command)), + catchError((errorResponse) => this.handleHttpError(errorResponse)), + ); + } + + handleHttpError(errorResponse: HttpErrorResponse): Observable<StateResource<CommandResource>> { + return of(this.handleErrorByStatus(errorResponse)); + } + + handleErrorByStatus(error: HttpErrorResponse): StateResource<CommandResource> { + if (isUnprocessableEntity(error.status)) { + return createErrorStateResource(error.error); + } + throwError({ error }); + } + + handleCommand(command: CommandResource): Observable<StateResource<CommandResource>> { + return this.startPolling(command); + } + + handleCommandError(command: CommandResource): Observable<StateResource<CommandResource>> { + if (isConcurrentModification(command.errorMessage)) { + this.snackBarService.showError(COMMAND_ERROR_MESSAGES[command.errorMessage]); + this.store.dispatch(Actions.publishConcurrentModificationAction()); + } + return of(createStateResource(command)); + } + + startPolling(commandResource: CommandResource): Observable<StateResource<CommandResource>> { + return isPending(commandResource) ? + this.pollCommand(commandResource) + : of(createStateResource(commandResource)); + } + + public pollCommand(commandResource: CommandResource): Observable<StateResource<CommandResource>> { + const interval: IntervallHandleWithTickObservable = startInterval(this.intervalTimer); + return interval.tickObservable.pipe( + mergeMap(() => this.getAndUpdate(commandResource)), + tap((stateResource) => this.handleInterval(stateResource, interval)), + ); + } + + handleInterval( + stateResource: StateResource<CommandResource>, + interval: IntervallHandleWithTickObservable, + ): void { + if (!stateResource.loading) this.clearInterval(interval.handle); + } + + getAndUpdate(commandResource: CommandResource): Observable<StateResource<CommandResource>> { + return this.getCommand(commandResource).pipe( + map((res) => createStateResource(res, isPending(res))), + ); + } + + getCommand(resource: CommandResource): Observable<CommandResource> { + return this.repository.getCommand(resource); + } + + clearInterval(handler: number): void { + window.clearInterval(handler); + } + + public getPendingCommands(resource: Resource, linkRel: string): Observable<CommandListResource> { + return this.repository.getPendingCommands(resource, linkRel); + } + + public getEffectedResource<T>(command: CommandResource): Observable<T> { + return this.repository.getEffectedResource(command); + } + + public createCommandByProps( + createCommandProps: CreateCommandProps, + ): Observable<StateResource<CommandResource>> { + this.store.dispatch(Actions.createCommand(createCommandProps)); + return this.store.select(Selectors.commandByOrder(createCommandProps.command.order)); + } } export interface IntervallHandleWithTickObservable { - handle: number, - tickObservable: Observable<any> + handle: number; + tickObservable: Observable<any>; } export function startInterval(interval: number): IntervallHandleWithTickObservable { - const subj: Subject<any> = new Subject(); - // Workaround: cast return value of setInterval() to number because since TS 4.8 it thinks it must be "Timer" - const handle = setInterval(() => subj.next('tick'), interval) as unknown as number; + const subj: Subject<any> = new Subject(); + // Workaround: cast return value of setInterval() to number because since TS 4.8 it thinks it must be "Timer" + const handle = setInterval(() => subj.next('tick'), interval) as unknown as number; - return { handle, tickObservable: subj.asObservable() }; + return { handle, tickObservable: subj.asObservable() }; } diff --git a/alfa-client/libs/command-shared/src/lib/command.util.spec.ts b/alfa-client/libs/command-shared/src/lib/command.util.spec.ts index 48bcb6df739d72e950d3811240117ad9e318ac19..cd3f65d6bda037c9552175f7b5c81cdfc821b70c 100644 --- a/alfa-client/libs/command-shared/src/lib/command.util.spec.ts +++ b/alfa-client/libs/command-shared/src/lib/command.util.spec.ts @@ -21,139 +21,155 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { createCommandErrorResource, createCommandListResource, createCommandResource } from 'libs/command-shared/test/command' -import { CommandLinkRel } from './command.linkrel' -import { CommandErrorMessage } from './command.message' -import { CommandListResource, CommandResource } from './command.model' -import { getPendingCommandByOrder, hasError, isConcurrentModification, isDone, isPending, isRevokeable, isSuccessfulDone } from './command.util' +import { + createCommandErrorResource, + createCommandListResource, + createCommandResource, +} from 'libs/command-shared/test/command'; +import { CommandLinkRel } from './command.linkrel'; +import { CommandErrorMessage } from './command.message'; +import { CommandListResource, CommandResource } from './command.model'; +import { + getPendingCommandByOrder, + hasError, + isConcurrentModification, + isDone, + isPending, + isRevokeable, + isSuccessfulDone, +} from './command.util'; describe('CommandUtil', () => { + describe('isRevokeable', () => { + it('should return true if Link exists', () => { + const result = isRevokeable(createCommandResource([CommandLinkRel.REVOKE])); - describe('isRevokeable', () => { - it('should return true if Link exists', () => { - const result = isRevokeable(createCommandResource([CommandLinkRel.REVOKE])) + expect(result).toBe(true); + }); + it('should return false if Link does NOT exists', () => { + const result = isRevokeable(createCommandResource()); - expect(result).toBe(true); - }) - it('should return false if Link does NOT exists', () => { - const result = isRevokeable(createCommandResource()) + expect(result).toBe(false); + }); + }); - expect(result).toBe(false); - }) - }) + describe('isPending', () => { + it('should return true if Link exists', () => { + const result = isPending(createCommandResource([CommandLinkRel.UPDATE])); - describe('isPending', () => { - it('should return true if Link exists', () => { - const result = isPending(createCommandResource([CommandLinkRel.UPDATE])) + expect(result).toBe(true); + }); + it('should return false if Link does NOT exists', () => { + const result = isPending(createCommandResource()); - expect(result).toBe(true); - }) - it('should return false if Link does NOT exists', () => { - const result = isPending(createCommandResource()) + expect(result).toBe(false); + }); + }); - expect(result).toBe(false); - }) - }) + describe('isDone', () => { + it('should return true if Link exists', () => { + const result = isDone(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE])); - describe('isDone', () => { - it('should return true if Link exists', () => { - const result = isDone(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE])) + expect(result).toBe(true); + }); + it('should return false if Link does NOT exists', () => { + const result = isDone(createCommandResource()); - expect(result).toBe(true); - }) - it('should return false if Link does NOT exists', () => { - const result = isDone(createCommandResource()) + expect(result).toBe(false); + }); + }); - expect(result).toBe(false); - }) - }) + describe('hasError', () => { + it('should be true if no update link is present and command has error message', () => { + const result = hasError(createCommandErrorResource()); - describe('hasError', () => { + expect(result).toBeTruthy(); + }); - it('should be true if no update link is present and command has error message', () => { - const result = hasError(createCommandErrorResource()); + it('should be false if update link is present', () => { + const result = hasError(createCommandResource([CommandLinkRel.UPDATE])); - expect(result).toBeTruthy(); - }) + expect(result).toBeFalsy(); + }); - it('should be false if update link is present', () => { - const result = hasError(createCommandResource([CommandLinkRel.UPDATE])); + it('should be false if error message is not present', () => { + const result = hasError(createCommandResource()); - expect(result).toBeFalsy(); - }) + expect(result).toBeFalsy(); + }); + }); - it('should be false if error message is not present', () => { - const result = hasError(createCommandResource()); + describe('getPendingCommandByOrder', () => { + const order: string = 'dummyOrder'; + const anotherOrder: string = 'anotherOrder'; - expect(result).toBeFalsy(); - }) - }) + it('should return null on non existing pending command', () => { + const listResource: CommandListResource = createCommandListResource(); - describe('getPendingCommandByOrder', () => { + const pendingCommand: CommandResource = getPendingCommandByOrder(listResource, [order]); - const order: string = 'dummyOrder'; - const anotherOrder: string = 'anotherOrder'; + expect(pendingCommand).toBeNull(); + }); - it('should return null on non existing pending command', () => { - const listResource: CommandListResource = createCommandListResource(); + it('should return existing pending command on single order', () => { + const command: CommandResource = { ...createCommandResource(), order }; + const listResource: CommandListResource = createCommandListResource([command]); - const pendingCommand: CommandResource = getPendingCommandByOrder(listResource, [order]); + const pendingCommand: CommandResource = getPendingCommandByOrder(listResource, [order]); - expect(pendingCommand).toBeNull(); - }) + expect(pendingCommand).toBe(command); + }); - it('should return existing pending command on single order', () => { - const command: CommandResource = { ...createCommandResource(), order }; - const listResource: CommandListResource = createCommandListResource([command]); + it('should return existing pending command on multiple orders', () => { + const command: CommandResource = { ...createCommandResource(), order: anotherOrder }; + const listResource: CommandListResource = createCommandListResource([command]); - const pendingCommand: CommandResource = getPendingCommandByOrder(listResource, [order]); + const pendingCommand: CommandResource = getPendingCommandByOrder(listResource, [ + order, + anotherOrder, + ]); - expect(pendingCommand).toBe(command); - }) + expect(pendingCommand).toBe(command); + }); + }); - it('should return existing pending command on multiple orders', () => { - const command: CommandResource = { ...createCommandResource(), order: anotherOrder }; - const listResource: CommandListResource = createCommandListResource([command]); + describe('isConcurrentModification', () => { + it('should return true on matching error message', () => { + const doesMatch: boolean = isConcurrentModification( + CommandErrorMessage.CONCURRENT_MODIFICATION, + ); - const pendingCommand: CommandResource = getPendingCommandByOrder(listResource, [order, anotherOrder]); + expect(doesMatch).toBeTruthy(); + }); + }); - expect(pendingCommand).toBe(command); - }) - }) + describe('isSuccessfulDone', () => { + it('should return true if command is done and has no error', () => { + const isDoneSuccessfuly: boolean = isSuccessfulDone({ + ...createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), + }); - describe('isConcurrentModification', () => { + expect(isDoneSuccessfuly).toBeTruthy(); + }); - it('should return true on matching error message', () => { - const doesMatch: boolean = isConcurrentModification(CommandErrorMessage.CONCURRENT_MODIFICATION); + it('should return false if command is done with error', () => { + const isDoneSuccessfuly: boolean = isSuccessfulDone({ + ...createCommandErrorResource([CommandLinkRel.EFFECTED_RESOURCE]), + }); - expect(doesMatch).toBeTruthy(); - }) - }) + expect(isDoneSuccessfuly).toBeFalsy(); + }); - describe('isSuccessfulDone', () => { + it('should return false if command is not done without error', () => { + const isDoneSuccessfuly: boolean = isSuccessfulDone(createCommandResource()); - it('should return true if command is done and has no error', () => { - const isDoneSuccessfuly: boolean = isSuccessfulDone({ ...createCommandResource([CommandLinkRel.EFFECTED_RESOURCE])}); + expect(isDoneSuccessfuly).toBeFalsy(); + }); - expect(isDoneSuccessfuly).toBeTruthy(); - }) + it('should return false if command is not done with error', () => { + const isDoneSuccessfuly: boolean = isSuccessfulDone(createCommandErrorResource()); - it('should return false if command is done with error', () => { - const isDoneSuccessfuly: boolean = isSuccessfulDone({ ...createCommandErrorResource([CommandLinkRel.EFFECTED_RESOURCE])}); - - expect(isDoneSuccessfuly).toBeFalsy(); - }) - - it('should return false if command is not done without error', () => { - const isDoneSuccessfuly: boolean = isSuccessfulDone(createCommandResource()); - - expect(isDoneSuccessfuly).toBeFalsy(); - }) - - it('should return false if command is not done with error', () => { - const isDoneSuccessfuly: boolean = isSuccessfulDone(createCommandErrorResource()); - - expect(isDoneSuccessfuly).toBeFalsy(); - }) - }) -}) \ No newline at end of file + expect(isDoneSuccessfuly).toBeFalsy(); + }); + }); +}); diff --git a/alfa-client/libs/command-shared/src/lib/command.util.ts b/alfa-client/libs/command-shared/src/lib/command.util.ts index 38083870500a739b406e9d6f04198f3c766e34cf..1a1aa81a2052dfe28d9d0ec8bf55a59daa6b4db7 100644 --- a/alfa-client/libs/command-shared/src/lib/command.util.ts +++ b/alfa-client/libs/command-shared/src/lib/command.util.ts @@ -28,42 +28,50 @@ import { CommandErrorMessage } from './command.message'; import { CommandListResource, CommandResource } from './command.model'; export function isRevokeable(commandResource: CommandResource): boolean { - return hasLink(commandResource, CommandLinkRel.REVOKE); + return hasLink(commandResource, CommandLinkRel.REVOKE); } export function isPending(commandResource: CommandResource): boolean { - return hasLink(commandResource, CommandLinkRel.UPDATE); + return hasLink(commandResource, CommandLinkRel.UPDATE); } export function isDone(commandResource: CommandResource): boolean { - return hasLink(commandResource, CommandLinkRel.EFFECTED_RESOURCE); + return hasLink(commandResource, CommandLinkRel.EFFECTED_RESOURCE); } export function hasErrorMessage(commandResource: CommandResource): boolean { - return !isNil(commandResource.errorMessage) && !isEmpty(commandResource.errorMessage); + return !isNil(commandResource.errorMessage) && !isEmpty(commandResource.errorMessage); } export function hasError(commandResource: CommandResource): boolean { - return hasErrorMessage(commandResource) && !isPending(commandResource); + return hasErrorMessage(commandResource) && !isPending(commandResource); } -export function getPendingCommandByOrder(pendingCommands: CommandListResource, commandOrder: any[]): CommandResource { - const commands: CommandResource[] = getEmbeddedCommandResources(pendingCommands).filter(command => commandOrder.includes(command.order)); - return commands.length > 0 ? commands[0] : null; +export function getPendingCommandByOrder( + pendingCommands: CommandListResource, + commandOrder: any[], +): CommandResource { + const commands: CommandResource[] = getEmbeddedCommandResources(pendingCommands).filter( + (command) => commandOrder.includes(command.order), + ); + return commands.length > 0 ? commands[0] : null; } function getEmbeddedCommandResources(commandListResource: CommandListResource): CommandResource[] { - return getEmbeddedResource<CommandResource[]>(commandListResource, CommandListLinkRel.COMMAND_LIST); + return getEmbeddedResource<CommandResource[]>( + commandListResource, + CommandListLinkRel.COMMAND_LIST, + ); } export function doIfCommandIsDone(commandResource: CommandResource, action: () => void) { - if (isObject(commandResource) && isDone(commandResource)) action(); + if (isObject(commandResource) && isDone(commandResource)) action(); } -export function isConcurrentModification(errorMessage: string): boolean{ - return errorMessage === CommandErrorMessage.CONCURRENT_MODIFICATION; +export function isConcurrentModification(errorMessage: string): boolean { + return errorMessage === CommandErrorMessage.CONCURRENT_MODIFICATION; } export function isSuccessfulDone(commandResource: CommandResource): boolean { - return isDone(commandResource) && !hasError(commandResource); -} \ No newline at end of file + return isDone(commandResource) && !hasError(commandResource); +} diff --git a/alfa-client/libs/command-shared/src/test-setup.ts b/alfa-client/libs/command-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/command-shared/src/test-setup.ts +++ b/alfa-client/libs/command-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/command-shared/test/command.ts b/alfa-client/libs/command-shared/test/command.ts index 3d8f9be742cf1f9fd58a003ed01a553873152c5f..eeb9f2dba68b587edc8d0f16ccb46c6cb4bde4c6 100644 --- a/alfa-client/libs/command-shared/test/command.ts +++ b/alfa-client/libs/command-shared/test/command.ts @@ -26,41 +26,61 @@ import { toResource } from 'libs/tech-shared/test/resource'; import { times } from 'lodash-es'; import { CommandListLinkRel } from '../src/lib/command.linkrel'; import { CommandErrorMessage } from '../src/lib/command.message'; -import { Command, CommandListResource, CommandOrder, CommandResource, CommandStatus, CreateCommand, CreateCommandProps } from '../src/lib/command.model'; +import { + Command, + CommandListResource, + CommandOrder, + CommandResource, + CommandStatus, + CreateCommand, + CreateCommandProps, +} from '../src/lib/command.model'; export function createCommand(): Command { - return { - body: null, - createdAt: faker.date.past(), - finishedAt: faker.date.past(), - order: faker.random.word(), - status: CommandStatus.FINISHED, - errorMessage: null - } + return { + body: null, + createdAt: faker.date.past(), + finishedAt: faker.date.past(), + order: faker.random.word(), + status: CommandStatus.FINISHED, + errorMessage: null, + }; } export function createCommandResource(linkRel: string[] = []): CommandResource { - return toResource(createCommand(), linkRel); + return toResource(createCommand(), linkRel); } export function createCommandResources(linkRelations: string[] = []): CommandResource[] { - return times(10, () => toResource(createCommandResource(), [...linkRelations])); + return times(10, () => toResource(createCommandResource(), [...linkRelations])); } -export function createCommandListResource(commandResources: CommandResource[] = createCommandResources(), linkRelations: string[] = []): CommandListResource { - return toResource({}, [...linkRelations], { - [CommandListLinkRel.COMMAND_LIST]: commandResources - }); +export function createCommandListResource( + commandResources: CommandResource[] = createCommandResources(), + linkRelations: string[] = [], +): CommandListResource { + return toResource({}, [...linkRelations], { + [CommandListLinkRel.COMMAND_LIST]: commandResources, + }); } export function createCommandErrorResource(linkRelations: string[] = []): CommandResource { - return {...createCommandResource(linkRelations), errorMessage: CommandErrorMessage.CONCURRENT_MODIFICATION }; + return { + ...createCommandResource(linkRelations), + errorMessage: CommandErrorMessage.CONCURRENT_MODIFICATION, + }; } -export function createCreateCommand(order: CommandOrder = CommandOrder.VORGANG_ANNEHMEN): CreateCommand { - return { order, body: null }; +export function createCreateCommand( + order: CommandOrder = CommandOrder.VORGANG_ANNEHMEN, +): CreateCommand { + return { order, body: null }; } export function createCreateCommandProps(): CreateCommandProps { - return { resource: createCommandResource(), linkRel: faker.internet.url(), command: createCreateCommand() }; -} \ No newline at end of file + return { + resource: createCommandResource(), + linkRel: faker.internet.url(), + command: createCreateCommand(), + }; +} diff --git a/alfa-client/libs/command-shared/tsconfig.json b/alfa-client/libs/command-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/command-shared/tsconfig.json +++ b/alfa-client/libs/command-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/command-shared/tsconfig.lib.json b/alfa-client/libs/command-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/command-shared/tsconfig.lib.json +++ b/alfa-client/libs/command-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/command-shared/tsconfig.spec.json b/alfa-client/libs/command-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/command-shared/tsconfig.spec.json +++ b/alfa-client/libs/command-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/environment-shared/.eslintrc.json b/alfa-client/libs/environment-shared/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/environment-shared/.eslintrc.json +++ b/alfa-client/libs/environment-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/environment-shared/jest.config.ts b/alfa-client/libs/environment-shared/jest.config.ts index b07f96debd3345886bfc28ed25cc15f25f4e70ab..64340e8f9ab8013c1f17468a8781532bd6c445c7 100644 --- a/alfa-client/libs/environment-shared/jest.config.ts +++ b/alfa-client/libs/environment-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'environment-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/environment-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'environment-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/environment-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/environment-shared/project.json b/alfa-client/libs/environment-shared/project.json index 7e937518f3144f23842a2512312e2a4d9ab990ef..14359050a373a68ee18c7546f1c4e756ae3eef48 100644 --- a/alfa-client/libs/environment-shared/project.json +++ b/alfa-client/libs/environment-shared/project.json @@ -1,34 +1,34 @@ { - "name": "environment-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/environment-shared/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/environment-shared/src/**/*.ts", - "libs/environment-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/environment-shared/tsconfig.spec.json", - "jestConfig": "libs/environment-shared/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/environment-shared"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "environment-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/environment-shared/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/environment-shared/src/**/*.ts", + "libs/environment-shared/src/**/*.html" + ] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/environment-shared/tsconfig.spec.json", + "jestConfig": "libs/environment-shared/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/environment-shared"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/environment-shared/src/index.ts b/alfa-client/libs/environment-shared/src/index.ts index ae1d4ae40fe8efa95d811ad544b75fc3e888f465..383ec972f1ababfc899ce9e307289b6d9219b772 100644 --- a/alfa-client/libs/environment-shared/src/index.ts +++ b/alfa-client/libs/environment-shared/src/index.ts @@ -24,4 +24,3 @@ export * from './lib/environment.model'; export * from './lib/environment.module'; export * from './lib/environment.service'; - diff --git a/alfa-client/libs/environment-shared/src/lib/environment.model.ts b/alfa-client/libs/environment-shared/src/lib/environment.model.ts index cd84fed8493b327833052aedb4ca235805c7b590..a20dc1227942f910b39667b2a59e5b635a606ecb 100644 --- a/alfa-client/libs/environment-shared/src/lib/environment.model.ts +++ b/alfa-client/libs/environment-shared/src/lib/environment.model.ts @@ -24,10 +24,10 @@ import { ResourceUri } from '@ngxp/rest/lib/resource.model'; export interface Environment { - production: boolean, - remoteHost: ResourceUri, - authServer: string, - realm: string, - clientId: string, - processorNames: string[] + production: boolean; + remoteHost: ResourceUri; + authServer: string; + realm: string; + clientId: string; + processorNames: string[]; } diff --git a/alfa-client/libs/environment-shared/src/lib/environment.module.spec.ts b/alfa-client/libs/environment-shared/src/lib/environment.module.spec.ts index 89a7295621ef806d287b3cdface58317b37cdb29..d148e5bc42d56fda342d289be57c2342ec6b16d7 100644 --- a/alfa-client/libs/environment-shared/src/lib/environment.module.spec.ts +++ b/alfa-client/libs/environment-shared/src/lib/environment.module.spec.ts @@ -25,13 +25,13 @@ import { EnvironmentModule } from './environment.module'; import { TestBed } from '@angular/core/testing'; describe('EnvironmentModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [EnvironmentModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [EnvironmentModule], + }).compileComponents(); + }); - it('should create', () => { - expect(EnvironmentModule).toBeDefined(); - }); + it('should create', () => { + expect(EnvironmentModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/environment-shared/src/lib/environment.module.ts b/alfa-client/libs/environment-shared/src/lib/environment.module.ts index abbb78246be02306eb0afe6e5116c228fd9e9605..c84a1cbac1e0dbff3bd591b0f95eef07cb756cf9 100644 --- a/alfa-client/libs/environment-shared/src/lib/environment.module.ts +++ b/alfa-client/libs/environment-shared/src/lib/environment.module.ts @@ -27,15 +27,12 @@ import { RestModule } from '@ngxp/rest'; import { ENVIRONMENT_CONFIG, getEnvironmentFactory } from './environment.service'; @NgModule({ - imports: [ - CommonModule, - RestModule - ], - providers: [ - { - provide: ENVIRONMENT_CONFIG, - useFactory: getEnvironmentFactory - } - ] + imports: [CommonModule, RestModule], + providers: [ + { + provide: ENVIRONMENT_CONFIG, + useFactory: getEnvironmentFactory, + }, + ], }) -export class EnvironmentModule { } +export class EnvironmentModule {} diff --git a/alfa-client/libs/environment-shared/src/lib/environment.service.ts b/alfa-client/libs/environment-shared/src/lib/environment.service.ts index 0ee924f7c7e3671b2d515d385f546c10842ab7b0..b25c92884ae85383e12be1b5263a5bc90bda14f5 100644 --- a/alfa-client/libs/environment-shared/src/lib/environment.service.ts +++ b/alfa-client/libs/environment-shared/src/lib/environment.service.ts @@ -28,17 +28,18 @@ import { Environment } from './environment.model'; export const ENVIRONMENT_CONFIG = new InjectionToken('environmentConfig'); export function getEnvironmentFactory(): Environment { - return window['__env__']; + return window['__env__']; } export async function loadEnvironment(url?: string): Promise<any> { - const envUrl = url ? url : `${getBaseUrl()}api/environment`; - const headers = new Headers({ 'X-Client': 'web' }); + const envUrl = url ? url : `${getBaseUrl()}api/environment`; + const headers = new Headers({ 'X-Client': 'web' }); - return window.fetch(envUrl, { headers }) - .then(response => response.json()) - .then(env => { - window['__env__'] = env; - return env; - }); -} \ No newline at end of file + return window + .fetch(envUrl, { headers }) + .then((response) => response.json()) + .then((env) => { + window['__env__'] = env; + return env; + }); +} diff --git a/alfa-client/libs/environment-shared/src/test-setup.ts b/alfa-client/libs/environment-shared/src/test-setup.ts index 32096869a0084d5cdd50f8fd6f051a9f7afe7ed7..9ffb6a66afc4d1c41f58bba4790410511a159f6d 100644 --- a/alfa-client/libs/environment-shared/src/test-setup.ts +++ b/alfa-client/libs/environment-shared/src/test-setup.ts @@ -25,13 +25,11 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting, + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { teardown: { destroyAfterEach: false } } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, +}); diff --git a/alfa-client/libs/environment-shared/test/environment.ts b/alfa-client/libs/environment-shared/test/environment.ts index d79cfdc39ebb8a6130d49be057e7367dda4ea256..a20e21858ab97031ca1929457e67534cf2268ef7 100644 --- a/alfa-client/libs/environment-shared/test/environment.ts +++ b/alfa-client/libs/environment-shared/test/environment.ts @@ -26,14 +26,14 @@ import { cloneDeep } from 'lodash-es'; import { Environment } from '../src/lib/environment.model'; const environment: Environment = { - production: false, - remoteHost: faker.internet.url(), - authServer: faker.internet.url(), - realm: faker.random.word(), - clientId: faker.datatype.uuid(), - processorNames: [faker.name.findName()] + production: false, + remoteHost: faker.internet.url(), + authServer: faker.internet.url(), + realm: faker.random.word(), + clientId: faker.datatype.uuid(), + processorNames: [faker.name.findName()], }; export function createEnvironment(): Environment { - return cloneDeep(environment); + return cloneDeep(environment); } diff --git a/alfa-client/libs/environment-shared/tsconfig.json b/alfa-client/libs/environment-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/environment-shared/tsconfig.json +++ b/alfa-client/libs/environment-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/environment-shared/tsconfig.lib.json b/alfa-client/libs/environment-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/environment-shared/tsconfig.lib.json +++ b/alfa-client/libs/environment-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/environment-shared/tsconfig.spec.json b/alfa-client/libs/environment-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/environment-shared/tsconfig.spec.json +++ b/alfa-client/libs/environment-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/forwarding-shared/.eslintrc.json b/alfa-client/libs/forwarding-shared/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/forwarding-shared/.eslintrc.json +++ b/alfa-client/libs/forwarding-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/forwarding-shared/jest.config.ts b/alfa-client/libs/forwarding-shared/jest.config.ts index 74eccca94e27e69606e0776fe1c8fc648274a2a8..279ea6357ffe2641748a89c14606f29b8b26d535 100644 --- a/alfa-client/libs/forwarding-shared/jest.config.ts +++ b/alfa-client/libs/forwarding-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'forwarding-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/forwarding-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'forwarding-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/forwarding-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/forwarding-shared/project.json b/alfa-client/libs/forwarding-shared/project.json index 3b1f8c609d475ba4d03a6ba65b90e116a2e35ddf..578c06def99e68edd127eadcaa4f9d94add8d36c 100644 --- a/alfa-client/libs/forwarding-shared/project.json +++ b/alfa-client/libs/forwarding-shared/project.json @@ -1,29 +1,29 @@ { - "name": "forwarding-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/forwarding-shared/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/forwarding-shared/src/**/*.ts", - "libs/forwarding-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/forwarding-shared"], - "options": { - "tsConfig": "libs/forwarding-shared/tsconfig.spec.json", - "jestConfig": "libs/forwarding-shared/jest.config.ts", - "passWithNoTests": true - } - } - }, - "tags": [] + "name": "forwarding-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/forwarding-shared/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/forwarding-shared/src/**/*.ts", + "libs/forwarding-shared/src/**/*.html" + ] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/forwarding-shared"], + "options": { + "tsConfig": "libs/forwarding-shared/tsconfig.spec.json", + "jestConfig": "libs/forwarding-shared/jest.config.ts", + "passWithNoTests": true + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding-shared.module.spec.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding-shared.module.spec.ts index 203e800678b06eda486055839c788e16591fa802..fdb9cda0fbe98f04432335b4b30abba4f8920b2a 100644 --- a/alfa-client/libs/forwarding-shared/src/lib/forwarding-shared.module.spec.ts +++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding-shared.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { ForwardingSharedModule } from './forwarding-shared.module'; describe('ForwardingSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ForwardingSharedModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ForwardingSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(ForwardingSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(ForwardingSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding-shared.module.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding-shared.module.ts index 5bcd22d840fbd2a258f33b3498510d48145740d8..ef4af642cdcefb47d07268ac8f74d81bac367687 100644 --- a/alfa-client/libs/forwarding-shared/src/lib/forwarding-shared.module.ts +++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding-shared.module.ts @@ -25,6 +25,6 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; @NgModule({ - imports: [CommonModule] + imports: [CommonModule], }) -export class ForwardingSharedModule { } +export class ForwardingSharedModule {} diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding.linkrel.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding.linkrel.ts index ef49bc70e5b85a7e98f004b8758a497d120cad00..1c003b898c15371dd0bfde87bd59e71116ca9d7b 100644 --- a/alfa-client/libs/forwarding-shared/src/lib/forwarding.linkrel.ts +++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding.linkrel.ts @@ -22,14 +22,14 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum ForwardingListLinkRel { - FORWARDING_LIST = 'forwardingList' + FORWARDING_LIST = 'forwardingList', } export enum ForwardingLinkRel { - MARK_AS_SUCCESS = 'mark-as-success', - MARK_AS_FAIL = 'mark-as-fail', + MARK_AS_SUCCESS = 'mark-as-success', + MARK_AS_FAIL = 'mark-as-fail', - SUCCESSFUL = 'successfull', - FAILED = 'failed', - ERROR = 'error' + SUCCESSFUL = 'successfull', + FAILED = 'failed', + ERROR = 'error', } diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding.model.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding.model.ts index a3541038ea5fad68bae0a2edf36dfa82ef6d22e3..4c08ed202e8889013be17ffaf258313500d7c313 100644 --- a/alfa-client/libs/forwarding-shared/src/lib/forwarding.model.ts +++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding.model.ts @@ -25,14 +25,14 @@ import { ListResource } from '@alfa-client/tech-shared'; import { Resource } from '@ngxp/rest'; export interface Forwarding { - zustaendigeStelle: string; - errorMessage: string; - createdAt: Date; - sentAt: Date; - createdBy: string; - createdByName: string; + zustaendigeStelle: string; + errorMessage: string; + createdAt: Date; + sentAt: Date; + createdBy: string; + createdByName: string; } -export interface ForwardingResource extends Forwarding, Resource { } +export interface ForwardingResource extends Forwarding, Resource {} -export interface ForwardingListResource extends ListResource { } \ No newline at end of file +export interface ForwardingListResource extends ListResource {} diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.spec.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.spec.ts index bd160bbe823d730ed74b80d5305d62c0f12a8a06..f989e89845bd543d7c91668e4629f4486c80af56 100644 --- a/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.spec.ts +++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.spec.ts @@ -31,43 +31,44 @@ import { ForwardingListResource } from './forwarding.model'; import { ForwardingRepository } from './forwarding.repository'; describe('ForwardingRepository', () => { - let repository: ForwardingRepository; - let resourceFactory = mock(ResourceFactory); - let resourceWrapper = { get: jest.fn() }; + let repository: ForwardingRepository; + let resourceFactory = mock(ResourceFactory); + let resourceWrapper = { get: jest.fn() }; - beforeEach(() => { - repository = new ForwardingRepository(useFromMock(resourceFactory)); + beforeEach(() => { + repository = new ForwardingRepository(useFromMock(resourceFactory)); - resourceFactory.fromId.mockReturnValue(resourceWrapper); - resourceFactory.from.mockReturnValue(resourceWrapper); - }) + resourceFactory.fromId.mockReturnValue(resourceWrapper); + resourceFactory.from.mockReturnValue(resourceWrapper); + }); - describe('getForwardings', () => { + describe('getForwardings', () => { + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.FORWARDING, + ]); + const commandList: ForwardingListResource = createForwardingListResource(); - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARDING]); - const commandList: ForwardingListResource = createForwardingListResource(); + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: commandList })); + }); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: commandList })); - }) + it('should call resourceFactory', () => { + repository.getForwardings(vorgang); - it('should call resourceFactory', () => { - repository.getForwardings(vorgang); + expect(resourceFactory.from).toHaveBeenCalledWith(vorgang); + }); - expect(resourceFactory.from).toHaveBeenCalledWith(vorgang); - }) + it('should call resourceWrapper', () => { + repository.getForwardings(vorgang); - it('should call resourceWrapper', () => { - repository.getForwardings(vorgang); + expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangWithEingangLinkRel.FORWARDING); + }); - expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangWithEingangLinkRel.FORWARDING); - }) + it('should return result', () => { + let result = repository.getForwardings(vorgang); - it('should return result', () => { - let result = repository.getForwardings(vorgang); - - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: commandList })); - }) - }) -}) \ No newline at end of file + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: commandList })); + }); + }); +}); diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.ts index 4ca10a091584293cbadc0ba1d017179d625b994d..88bb1631d96d3c80331d1160590a86bb10c8b844 100644 --- a/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.ts +++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding.repository.ts @@ -29,9 +29,9 @@ import { ForwardingListResource } from './forwarding.model'; @Injectable({ providedIn: 'root' }) export class ForwardingRepository { - constructor(private resourceFactory: ResourceFactory) { } + constructor(private resourceFactory: ResourceFactory) {} - public getForwardings(vorgang: VorgangWithEingangResource): Observable<ForwardingListResource> { - return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.FORWARDING); - } -} \ No newline at end of file + public getForwardings(vorgang: VorgangWithEingangResource): Observable<ForwardingListResource> { + return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.FORWARDING); + } +} diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding.service.spec.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding.service.spec.ts index b912d34843c7c250b7a113ef637672fdb78c8be3..b5cd6188bdf3bd1a9860d2c0bbc4b7388b2b793f 100644 --- a/alfa-client/libs/forwarding-shared/src/lib/forwarding.service.spec.ts +++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding.service.spec.ts @@ -23,13 +23,29 @@ */ import { CommandOrder, CommandResource, CommandService } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { StateResource, createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; -import { CreateForwardCommand, ForwardRequest, VorgangResource, VorgangService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + CreateForwardCommand, + ForwardRequest, + VorgangResource, + VorgangService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { cold, hot } from 'jest-marbles'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; import { createCommandResource } from 'libs/command-shared/test/command'; -import { createVorgangForwardRequest, createVorgangResource, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; +import { + createVorgangForwardRequest, + createVorgangResource, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; import { of } from 'rxjs'; import { createApiError } from '../../../tech-shared/test/error'; import { createForwardingListResource, createForwardingResource } from '../../test/forwarding'; @@ -39,293 +55,317 @@ import { ForwardingRepository } from './forwarding.repository'; import { ForwardingService } from './forwarding.service'; describe('ForwardingService', () => { - let service: ForwardingService; - let commandService: Mock<CommandService>; - let vorgangService: Mock<VorgangService>; - let navigationService: Mock<NavigationService>; - let forwardingRepository: Mock<ForwardingRepository>; + let service: ForwardingService; + let commandService: Mock<CommandService>; + let vorgangService: Mock<VorgangService>; + let navigationService: Mock<NavigationService>; + let forwardingRepository: Mock<ForwardingRepository>; + + const forwardRequest: ForwardRequest = createVorgangForwardRequest(); + const forwading: ForwardingResource = createForwardingResource(); + + beforeEach(() => { + commandService = mock(CommandService); + vorgangService = mock(VorgangService); + navigationService = mock(NavigationService); + forwardingRepository = mock(ForwardingRepository); + + service = new ForwardingService( + useFromMock(commandService), + useFromMock(vorgangService), + useFromMock(navigationService), + useFromMock(forwardingRepository), + ); + }); + + it('should create', () => { + expect(service).toBeTruthy(); + }); + + describe('forward', () => { + const vorgang: VorgangResource = createVorgangResource(); + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + + beforeEach(() => { + commandService.createCommand.mockReturnValue(of(commandStateResource)); + vorgangService.getPendingForwardCommand(of(commandStateResource)); + }); + + it('should call commandService', () => { + const command: CreateForwardCommand = { + order: CommandOrder.REDIRECT_VORGANG, + redirectRequest: forwardRequest, + body: null, + }; + + service.forward(vorgang, forwardRequest); - const forwardRequest: ForwardRequest = createVorgangForwardRequest(); - const forwading: ForwardingResource = createForwardingResource(); + expect(commandService.createCommand).toHaveBeenCalledWith( + vorgang, + VorgangWithEingangLinkRel.FORWARD, + command, + ); + }); + + it('should call reloadCurrentVorgang', () => { + service.reloadCurrentVorgang = jest.fn(); + + service.forward(vorgang, forwardRequest); + + expect(service.reloadCurrentVorgang).toHaveBeenCalled(); + }); + + it('should call setPendingForwardSingleCommandLoading', () => { + service.forward(vorgang, forwardRequest); + + expect(vorgangService.setPendingForwardSingleCommandLoading).toHaveBeenCalled(); + }); + + it('should call setPendingForwardSingleCommand', () => { + service.forward(vorgang, forwardRequest); - beforeEach(() => { - commandService = mock(CommandService); - vorgangService = mock(VorgangService); - navigationService = mock(NavigationService); - forwardingRepository = mock(ForwardingRepository); + expect(vorgangService.setPendingForwardSingleCommand).toHaveBeenCalled(); + }); + }); - service = new ForwardingService(useFromMock(commandService), useFromMock(vorgangService), useFromMock(navigationService), useFromMock(forwardingRepository)); - }) + describe('reloadCurrentVorgang', () => { + it('should call vorgang service', () => { + service.reloadCurrentVorgang(createEmptyStateResource()); - it('should create', () => { - expect(service).toBeTruthy(); - }); + expect(vorgangService.reloadCurrentVorgang).toHaveBeenCalled(); + }); - describe('forward', () => { + it('should NOT call vorgang service on error', () => { + service.reloadCurrentVorgang(createErrorStateResource(createApiError())); - const vorgang: VorgangResource = createVorgangResource(); - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); + expect(vorgangService.reloadCurrentVorgang).not.toHaveBeenCalled(); + }); + }); - beforeEach(() => { - commandService.createCommand.mockReturnValue(of(commandStateResource)); - vorgangService.getPendingForwardCommand(of(commandStateResource)); - }) + describe('pollPendingForwardCommand', () => { + const commandReturnValue: StateResource<CommandResource> = createStateResource({ + ...createCommandResource(), + }); + const commandResourceWithUpdateLink: CommandResource = { + ...createCommandResource([CommandLinkRel.UPDATE]), + }; - it('should call commandService', () => { - const command: CreateForwardCommand = { order: CommandOrder.REDIRECT_VORGANG, redirectRequest: forwardRequest, body: null }; + beforeEach(() => { + commandService.pollCommand.mockReturnValue(of(commandReturnValue)); + service.reloadCurrentVorgang = jest.fn(); + }); - service.forward(vorgang, forwardRequest); + it('should call commandService on pending forward command', () => { + service.pollPendingForwardCommand(createStateResource({ ...createCommandResource() })); - expect(commandService.createCommand).toHaveBeenCalledWith(vorgang, VorgangWithEingangLinkRel.FORWARD, command); - }) + expect(commandService.pollCommand).not.toHaveBeenCalled(); + }); - it('should call reloadCurrentVorgang', () => { - service.reloadCurrentVorgang = jest.fn(); + it('should not call commandService', () => { + service.pollPendingForwardCommand(createStateResource(commandResourceWithUpdateLink)); - service.forward(vorgang, forwardRequest); + expect(commandService.pollCommand).toHaveBeenCalledWith(commandResourceWithUpdateLink); + }); - expect(service.reloadCurrentVorgang).toHaveBeenCalled(); - }) + it('should call vorgangservice on command is done', () => { + const commandServiceReturnValue = createStateResource( + createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), + ); + commandService.pollCommand.mockReturnValue(of(commandServiceReturnValue)); - it('should call setPendingForwardSingleCommandLoading', () => { - service.forward(vorgang, forwardRequest); + service.pollPendingForwardCommand(createStateResource(commandResourceWithUpdateLink)); - expect(vorgangService.setPendingForwardSingleCommandLoading).toHaveBeenCalled(); - }) + expect(vorgangService.setPendingForwardSingleCommand).toHaveBeenCalledWith( + commandServiceReturnValue, + ); + }); - it('should call setPendingForwardSingleCommand', () => { - service.forward(vorgang, forwardRequest); + it('should call not vorgangservice on pending command', () => { + const commandServiceReturnValue = createStateResource(createCommandResource()); + commandService.pollCommand.mockReturnValue(of(commandServiceReturnValue)); - expect(vorgangService.setPendingForwardSingleCommand).toHaveBeenCalled(); - }) - }) + service.pollPendingForwardCommand(createStateResource(commandResourceWithUpdateLink)); - describe('reloadCurrentVorgang', () => { + expect(vorgangService.setPendingForwardSingleCommand).not.toHaveBeenCalled(); + }); - it('should call vorgang service', () => { - service.reloadCurrentVorgang(createEmptyStateResource()); + it('should call reloadCurrentVorgang on command is done', () => { + const command: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); + const commandServiceReturnValue = createStateResource(command); + commandService.pollCommand.mockReturnValue(of(commandServiceReturnValue)); - expect(vorgangService.reloadCurrentVorgang).toHaveBeenCalled(); - }) + service.pollPendingForwardCommand(createStateResource(commandResourceWithUpdateLink)); - it('should NOT call vorgang service on error', () => { - service.reloadCurrentVorgang(createErrorStateResource(createApiError())); + expect(service.reloadCurrentVorgang).toHaveBeenCalledWith(commandServiceReturnValue); + }); + }); - expect(vorgangService.reloadCurrentVorgang).not.toHaveBeenCalled(); - }) - }) + describe('onNavigation', () => { + beforeEach(() => { + service.unsubscribe = jest.fn(); + }); - describe('pollPendingForwardCommand', () => { + describe('on leaving vorgang-detail page', () => { + it('should call unsubscribe on subscriptions', () => { + service.onNavigation({}); - const commandReturnValue: StateResource<CommandResource> = createStateResource({ ...createCommandResource() }); - const commandResourceWithUpdateLink: CommandResource = { ...createCommandResource([CommandLinkRel.UPDATE]) }; + expect(service.unsubscribe).toHaveBeenCalled(); + }); + }); + }); - beforeEach(() => { - commandService.pollCommand.mockReturnValue(of(commandReturnValue)); - service.reloadCurrentVorgang = jest.fn(); - }) + describe('getPendingForwardCommand', () => { + beforeEach(() => { + service.listenToNavigation = jest.fn(); + }); - it('should call commandService on pending forward command', () => { - service.pollPendingForwardCommand(createStateResource({ ...createCommandResource() })); + it('should call listenToNavigation', () => { + vorgangService.getPendingForwardCommand.mockReturnValue(of({})); - expect(commandService.pollCommand).not.toHaveBeenCalled(); - }) + service.getPendingForwardCommand(); - it('should not call commandService', () => { - service.pollPendingForwardCommand(createStateResource(commandResourceWithUpdateLink)); + expect(service.listenToNavigation).toHaveBeenCalled(); + }); - expect(commandService.pollCommand).toHaveBeenCalledWith(commandResourceWithUpdateLink); - }) + it('should call vorgang service', () => { + vorgangService.getPendingForwardCommand.mockReturnValue(of({})); - it('should call vorgangservice on command is done', () => { - const commandServiceReturnValue = createStateResource(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE])); - commandService.pollCommand.mockReturnValue(of(commandServiceReturnValue)); + service.getPendingForwardCommand(); - service.pollPendingForwardCommand(createStateResource(commandResourceWithUpdateLink)); + expect(vorgangService.getPendingForwardCommand).toHaveBeenCalled(); + }); + }); - expect(vorgangService.setPendingForwardSingleCommand).toHaveBeenCalledWith(commandServiceReturnValue); + describe('getForwardings', () => { + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const listResource: ForwardingListResource = createForwardingListResource(); - }) + beforeEach(() => { + forwardingRepository.getForwardings.mockReturnValue(hot('-a', { a: listResource })); + }); - it('should call not vorgangservice on pending command', () => { - const commandServiceReturnValue = createStateResource(createCommandResource()); - commandService.pollCommand.mockReturnValue(of(commandServiceReturnValue)); + it('should return value', () => { + const result = service.getForwardings(vorgang); - service.pollPendingForwardCommand(createStateResource(commandResourceWithUpdateLink)); + expect(result).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: createStateResource(listResource) }), + ); + }); - expect(vorgangService.setPendingForwardSingleCommand).not.toHaveBeenCalled(); - }) + it('should call repository', () => { + service.getForwardings(vorgang); - it('should call reloadCurrentVorgang on command is done', () => { - const command: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); - const commandServiceReturnValue = createStateResource(command); - commandService.pollCommand.mockReturnValue(of(commandServiceReturnValue)); + expect(forwardingRepository.getForwardings).toHaveBeenCalledWith(vorgang); + }); + }); - service.pollPendingForwardCommand(createStateResource(commandResourceWithUpdateLink)); + describe('markAs', () => { + const stateResource: StateResource<ForwardingResource> = createStateResource(forwading); - expect(service.reloadCurrentVorgang).toHaveBeenCalledWith(commandServiceReturnValue); - }) - }) + beforeEach(() => { + commandService.createCommand.mockReturnValue(hot('-a', { a: stateResource })); + }); - describe('onNavigation', () => { + describe('createMarkAsCommand', () => { + it('should return value', () => { + const result = service.createMarkAsCommand(forwading, ForwardingLinkRel.MARK_AS_SUCCESS, { + order: CommandOrder.FORWARD_SUCCESSFULL, + body: null, + }); - beforeEach(() => { - service.unsubscribe = jest.fn(); - }) + expect(result).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: stateResource }), + ); + }); + }); - describe('on leaving vorgang-detail page', () => { + describe('markAsSuccess', () => { + it('should call command service', () => { + service.markAsSuccess(forwading); - it('should call unsubscribe on subscriptions', () => { - service.onNavigation({}); + expect(commandService.createCommand).toHaveBeenCalledWith( + forwading, + ForwardingLinkRel.MARK_AS_SUCCESS, + { order: CommandOrder.FORWARD_SUCCESSFULL, body: null }, + ); + }); - expect(service.unsubscribe).toHaveBeenCalled(); - }) - }) - }) + it('should update list on valid response', () => { + commandService.createCommand.mockReturnValue(of(stateResource)); - describe('getPendingForwardCommand', () => { + service.updateForwardingList = jest.fn(); - beforeEach(() => { - service.listenToNavigation = jest.fn(); - }) + service.markAsSuccess(forwading).subscribe(); - it('should call listenToNavigation', () => { - vorgangService.getPendingForwardCommand.mockReturnValue(of({})); + expect(service.updateForwardingList).toHaveBeenCalled(); + }); + }); - service.getPendingForwardCommand(); + describe('markAsFail', () => { + it('should call command service', () => { + service.markAsFail(forwading); - expect(service.listenToNavigation).toHaveBeenCalled(); - }) + expect(commandService.createCommand).toHaveBeenCalledWith( + forwading, + ForwardingLinkRel.MARK_AS_FAIL, + { order: CommandOrder.FORWARD_FAILED, body: null }, + ); + }); - it('should call vorgang service', () => { - vorgangService.getPendingForwardCommand.mockReturnValue(of({})); + it('should update vorgang on valid response', () => { + commandService.createCommand.mockReturnValue( + of(createStateResource(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]))), + ); - service.getPendingForwardCommand(); + service.markAsFail(forwading).subscribe(); - expect(vorgangService.getPendingForwardCommand).toHaveBeenCalled(); - }) - }) + expect(vorgangService.reloadCurrentVorgang).toHaveBeenCalled(); + }); + }); + }); - describe('getForwardings', () => { + describe('update forwarding list', () => { + beforeEach(() => { + service.updateList = jest.fn(); + }); - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const listResource: ForwardingListResource = createForwardingListResource(); + it('should do nothing if link not exits', () => { + const command: CommandResource = createCommandResource(); - beforeEach(() => { - forwardingRepository.getForwardings.mockReturnValue(hot('-a', { a: listResource })); - }) + service.updateForwardingList(createStateResource(command)); - it('should return value', () => { - const result = service.getForwardings(vorgang); + expect(service.updateList).not.toHaveBeenCalled(); + }); - expect(result).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: createStateResource(listResource) })); - }) + it('should call update list', () => { + const command: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); - it('should call repository', () => { - service.getForwardings(vorgang); + service.updateForwardingList(createStateResource(command)); - expect(forwardingRepository.getForwardings).toHaveBeenCalledWith(vorgang); - }) - }) + expect(service.updateList).toHaveBeenCalledWith(command); + }); + }); - describe('markAs', () => { + describe('update list', () => { + const command: CommandResource = createCommandResource(); + const list: ForwardingListResource = createForwardingListResource(); - const stateResource: StateResource<ForwardingResource> = createStateResource(forwading); + beforeEach(() => { + commandService.getEffectedResource.mockReturnValue(of(list)); + service.setList = jest.fn(); + }); - beforeEach(() => { - commandService.createCommand.mockReturnValue(hot('-a', { a: stateResource })); - }) + it('should call command service', () => { + service.updateList(command); - describe('createMarkAsCommand', () => { + expect(commandService.getEffectedResource).toHaveBeenCalledWith(command); + }); - it('should return value', () => { - const result = service.createMarkAsCommand(forwading, ForwardingLinkRel.MARK_AS_SUCCESS, { order: CommandOrder.FORWARD_SUCCESSFULL, body: null }); + it('should set fowardling list', () => { + service.updateList(command); - expect(result).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: stateResource })); - }) - }) - - describe('markAsSuccess', () => { - - it('should call command service', () => { - service.markAsSuccess(forwading); - - expect(commandService.createCommand).toHaveBeenCalledWith(forwading, ForwardingLinkRel.MARK_AS_SUCCESS, { order: CommandOrder.FORWARD_SUCCESSFULL, body: null }); - }) - - it('should update list on valid response', () => { - commandService.createCommand.mockReturnValue(of(stateResource)); - - service.updateForwardingList = jest.fn(); - - service.markAsSuccess(forwading).subscribe(); - - expect(service.updateForwardingList).toHaveBeenCalled(); - }) - }) - - describe('markAsFail', () => { - - it('should call command service', () => { - service.markAsFail(forwading); - - expect(commandService.createCommand).toHaveBeenCalledWith(forwading, ForwardingLinkRel.MARK_AS_FAIL, { order: CommandOrder.FORWARD_FAILED, body: null }); - }) - - it('should update vorgang on valid response', () => { - commandService.createCommand.mockReturnValue(of(createStateResource(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE])))); - - service.markAsFail(forwading).subscribe(); - - expect(vorgangService.reloadCurrentVorgang).toHaveBeenCalled(); - }) - }) - }) - - describe('update forwarding list', () => { - - - beforeEach(() => { - service.updateList = jest.fn(); - }) - - it('should do nothing if link not exits', () => { - const command: CommandResource = createCommandResource(); - - service.updateForwardingList(createStateResource(command)); - - expect(service.updateList).not.toHaveBeenCalled(); - }) - - it('should call update list', () => { - const command: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); - - service.updateForwardingList(createStateResource(command)); - - expect(service.updateList).toHaveBeenCalledWith(command); - }) - }) - - describe('update list', () => { - - const command: CommandResource = createCommandResource(); - const list: ForwardingListResource = createForwardingListResource(); - - beforeEach(() => { - commandService.getEffectedResource.mockReturnValue(of(list)); - service.setList = jest.fn(); - }) - - it('should call command service', () => { - service.updateList(command); - - expect(commandService.getEffectedResource).toHaveBeenCalledWith(command); - }) - - it('should set fowardling list', () => { - service.updateList(command); - - expect(service.setList).toHaveBeenCalledWith(list); - }) - }) -}) \ No newline at end of file + expect(service.setList).toHaveBeenCalledWith(list); + }); + }); +}); diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding.service.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding.service.ts index f40bf4f0b65c59565d008878caee1715cac2ec1f..c425ea44e5bb2ef00586dd52fbf41cfb7af75e4b 100644 --- a/alfa-client/libs/forwarding-shared/src/lib/forwarding.service.ts +++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding.service.ts @@ -23,132 +23,181 @@ */ import { Injectable, OnDestroy } from '@angular/core'; import { Params } from '@angular/router'; -import { CommandResource, CommandService, CreateCommand, isDone, isPending } from '@alfa-client/command-shared'; +import { + CommandResource, + CommandService, + CreateCommand, + isDone, + isPending, +} from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { StateResource, createEmptyStateResource, createStateResource, hasError } from '@alfa-client/tech-shared'; -import { ForwardRequest, VorgangResource, VorgangService, VorgangWithEingangLinkRel, VorgangWithEingangResource, createForwardCommand } from '@alfa-client/vorgang-shared'; +import { + StateResource, + createEmptyStateResource, + createStateResource, + hasError, +} from '@alfa-client/tech-shared'; +import { + ForwardRequest, + VorgangResource, + VorgangService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, + createForwardCommand, +} from '@alfa-client/vorgang-shared'; import { isNil } from 'lodash-es'; import { BehaviorSubject, Observable, Subscription } from 'rxjs'; import { first, map, startWith, tap } from 'rxjs/operators'; import { ForwardingLinkRel } from './forwarding.linkrel'; import { ForwardingListResource, ForwardingResource } from './forwarding.model'; import { ForwardingRepository } from './forwarding.repository'; -import { createForwardingMarkAsFailCommand, createForwardingMarkAsSuccessCommand } from './forwarding.util'; +import { + createForwardingMarkAsFailCommand, + createForwardingMarkAsSuccessCommand, +} from './forwarding.util'; @Injectable({ providedIn: 'root' }) export class ForwardingService implements OnDestroy { - - private readonly forwardingList$: BehaviorSubject<StateResource<ForwardingListResource>> = new BehaviorSubject(createEmptyStateResource<ForwardingListResource>()); - - private navigationSubscription: Subscription; - private subscription: Subscription; - - constructor( - private commandService: CommandService, - private vorgangService: VorgangService, - private navigationService: NavigationService, - private forwardingRepository: ForwardingRepository - ) { } - - getForwardings(vorgang: VorgangWithEingangResource): Observable<StateResource<ForwardingListResource>> { - this.forwardingList$.next(createEmptyStateResource(true)); - - const subscription = this.forwardingRepository.getForwardings(vorgang).subscribe(list => { - this.forwardingList$.next(createStateResource(list)); - subscription.unsubscribe(); - }) - - return this.forwardingList$.asObservable(); - } - - getPendingForwardCommand(): Observable<StateResource<CommandResource>> { - this.listenToNavigation(); - - return this.vorgangService.getPendingForwardCommand().pipe( - map(pendingCommand => this.pollPendingForwardCommand(pendingCommand))) - } - - listenToNavigation(): void { - this.unsubscribe(); - this.navigationSubscription = this.navigationService.urlChanged().subscribe(params => this.onNavigation(params)); - } - - onNavigation(params: Params): void { - if (NavigationService.isVorgangListPage(params)) { - this.unsubscribe(); - } - } - - pollPendingForwardCommand(command: StateResource<CommandResource>): StateResource<CommandResource> { - if (this.shouldPoll(command)) { - this.subscription = this.commandService.pollCommand(command.resource).subscribe(updatedCommand => { - if (isDone(updatedCommand.resource)) { - this.vorgangService.setPendingForwardSingleCommand(updatedCommand); - this.reloadCurrentVorgang(updatedCommand); - this.subscription.unsubscribe(); - } - }) - } - return command; - } - - private shouldPoll(command: StateResource<CommandResource>): boolean { - return command.loaded && isPending(command.resource); - } - - public forward(vorgang: VorgangResource, request: ForwardRequest): Observable<StateResource<CommandResource>> { - this.vorgangService.setPendingForwardSingleCommandLoading(); - const subscription: Subscription = this.commandService.createCommand(vorgang, VorgangWithEingangLinkRel.FORWARD, createForwardCommand(request)).subscribe(command => { - this.vorgangService.setPendingForwardSingleCommand(command); - this.reloadCurrentVorgang(command); - subscription.unsubscribe(); - }) - return this.vorgangService.getPendingForwardCommand(); - } - - markAsSuccess(forward: ForwardingResource): Observable<StateResource<CommandResource>> { - return this.createMarkAsCommand(forward, ForwardingLinkRel.MARK_AS_SUCCESS, createForwardingMarkAsSuccessCommand()).pipe( - tap(command => this.updateForwardingList(command)) - ); - } - - markAsFail(forward: ForwardingResource): Observable<StateResource<CommandResource>> { - return this.createMarkAsCommand(forward, ForwardingLinkRel.MARK_AS_FAIL, createForwardingMarkAsFailCommand()).pipe( - tap(command => { - if (isDone(command.resource)) this.reloadCurrentVorgang(command); - })); - } - - reloadCurrentVorgang(command: StateResource<CommandResource>): void { - if (!hasError(command)) { - this.vorgangService.reloadCurrentVorgang(); - } - } - - createMarkAsCommand(forward: ForwardingResource, linkRel: string, command: CreateCommand): Observable<StateResource<CommandResource>> { - return this.commandService.createCommand(forward, linkRel, command).pipe( - startWith(createEmptyStateResource<CommandResource>(true)) - ); - } - - updateForwardingList(command: StateResource<CommandResource>): void { - if (isDone(command.resource)) this.updateList(command.resource); - } - - updateList(command: CommandResource): void { - this.commandService.getEffectedResource<ForwardingListResource>(command).pipe(first()).subscribe(list => this.setList(list)); - } - - setList(list: ForwardingListResource): void { - this.forwardingList$.next(createStateResource(list)); - } - - ngOnDestroy(): void { - this.unsubscribe(); - } - - unsubscribe(): void { - if (!isNil(this.navigationSubscription)) this.navigationSubscription.unsubscribe(); - if (!isNil(this.subscription)) this.subscription.unsubscribe(); - } -} \ No newline at end of file + private readonly forwardingList$: BehaviorSubject<StateResource<ForwardingListResource>> = + new BehaviorSubject(createEmptyStateResource<ForwardingListResource>()); + + private navigationSubscription: Subscription; + private subscription: Subscription; + + constructor( + private commandService: CommandService, + private vorgangService: VorgangService, + private navigationService: NavigationService, + private forwardingRepository: ForwardingRepository, + ) {} + + getForwardings( + vorgang: VorgangWithEingangResource, + ): Observable<StateResource<ForwardingListResource>> { + this.forwardingList$.next(createEmptyStateResource(true)); + + const subscription = this.forwardingRepository.getForwardings(vorgang).subscribe((list) => { + this.forwardingList$.next(createStateResource(list)); + subscription.unsubscribe(); + }); + + return this.forwardingList$.asObservable(); + } + + getPendingForwardCommand(): Observable<StateResource<CommandResource>> { + this.listenToNavigation(); + + return this.vorgangService + .getPendingForwardCommand() + .pipe(map((pendingCommand) => this.pollPendingForwardCommand(pendingCommand))); + } + + listenToNavigation(): void { + this.unsubscribe(); + this.navigationSubscription = this.navigationService + .urlChanged() + .subscribe((params) => this.onNavigation(params)); + } + + onNavigation(params: Params): void { + if (NavigationService.isVorgangListPage(params)) { + this.unsubscribe(); + } + } + + pollPendingForwardCommand( + command: StateResource<CommandResource>, + ): StateResource<CommandResource> { + if (this.shouldPoll(command)) { + this.subscription = this.commandService + .pollCommand(command.resource) + .subscribe((updatedCommand) => { + if (isDone(updatedCommand.resource)) { + this.vorgangService.setPendingForwardSingleCommand(updatedCommand); + this.reloadCurrentVorgang(updatedCommand); + this.subscription.unsubscribe(); + } + }); + } + return command; + } + + private shouldPoll(command: StateResource<CommandResource>): boolean { + return command.loaded && isPending(command.resource); + } + + public forward( + vorgang: VorgangResource, + request: ForwardRequest, + ): Observable<StateResource<CommandResource>> { + this.vorgangService.setPendingForwardSingleCommandLoading(); + const subscription: Subscription = this.commandService + .createCommand(vorgang, VorgangWithEingangLinkRel.FORWARD, createForwardCommand(request)) + .subscribe((command) => { + this.vorgangService.setPendingForwardSingleCommand(command); + this.reloadCurrentVorgang(command); + subscription.unsubscribe(); + }); + return this.vorgangService.getPendingForwardCommand(); + } + + markAsSuccess(forward: ForwardingResource): Observable<StateResource<CommandResource>> { + return this.createMarkAsCommand( + forward, + ForwardingLinkRel.MARK_AS_SUCCESS, + createForwardingMarkAsSuccessCommand(), + ).pipe(tap((command) => this.updateForwardingList(command))); + } + + markAsFail(forward: ForwardingResource): Observable<StateResource<CommandResource>> { + return this.createMarkAsCommand( + forward, + ForwardingLinkRel.MARK_AS_FAIL, + createForwardingMarkAsFailCommand(), + ).pipe( + tap((command) => { + if (isDone(command.resource)) this.reloadCurrentVorgang(command); + }), + ); + } + + reloadCurrentVorgang(command: StateResource<CommandResource>): void { + if (!hasError(command)) { + this.vorgangService.reloadCurrentVorgang(); + } + } + + createMarkAsCommand( + forward: ForwardingResource, + linkRel: string, + command: CreateCommand, + ): Observable<StateResource<CommandResource>> { + return this.commandService + .createCommand(forward, linkRel, command) + .pipe(startWith(createEmptyStateResource<CommandResource>(true))); + } + + updateForwardingList(command: StateResource<CommandResource>): void { + if (isDone(command.resource)) this.updateList(command.resource); + } + + updateList(command: CommandResource): void { + this.commandService + .getEffectedResource<ForwardingListResource>(command) + .pipe(first()) + .subscribe((list) => this.setList(list)); + } + + setList(list: ForwardingListResource): void { + this.forwardingList$.next(createStateResource(list)); + } + + ngOnDestroy(): void { + this.unsubscribe(); + } + + unsubscribe(): void { + if (!isNil(this.navigationSubscription)) this.navigationSubscription.unsubscribe(); + if (!isNil(this.subscription)) this.subscription.unsubscribe(); + } +} diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding.util.spec.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding.util.spec.ts index 06fda76d54de9bf7d9e4d6e2fdb91ce8c0aea421..81749b66792f278ac5db1b23c3f0b370f36c3091 100644 --- a/alfa-client/libs/forwarding-shared/src/lib/forwarding.util.spec.ts +++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding.util.spec.ts @@ -22,25 +22,25 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { CommandOrder, CreateCommand } from '@alfa-client/command-shared'; -import { createForwardingMarkAsFailCommand, createForwardingMarkAsSuccessCommand } from './forwarding.util'; +import { + createForwardingMarkAsFailCommand, + createForwardingMarkAsSuccessCommand, +} from './forwarding.util'; describe('ForwardingUtil', () => { + describe('create ForwardMarkAsSuccessCommand', () => { + it('should return command', () => { + const command: CreateCommand = createForwardingMarkAsSuccessCommand(); - describe('create ForwardMarkAsSuccessCommand', () => { + expect(command.order).toBe(CommandOrder.FORWARD_SUCCESSFULL); + }); + }); - it('should return command', () => { - const command: CreateCommand = createForwardingMarkAsSuccessCommand(); + describe('create ForwardMarkAsFailedCommand', () => { + it('should return command', () => { + const command: CreateCommand = createForwardingMarkAsFailCommand(); - expect(command.order).toBe(CommandOrder.FORWARD_SUCCESSFULL); - }) - }) - - describe('create ForwardMarkAsFailedCommand', () => { - - it('should return command', () => { - const command: CreateCommand = createForwardingMarkAsFailCommand(); - - expect(command.order).toBe(CommandOrder.FORWARD_FAILED); - }) - }) -}) \ No newline at end of file + expect(command.order).toBe(CommandOrder.FORWARD_FAILED); + }); + }); +}); diff --git a/alfa-client/libs/forwarding-shared/src/lib/forwarding.util.ts b/alfa-client/libs/forwarding-shared/src/lib/forwarding.util.ts index 2230441fe09b01482de9748fbe2d674236631668..84893c41ff4422e0a5ad116e0225e5c2501ebe38 100644 --- a/alfa-client/libs/forwarding-shared/src/lib/forwarding.util.ts +++ b/alfa-client/libs/forwarding-shared/src/lib/forwarding.util.ts @@ -24,9 +24,9 @@ import { CommandOrder, CreateCommand } from '@alfa-client/command-shared'; export function createForwardingMarkAsSuccessCommand(): CreateCommand { - return { order: CommandOrder.FORWARD_SUCCESSFULL, body: null }; + return { order: CommandOrder.FORWARD_SUCCESSFULL, body: null }; } export function createForwardingMarkAsFailCommand(): CreateCommand { - return { order: CommandOrder.FORWARD_FAILED, body: null }; -} \ No newline at end of file + return { order: CommandOrder.FORWARD_FAILED, body: null }; +} diff --git a/alfa-client/libs/forwarding-shared/src/test-setup.ts b/alfa-client/libs/forwarding-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/forwarding-shared/src/test-setup.ts +++ b/alfa-client/libs/forwarding-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/forwarding-shared/test/forwarding.ts b/alfa-client/libs/forwarding-shared/test/forwarding.ts index 0e297b87ba7bc88f03d6684ccfcdc0d78d30d738..5be388a1d11942af948b1f40f005e0819ac699f0 100644 --- a/alfa-client/libs/forwarding-shared/test/forwarding.ts +++ b/alfa-client/libs/forwarding-shared/test/forwarding.ts @@ -25,29 +25,33 @@ import { faker } from '@faker-js/faker'; import { toResource } from 'libs/tech-shared/test/resource'; import { times } from 'lodash-es'; import { ForwardingListLinkRel } from '../src/lib/forwarding.linkrel'; -import { Forwarding, ForwardingListResource, ForwardingResource } from '../src/lib/forwarding.model'; +import { + Forwarding, + ForwardingListResource, + ForwardingResource, +} from '../src/lib/forwarding.model'; export function createForwarding(): Forwarding { - return { - errorMessage: faker.random.words(15), - createdAt: faker.date.past(), - sentAt: faker.date.past(), - createdBy: faker.name.findName(), - createdByName: faker.name.findName(), - zustaendigeStelle: faker.random.words(5) - } + return { + errorMessage: faker.random.words(15), + createdAt: faker.date.past(), + sentAt: faker.date.past(), + createdBy: faker.name.findName(), + createdByName: faker.name.findName(), + zustaendigeStelle: faker.random.words(5), + }; } export function createForwardingResource(linkRel: string[] = []): ForwardingResource { - return toResource(createForwarding(), linkRel); + return toResource(createForwarding(), linkRel); } export function createForwardingResources(): ForwardingResource[] { - return times(10, () => createForwardingResource()); + return times(10, () => createForwardingResource()); } export function createForwardingListResource(linkRel: string[] = []): ForwardingListResource { - return toResource({}, [...linkRel], { - [ForwardingListLinkRel.FORWARDING_LIST]: createForwardingResources() - }) -} \ No newline at end of file + return toResource({}, [...linkRel], { + [ForwardingListLinkRel.FORWARDING_LIST]: createForwardingResources(), + }); +} diff --git a/alfa-client/libs/forwarding-shared/tsconfig.json b/alfa-client/libs/forwarding-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/forwarding-shared/tsconfig.json +++ b/alfa-client/libs/forwarding-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/forwarding-shared/tsconfig.lib.json b/alfa-client/libs/forwarding-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/forwarding-shared/tsconfig.lib.json +++ b/alfa-client/libs/forwarding-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/forwarding-shared/tsconfig.spec.json b/alfa-client/libs/forwarding-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/forwarding-shared/tsconfig.spec.json +++ b/alfa-client/libs/forwarding-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/forwarding/.eslintrc.json b/alfa-client/libs/forwarding/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/forwarding/.eslintrc.json +++ b/alfa-client/libs/forwarding/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/forwarding/jest.config.ts b/alfa-client/libs/forwarding/jest.config.ts index 14c9edb8c7d87d7f62c891b4263c6095431d8a90..459b4e5e75fd1f7d61cffe5583006161065fdd0f 100644 --- a/alfa-client/libs/forwarding/jest.config.ts +++ b/alfa-client/libs/forwarding/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'forwarding', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/forwarding', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'forwarding', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/forwarding', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/forwarding/project.json b/alfa-client/libs/forwarding/project.json index ec8a4c243ba631fbbc22338834d4146f6d6d0e27..1af3c28e4c3990be75ac1eb06bf82579613309da 100644 --- a/alfa-client/libs/forwarding/project.json +++ b/alfa-client/libs/forwarding/project.json @@ -1,29 +1,26 @@ { - "name": "forwarding", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/forwarding/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/forwarding/src/**/*.ts", - "libs/forwarding/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/forwarding"], - "options": { - "tsConfig": "libs/forwarding/tsconfig.spec.json", - "jestConfig": "libs/forwarding/jest.config.ts", - "passWithNoTests": true - } - } - }, - "tags": [] + "name": "forwarding", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/forwarding/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/forwarding/src/**/*.ts", "libs/forwarding/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/forwarding"], + "options": { + "tsConfig": "libs/forwarding/tsconfig.spec.json", + "jestConfig": "libs/forwarding/jest.config.ts", + "passWithNoTests": true + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/forwarding/src/index.ts b/alfa-client/libs/forwarding/src/index.ts index ebaecd62f10e521fc44946750bc4fae2cbe10ffa..21c4a788e7e4e28831abbf51d15e9a4176e94247 100644 --- a/alfa-client/libs/forwarding/src/index.ts +++ b/alfa-client/libs/forwarding/src/index.ts @@ -23,4 +23,3 @@ */ export * from './lib/forwarding.module'; export * from './lib/vorgang-forwarding-container/vorgang-forwarding-container.component'; - diff --git a/alfa-client/libs/forwarding/src/lib/forwarding.module.spec.ts b/alfa-client/libs/forwarding/src/lib/forwarding.module.spec.ts index 7764ba06a8ab6e6b541effa74f8b2d2a591d57a9..6209f96dedd1c12a2462d81b75b87edfd8566104 100644 --- a/alfa-client/libs/forwarding/src/lib/forwarding.module.spec.ts +++ b/alfa-client/libs/forwarding/src/lib/forwarding.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { ForwardingModule } from './forwarding.module'; describe('ForwardingModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ForwardingModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ForwardingModule], + }).compileComponents(); + }); - it('should create', () => { - expect(ForwardingModule).toBeDefined(); - }); + it('should create', () => { + expect(ForwardingModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/forwarding/src/lib/forwarding.module.ts b/alfa-client/libs/forwarding/src/lib/forwarding.module.ts index ccd775b5d206d326a675d1d1b0ef5c0f08057134..a2bd7bad70241de56a83b1c249fac068aabbd512 100644 --- a/alfa-client/libs/forwarding/src/lib/forwarding.module.ts +++ b/alfa-client/libs/forwarding/src/lib/forwarding.module.ts @@ -35,25 +35,17 @@ import { VorgangForwardingInfoComponent } from './vorgang-forwarding-container/v import { VorgangForwardZustellenContainerComponent } from './vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component'; @NgModule({ - imports: [ - CommonModule, - TechSharedModule, - ForwardingSharedModule, - CommandSharedModule, - UiModule - ], - declarations: [ - VorgangForwardZustellenContainerComponent, - VorgangForwardingContainerComponent, - VorgangForwardFormularComponent, - VorgangForwardingInfoComponent, - VorgangForwardingInfoListComponent, - VorgangForwardFormularComponent, - VorgangForwardZustellenContainerComponent, - VorgangForwardFormComponent - ], - exports: [ - VorgangForwardingContainerComponent - ] + imports: [CommonModule, TechSharedModule, ForwardingSharedModule, CommandSharedModule, UiModule], + declarations: [ + VorgangForwardZustellenContainerComponent, + VorgangForwardingContainerComponent, + VorgangForwardFormularComponent, + VorgangForwardingInfoComponent, + VorgangForwardingInfoListComponent, + VorgangForwardFormularComponent, + VorgangForwardZustellenContainerComponent, + VorgangForwardFormComponent, + ], + exports: [VorgangForwardingContainerComponent], }) -export class ForwardingModule { } +export class ForwardingModule {} diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.html b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.html index 7b6083760a648e76ae46d3465acf505208ceee56..4425e0e321397ec41da55df4e01bedb2dc04f172 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.html +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.html @@ -24,26 +24,28 @@ --> <form class="form" [formGroup]="form" (submit)="submit.emit()"> - - <ozgcloud-text-editor - label="zuständige Stelle" - [formControlName]="formServiceClass.FIELD_EMAIL" - autocomplete="email" - placeholder="E-Mail Adresse"> - </ozgcloud-text-editor> - - <ozgcloud-text-editor - label="Passwort" - [formControlName]="formServiceClass.FIELD_PASSWORD" - placeholder="Passwort für die Verschlüsselung"> - </ozgcloud-text-editor> - - <ozgcloud-stroked-button-with-spinner dataTestId="forward-button" - toolTip="Vorgang weiterleiten" - icon="forward" - type="submit" - text="Weiterleiten" - [stateResource]="forwardStateResource"> - </ozgcloud-stroked-button-with-spinner> - + <ozgcloud-text-editor + label="zuständige Stelle" + [formControlName]="formServiceClass.FIELD_EMAIL" + autocomplete="email" + placeholder="E-Mail Adresse" + > + </ozgcloud-text-editor> + + <ozgcloud-text-editor + label="Passwort" + [formControlName]="formServiceClass.FIELD_PASSWORD" + placeholder="Passwort für die Verschlüsselung" + > + </ozgcloud-text-editor> + + <ozgcloud-stroked-button-with-spinner + dataTestId="forward-button" + toolTip="Vorgang weiterleiten" + icon="forward" + type="submit" + text="Weiterleiten" + [stateResource]="forwardStateResource" + > + </ozgcloud-stroked-button-with-spinner> </form> diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.scss b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.scss index 0fd9f0e3198cbed064a327c8e9dd11b000236fa7..7e17b916f878cedfa9cb987a5108f6255dba2489 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.scss +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.scss @@ -22,14 +22,14 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .form { - display: flex; - width: 100%; - max-width: 320px; - flex-direction: column; + display: flex; + width: 100%; + max-width: 320px; + flex-direction: column; - ::ng-deep { - mat-form-field { - width: 100%; - } - } + ::ng-deep { + mat-form-field { + width: 100%; + } + } } diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.spec.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.spec.ts index f93b4fe5723350d06ae121f5360bde5621ea600f..8a9b1e30f948e60e643181f0c7d08f0bb29f0356 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.spec.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.spec.ts @@ -36,87 +36,86 @@ import { VorgangForwardFormComponent } from './vorgang-forward-form.component'; import { VorgangForwardFormService } from './vorgang-forward.formservice'; describe('VorgangForwardFormComponent', () => { - let component: VorgangForwardFormComponent; - let fixture: ComponentFixture<VorgangForwardFormComponent>; - - const form: UntypedFormGroup = new UntypedFormGroup({ - [VorgangForwardFormService.FIELD_PASSWORD]: new UntypedFormControl(null), - [VorgangForwardFormService.FIELD_EMAIL]: new UntypedFormControl(null) - }); - - const formService = { ...mock(VorgangForwardFormService), form }; - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangForwardFormComponent, - MatIcon, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(TextEditorComponent) - ], - imports: [ - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule, - BrowserAnimationsModule - ], - providers: [ - { - provide: VorgangForwardFormService, - useValue: formService - } - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(VorgangForwardFormComponent); - component = fixture.componentInstance; - component.vorgang = vorgangWithEingang; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('zustaendige stelle email exists', () => { - - it('should return false if vorgang is undefined', () => { - component.vorgang = undefined; - - var result: boolean = component.zustaendigeStelleEmailExists(); - - expect(result).toBeFalsy(); - }) - - it('should return true if exists', () => { - component.vorgang = vorgangWithEingang; - - var result: boolean = component.zustaendigeStelleEmailExists(); - - expect(result).toBeTruthy(); - }) - - it('should return false if NOT exists', () => { - component.vorgang = { ...vorgangWithEingang, eingang: { ...vorgangWithEingang.eingang, zustaendigeStelle: { email: null } } }; - - var result: boolean = component.zustaendigeStelleEmailExists(); - - expect(result).toBeFalsy(); - }) - }) - - describe('patch email field', () => { - - it('should set email', () => { - component.vorgang = vorgangWithEingang; - - component.patchEmail(); - - expect(formService.patchField).toHaveBeenCalledWith('email', vorgangWithEingang.eingang.zustaendigeStelle.email); - }) - }) + let component: VorgangForwardFormComponent; + let fixture: ComponentFixture<VorgangForwardFormComponent>; + + const form: UntypedFormGroup = new UntypedFormGroup({ + [VorgangForwardFormService.FIELD_PASSWORD]: new UntypedFormControl(null), + [VorgangForwardFormService.FIELD_EMAIL]: new UntypedFormControl(null), + }); + + const formService = { ...mock(VorgangForwardFormService), form }; + + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangForwardFormComponent, + MatIcon, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(TextEditorComponent), + ], + imports: [MatFormFieldModule, MatInputModule, ReactiveFormsModule, BrowserAnimationsModule], + providers: [ + { + provide: VorgangForwardFormService, + useValue: formService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangForwardFormComponent); + component = fixture.componentInstance; + component.vorgang = vorgangWithEingang; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('zustaendige stelle email exists', () => { + it('should return false if vorgang is undefined', () => { + component.vorgang = undefined; + + var result: boolean = component.zustaendigeStelleEmailExists(); + + expect(result).toBeFalsy(); + }); + + it('should return true if exists', () => { + component.vorgang = vorgangWithEingang; + + var result: boolean = component.zustaendigeStelleEmailExists(); + + expect(result).toBeTruthy(); + }); + + it('should return false if NOT exists', () => { + component.vorgang = { + ...vorgangWithEingang, + eingang: { ...vorgangWithEingang.eingang, zustaendigeStelle: { email: null } }, + }; + + var result: boolean = component.zustaendigeStelleEmailExists(); + + expect(result).toBeFalsy(); + }); + }); + + describe('patch email field', () => { + it('should set email', () => { + component.vorgang = vorgangWithEingang; + + component.patchEmail(); + + expect(formService.patchField).toHaveBeenCalledWith( + 'email', + vorgangWithEingang.eingang.zustaendigeStelle.email, + ); + }); + }); }); diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.ts index 8aa41964e680f16a6a8087d7f98cc28e9d4d1883..30bff416ffd815bd00a79b5f39acd8deaa28d08e 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward-form.component.ts @@ -30,36 +30,43 @@ import { isNil } from 'lodash-es'; import { VorgangForwardFormService } from './vorgang-forward.formservice'; @Component({ - selector: 'alfa-vorgang-forward-form', - templateUrl: './vorgang-forward-form.component.html', - styleUrls: ['./vorgang-forward-form.component.scss'] + selector: 'alfa-vorgang-forward-form', + templateUrl: './vorgang-forward-form.component.html', + styleUrls: ['./vorgang-forward-form.component.scss'], }) export class VorgangForwardFormComponent implements OnChanges { + @Input() forwardStateResource: StateResource<CommandResource>; + @Input() vorgang: VorgangWithEingangResource; - @Input() forwardStateResource: StateResource<CommandResource>; - @Input() vorgang: VorgangWithEingangResource; + @Output('doSubmit') submit: EventEmitter<void> = new EventEmitter(); - @Output('doSubmit') submit: EventEmitter<void> = new EventEmitter(); + readonly formServiceClass = VorgangForwardFormService; - readonly formServiceClass = VorgangForwardFormService; + constructor(private formService: VorgangForwardFormService) {} - constructor(private formService: VorgangForwardFormService) { } + ngOnChanges(changes: SimpleChanges) { + if (changes.vorgang && this.zustaendigeStelleEmailExists()) { + this.patchEmail(); + } + } - ngOnChanges(changes: SimpleChanges) { - if (changes.vorgang && this.zustaendigeStelleEmailExists()) { - this.patchEmail(); - } - } + zustaendigeStelleEmailExists(): boolean { + return ( + this.vorgang && + this.vorgang.eingang && + this.vorgang.eingang.zustaendigeStelle && + !isNil(this.vorgang.eingang.zustaendigeStelle.email) + ); + } - zustaendigeStelleEmailExists(): boolean { - return this.vorgang && this.vorgang.eingang && this.vorgang.eingang.zustaendigeStelle && !isNil(this.vorgang.eingang.zustaendigeStelle.email); - } + patchEmail(): void { + this.formService.patchField( + VorgangForwardFormService.FIELD_EMAIL, + this.vorgang.eingang.zustaendigeStelle.email, + ); + } - patchEmail(): void { - this.formService.patchField(VorgangForwardFormService.FIELD_EMAIL, this.vorgang.eingang.zustaendigeStelle.email) - } - - get form(): UntypedFormGroup { - return this.formService.form; - } + get form(): UntypedFormGroup { + return this.formService.form; + } } diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.spec.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.spec.ts index c66208dcbd1e424d1f616bbcf1204fa7f418a4e9..c575249626f61b61a60ff5d7392af835e28d864d 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.spec.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.spec.ts @@ -29,56 +29,54 @@ import { of } from 'rxjs'; import { VorgangForwardFormService } from './vorgang-forward.formservice'; describe('VorgangForwardFormService', () => { - let formService: VorgangForwardFormService; - let service; + let formService: VorgangForwardFormService; + let service; - const formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + const formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); - beforeEach(() => { - service = mock(ForwardingService); + beforeEach(() => { + service = mock(ForwardingService); - formService = new VorgangForwardFormService(formBuilder, useFromMock(service)); - }) + formService = new VorgangForwardFormService(formBuilder, useFromMock(service)); + }); - it('should create', () => { - expect(formService).toBeTruthy(); - }); + it('should create', () => { + expect(formService).toBeTruthy(); + }); - describe('submit', () => { + describe('submit', () => { + const returnValue = {}; - const returnValue = {}; + beforeEach(() => { + service.forward.mockReturnValue(of(returnValue)); + service.doSubmit = jest.fn(); + }); - beforeEach(() => { - service.forward.mockReturnValue(of(returnValue)); - service.doSubmit = jest.fn(); - }) + it('should call service', () => { + formService.vorgang = createVorgangResource(); - it('should call service', () => { - formService.vorgang = createVorgangResource(); + formService.submit(); - formService.submit(); + expect(service.forward).toHaveBeenCalledWith(formService.vorgang, formService.form.value); + }); + }); - expect(service.forward).toHaveBeenCalledWith(formService.vorgang, formService.form.value); - }) - }) + describe('patch field', () => { + const controlName: string = 'testField'; + const value: string = 'testField'; - describe('patch field', () => { + const form: UntypedFormGroup = <any>{ + controls: { + [controlName]: new UntypedFormControl(), + }, + }; - const controlName: string = 'testField'; - const value: string = 'testField'; + it('should set control value', () => { + formService.form = form; - const form: UntypedFormGroup = <any>{ - controls: { - [controlName]: new UntypedFormControl() - } - }; + formService.patchField(controlName, value); - it('should set control value', () => { - formService.form = form; - - formService.patchField(controlName, value); - - expect(formService.form.controls[controlName].value).toEqual(value); - }) - }) -}) \ No newline at end of file + expect(formService.form.controls[controlName].value).toEqual(value); + }); + }); +}); diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.ts index 5c55d9be7406dc1e343a5722d0e8c9acd5960e9f..550ff12cf4a72eb21edb4a57c8abd8295df8ab3d 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice.ts @@ -31,38 +31,40 @@ import { Observable } from 'rxjs'; @Injectable() export class VorgangForwardFormService extends AbstractFormService { + static readonly FIELD_PATH_PREFIX = 'command.redirectRequest'; - static readonly FIELD_PATH_PREFIX = 'command.redirectRequest'; + static readonly FIELD_EMAIL = 'email'; + static readonly FIELD_PASSWORD = 'password'; - static readonly FIELD_EMAIL = 'email'; - static readonly FIELD_PASSWORD = 'password'; + vorgang: VorgangResource; - vorgang: VorgangResource; + constructor( + formBuilder: UntypedFormBuilder, + private forwardingService: ForwardingService, + ) { + super(formBuilder); + } - constructor(formBuilder: UntypedFormBuilder, private forwardingService: ForwardingService) { - super(formBuilder); - } + protected initForm(): UntypedFormGroup { + return this.formBuilder.group({ + [VorgangForwardFormService.FIELD_EMAIL]: new UntypedFormControl(), + [VorgangForwardFormService.FIELD_PASSWORD]: new UntypedFormControl(), + }); + } - protected initForm(): UntypedFormGroup { - return this.formBuilder.group({ - [VorgangForwardFormService.FIELD_EMAIL]: new UntypedFormControl(), - [VorgangForwardFormService.FIELD_PASSWORD]: new UntypedFormControl() - }) - } + protected getPathPrefix(): string { + return VorgangForwardFormService.FIELD_PATH_PREFIX; + } - protected getPathPrefix(): string { - return VorgangForwardFormService.FIELD_PATH_PREFIX; - } + public setVorgang(vorgang: VorgangResource): void { + this.vorgang = vorgang; + } - public setVorgang(vorgang: VorgangResource): void { - this.vorgang = vorgang; - } + protected doSubmit(): Observable<StateResource<CommandResource>> { + return this.forwardingService.forward(this.vorgang, this.getFormValue()); + } - protected doSubmit(): Observable<StateResource<CommandResource>> { - return this.forwardingService.forward(this.vorgang, this.getFormValue()); - } - - patchField(fieldName: string, value: string) { - this.form.controls[fieldName].patchValue(value); - } + patchField(fieldName: string, value: string) { + this.form.controls[fieldName].patchValue(value); + } } diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.html b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.html index 494b5ec561a9c9b606068e31510d7cc35822afa5..f9816537fedd9f86af220f79063c58ce5f337efc 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.html +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.html @@ -23,15 +23,20 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ozgcloud-spinner data-test-id="forwarding-spinner" - [diameter]="24" - [show]="pendingForwardCommand.resource | hasLink: commandLinkRel.UPDATE" - padding="0" - text="Vorgang wird weitergeleitet"> +<ozgcloud-spinner + data-test-id="forwarding-spinner" + [diameter]="24" + [show]="pendingForwardCommand.resource | hasLink: commandLinkRel.UPDATE" + padding="0" + text="Vorgang wird weitergeleitet" +> </ozgcloud-spinner> -<alfa-vorgang-forward-form *ngIf="vorgang | hasLink: vorgangLinkRel.FORWARD" data-test-id="forward-form" - [vorgang]="vorgang" - [forwardStateResource]="pendingForwardCommand" - (doSubmit)="submit.emit()"> +<alfa-vorgang-forward-form + *ngIf="vorgang | hasLink: vorgangLinkRel.FORWARD" + data-test-id="forward-form" + [vorgang]="vorgang" + [forwardStateResource]="pendingForwardCommand" + (doSubmit)="submit.emit()" +> </alfa-vorgang-forward-form> diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.spec.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.spec.ts index c38811cdeec9344a1cf1bde510600cd7482b6c8c..fd909792f0675e3d96c2e3e42d2055c085f1beb8 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.spec.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.spec.ts @@ -31,51 +31,50 @@ import { VorgangForwardFormComponent } from './vorgang-forward-form/vorgang-forw import { VorgangForwardFormularComponent } from './vorgang-forward-formular.component'; describe('VorgangForwardFormularComponent', () => { - let component: VorgangForwardFormularComponent; - let fixture: ComponentFixture<VorgangForwardFormularComponent>; + let component: VorgangForwardFormularComponent; + let fixture: ComponentFixture<VorgangForwardFormularComponent>; - const forwardFormular: string = '[data-test-id="forward-form"]'; + const forwardFormular: string = '[data-test-id="forward-form"]'; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangForwardFormularComponent, - HasLinkPipe, - MockComponent(SpinnerComponent), - MockComponent(VorgangForwardFormComponent) - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangForwardFormularComponent, + HasLinkPipe, + MockComponent(SpinnerComponent), + MockComponent(VorgangForwardFormComponent), + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangForwardFormularComponent); - component = fixture.componentInstance; - component.pendingForwardCommand = createEmptyStateResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangForwardFormularComponent); + component = fixture.componentInstance; + component.pendingForwardCommand = createEmptyStateResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('forward formular', () => { + describe('forward formular', () => { + it('should show', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARD]); + fixture.detectChanges(); - it('should show', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARD]); - fixture.detectChanges(); + const element = fixture.nativeElement.querySelector(forwardFormular); - const element = fixture.nativeElement.querySelector(forwardFormular); + expect(element).toBeInstanceOf(HTMLElement); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) + it('should not show', () => { + component.vorgang = createVorgangWithEingangResource(); + fixture.detectChanges(); - it('should not show', () => { - component.vorgang = createVorgangWithEingangResource(); - fixture.detectChanges(); + const element = fixture.nativeElement.querySelector(forwardFormular); - const element = fixture.nativeElement.querySelector(forwardFormular); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.ts index 8730fa82f077a9c9f3036f60cbc7496293a328e4..55884089f339a5d448d8f06f35e08b85835846cb 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forward-formular/vorgang-forward-formular.component.ts @@ -28,17 +28,16 @@ import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-cli import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; @Component({ - selector: 'alfa-vorgang-forward-formular', - templateUrl: './vorgang-forward-formular.component.html', - styleUrls: ['./vorgang-forward-formular.component.scss'] + selector: 'alfa-vorgang-forward-formular', + templateUrl: './vorgang-forward-formular.component.html', + styleUrls: ['./vorgang-forward-formular.component.scss'], }) export class VorgangForwardFormularComponent { + @Input() public vorgang: VorgangWithEingangResource; + @Input() public pendingForwardCommand: StateResource<CommandResource>; - @Input() public vorgang: VorgangWithEingangResource; - @Input() public pendingForwardCommand: StateResource<CommandResource>; + @Output('doSubmit') submit: EventEmitter<void> = new EventEmitter(); - @Output('doSubmit') submit: EventEmitter<void> = new EventEmitter(); - - readonly commandLinkRel = CommandLinkRel; - readonly vorgangLinkRel = VorgangWithEingangLinkRel; -} \ No newline at end of file + readonly commandLinkRel = CommandLinkRel; + readonly vorgangLinkRel = VorgangWithEingangLinkRel; +} diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.html b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.html index 737dee089f8a26fd6e7dd5d00c27ba47ad5bd55e..20817a37f97aa64b8d5931020b7af3f1585227fa 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.html +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.html @@ -23,21 +23,28 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ng-container *ngIf="(vorgang | hasLink: vorgangLinkRel.FORWARD) || (vorgang | hasLink: vorgangLinkRel.FORWARDING)"> - - <ozgcloud-expansion-panel headline="Vorgang weiterleiten" data-test-id="forwarding" *ngIf="forwardingStateResources$ |async as forwardingStateResources"> - - <ozgcloud-spinner [stateResource]="forwardingStateResources"> - <alfa-vorgang-forwarding-info-list [forwardingList]="forwardingStateResources"></alfa-vorgang-forwarding-info-list> - </ozgcloud-spinner> - - - <alfa-vorgang-forward-formular data-test-id="forward-formular" - [vorgang]="vorgang" - [pendingForwardCommand]="pendingForwardStateResource$ | async" - (doSubmit)="submit()"> - </alfa-vorgang-forward-formular> - - </ozgcloud-expansion-panel> - -</ng-container> \ No newline at end of file +<ng-container + *ngIf=" + (vorgang | hasLink: vorgangLinkRel.FORWARD) || (vorgang | hasLink: vorgangLinkRel.FORWARDING) + " +> + <ozgcloud-expansion-panel + headline="Vorgang weiterleiten" + data-test-id="forwarding" + *ngIf="forwardingStateResources$ | async as forwardingStateResources" + > + <ozgcloud-spinner [stateResource]="forwardingStateResources"> + <alfa-vorgang-forwarding-info-list + [forwardingList]="forwardingStateResources" + ></alfa-vorgang-forwarding-info-list> + </ozgcloud-spinner> + + <alfa-vorgang-forward-formular + data-test-id="forward-formular" + [vorgang]="vorgang" + [pendingForwardCommand]="pendingForwardStateResource$ | async" + (doSubmit)="submit()" + > + </alfa-vorgang-forward-formular> + </ozgcloud-expansion-panel> +</ng-container> diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.spec.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.spec.ts index e839c3db2fbb0a6093e8ecee447ad74078c6dc30..d9f2cc875f49c0f514134f8715c6d09fb5491a5e 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.spec.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.spec.ts @@ -29,7 +29,10 @@ import { mock } from '@alfa-client/test-utils'; import { ExpansionPanelComponent, SpinnerComponent } from '@alfa-client/ui'; import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; import { createCommandResource } from 'libs/command-shared/test/command'; -import { createVorgangForwardRequest, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; +import { + createVorgangForwardRequest, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; import { MockComponent } from 'ng-mocks'; import { of } from 'rxjs'; import { VorgangForwardFormService } from './vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice'; @@ -38,152 +41,153 @@ import { VorgangForwardingContainerComponent } from './vorgang-forwarding-contai import { VorgangForwardingInfoListComponent } from './vorgang-forwarding-info-list/vorgang-forwarding-info-list.component'; describe('VorgangForwardingContainerComponent', () => { - let component: VorgangForwardingContainerComponent; - let fixture: ComponentFixture<VorgangForwardingContainerComponent>; + let component: VorgangForwardingContainerComponent; + let fixture: ComponentFixture<VorgangForwardingContainerComponent>; + + const formService = mock(VorgangForwardFormService); + const service = mock(ForwardingService); + + const forwarding: string = '[data-test-id="forwarding"]'; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangForwardingContainerComponent, + HasLinkPipe, + MockComponent(SpinnerComponent), + MockComponent(VorgangForwardingInfoListComponent), + MockComponent(VorgangForwardFormularComponent), + MockComponent(ExpansionPanelComponent), + ], + providers: [ + UntypedFormBuilder, + { + provide: VorgangForwardFormService, + useValue: formService, + }, + { + provide: ForwardingService, + useValue: service, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangForwardingContainerComponent); + component = fixture.componentInstance; + component.pendingForwardStateResource$ = of( + createStateResource({ + ...createCommandResource(), + redirectRequest: createVorgangForwardRequest(), + }), + ); + component.vorgang = createVorgangWithEingangResource(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnChanges', () => { + it('should call update vorgang', () => { + component.updateVorgang = jest.fn(); + + component.ngOnChanges(); + + expect(component.updateVorgang).toHaveBeenCalled(); + }); + + it('should call get forwardings', () => { + component.getForwardings = jest.fn(); + + component.ngOnChanges(); + + expect(component.getForwardings).toHaveBeenCalled(); + }); + + it('should call get pending forward command', () => { + component.getPendingForwardCommand = jest.fn(); + + component.ngOnChanges(); + + expect(component.getPendingForwardCommand).toHaveBeenCalled(); + }); + }); + + describe('getForwardings', () => { + it('should do nothing if link not exists', () => { + component.vorgang = createVorgangWithEingangResource(); + fixture.detectChanges(); + + component.getForwardings(); + + expect(service.getForwardings).not.toHaveBeenCalled(); + }); + + it('should call service get forward commands', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARDING]); + fixture.detectChanges(); + + component.getForwardings(); + + expect(service.getForwardings).toHaveBeenCalled(); + }); + }); + + describe('getPendingForwardCommand', () => { + it('should call service get pending forward command', () => { + component.vorgang = createVorgangWithEingangResource(); + fixture.detectChanges(); + + component.getPendingForwardCommand(); + + expect(service.getPendingForwardCommand).toHaveBeenCalled(); + }); + }); + + describe('forwarding', () => { + describe('on forwarding link', () => { + it('should show if exists', () => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.FORWARDING, + ]); + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector(forwarding); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should hide is not exists', () => { + component.vorgang = createVorgangWithEingangResource(); + fixture.detectChanges(); - const formService = mock(VorgangForwardFormService); - const service = mock(ForwardingService); + const element = fixture.nativeElement.querySelector(forwarding); - const forwarding: string = '[data-test-id="forwarding"]'; + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangForwardingContainerComponent, - HasLinkPipe, - MockComponent(SpinnerComponent), - MockComponent(VorgangForwardingInfoListComponent), - MockComponent(VorgangForwardFormularComponent), - MockComponent(ExpansionPanelComponent) - ], - providers: [ - UntypedFormBuilder, - { - provide: VorgangForwardFormService, - useValue: formService - }, - { - provide: ForwardingService, - useValue: service - } - ] - }) - }) + describe('on forward link', () => { + it('should show if exists', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARD]); + fixture.detectChanges(); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangForwardingContainerComponent); - component = fixture.componentInstance; - component.pendingForwardStateResource$ = of(createStateResource({ ...createCommandResource(), redirectRequest: createVorgangForwardRequest() })); - component.vorgang = createVorgangWithEingangResource(); - fixture.detectChanges(); - }); + const element = fixture.nativeElement.querySelector(forwarding); - it('should create', () => { - expect(component).toBeTruthy(); - }); + expect(element).toBeInstanceOf(HTMLElement); + }); - describe('ngOnChanges', () => { + it('should hide is not exists', () => { + component.vorgang = createVorgangWithEingangResource(); + fixture.detectChanges(); - it('should call update vorgang', () => { - component.updateVorgang = jest.fn(); + const element = fixture.nativeElement.querySelector(forwarding); - component.ngOnChanges(); - - expect(component.updateVorgang).toHaveBeenCalled(); - }) - - it('should call get forwardings', () => { - component.getForwardings = jest.fn(); - - component.ngOnChanges(); - - expect(component.getForwardings).toHaveBeenCalled(); - }) - - it('should call get pending forward command', () => { - component.getPendingForwardCommand = jest.fn(); - - component.ngOnChanges(); - - expect(component.getPendingForwardCommand).toHaveBeenCalled(); - }) - }) - - describe('getForwardings', () => { - - it('should do nothing if link not exists', () => { - component.vorgang = createVorgangWithEingangResource(); - fixture.detectChanges(); - - component.getForwardings(); - - expect(service.getForwardings).not.toHaveBeenCalled(); - }) - - it('should call service get forward commands', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARDING]); - fixture.detectChanges(); - - component.getForwardings(); - - expect(service.getForwardings).toHaveBeenCalled(); - }) - }) - - describe('getPendingForwardCommand', () => { - - it('should call service get pending forward command', () => { - component.vorgang = createVorgangWithEingangResource(); - fixture.detectChanges(); - - component.getPendingForwardCommand(); - - expect(service.getPendingForwardCommand).toHaveBeenCalled(); - }) - }) - - describe('forwarding', () => { - - describe('on forwarding link', () => { - - it('should show if exists', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARDING]); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(forwarding); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should hide is not exists', () => { - component.vorgang = createVorgangWithEingangResource(); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(forwarding); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('on forward link', () => { - - it('should show if exists', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARD]); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(forwarding); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should hide is not exists', () => { - component.vorgang = createVorgangWithEingangResource(); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(forwarding); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - }) -}) + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + }); +}); diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.ts index 4dbee190122c21ce768a8abd98c5fd0c5bc2302c..10c25d1ab793e2ea9e65c68a315a36e06e060078 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-container.component.ts @@ -32,45 +32,53 @@ import { Observable, of } from 'rxjs'; import { VorgangForwardFormService } from './vorgang-forward-formular/vorgang-forward-form/vorgang-forward.formservice'; @Component({ - selector: 'alfa-vorgang-forwarding-container', - templateUrl: './vorgang-forwarding-container.component.html', - styleUrls: ['./vorgang-forwarding-container.component.scss'], - providers: [VorgangForwardFormService] + selector: 'alfa-vorgang-forwarding-container', + templateUrl: './vorgang-forwarding-container.component.html', + styleUrls: ['./vorgang-forwarding-container.component.scss'], + providers: [VorgangForwardFormService], }) export class VorgangForwardingContainerComponent implements OnChanges { + @Input() public vorgang: VorgangWithEingangResource; - @Input() public vorgang: VorgangWithEingangResource; + forwardingStateResources$: Observable<StateResource<ForwardingListResource>> = of( + createEmptyStateResource<ForwardingListResource>(), + ); + pendingForwardStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - forwardingStateResources$: Observable<StateResource<ForwardingListResource>> = of(createEmptyStateResource<ForwardingListResource>()); - pendingForwardStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = CommandLinkRel; + readonly vorgangLinkRel = VorgangWithEingangLinkRel; - readonly linkRel = CommandLinkRel; - readonly vorgangLinkRel = VorgangWithEingangLinkRel; + constructor( + public formService: VorgangForwardFormService, + private forwardingService: ForwardingService, + ) {} - constructor(public formService: VorgangForwardFormService, private forwardingService: ForwardingService) { } + ngOnChanges(): void { + this.updateVorgang(); - ngOnChanges(): void { - this.updateVorgang(); + this.getForwardings(); + this.getPendingForwardCommand(); + } - this.getForwardings(); - this.getPendingForwardCommand(); - } + updateVorgang(): void { + this.formService.setVorgang(this.vorgang); + } - updateVorgang(): void { - this.formService.setVorgang(this.vorgang); - } + getForwardings(): void { + if (hasLink(this.vorgang, VorgangWithEingangLinkRel.FORWARDING)) { + this.forwardingStateResources$ = this.forwardingService.getForwardings(this.vorgang); + } + } - getForwardings(): void { - if (hasLink(this.vorgang, VorgangWithEingangLinkRel.FORWARDING)) { - this.forwardingStateResources$ = this.forwardingService.getForwardings(this.vorgang); - } - } + getPendingForwardCommand(): void { + this.pendingForwardStateResource$ = this.forwardingService.getPendingForwardCommand(); + } - getPendingForwardCommand(): void { - this.pendingForwardStateResource$ = this.forwardingService.getPendingForwardCommand(); - } - - submit(): void { - this.pendingForwardStateResource$ = <Observable<StateResource<CommandResource>>>this.formService.submit(); - } -} \ No newline at end of file + submit(): void { + this.pendingForwardStateResource$ = <Observable<StateResource<CommandResource>>>( + this.formService.submit() + ); + } +} diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.html b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.html index 509b20d79a4528ad1698680fe904a123907830b5..d7121cf3480e3d54378726a09da3bb7ee75dd71a 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.html +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.html @@ -23,6 +23,10 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-vorgang-forwarding-info *ngFor="let forwarding of (forwardingList.resource | toEmbeddedResources: listLinkRel.FORWARDING_LIST)" - [forwarding]="forwarding"> +<alfa-vorgang-forwarding-info + *ngFor=" + let forwarding of forwardingList.resource | toEmbeddedResources: listLinkRel.FORWARDING_LIST + " + [forwarding]="forwarding" +> </alfa-vorgang-forwarding-info> diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.spec.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.spec.ts index 0af09e04ad179be9757cc36adece3a5291b2dba8..4df6096228b44befcc1b916dc925035b4f8d4a02 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.spec.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.spec.ts @@ -29,27 +29,27 @@ import { VorgangForwardingInfoListComponent } from './vorgang-forwarding-info-li import { VorgangForwardingInfoComponent } from './vorgang-forwarding-info/vorgang-forwarding-info.component'; describe('VorgangForwardingInfoListComponent', () => { - let component: VorgangForwardingInfoListComponent; - let fixture: ComponentFixture<VorgangForwardingInfoListComponent>; + let component: VorgangForwardingInfoListComponent; + let fixture: ComponentFixture<VorgangForwardingInfoListComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangForwardingInfoListComponent, - MockComponent(VorgangForwardingInfoComponent), - ToEmbeddedResourcesPipe - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangForwardingInfoListComponent, + MockComponent(VorgangForwardingInfoComponent), + ToEmbeddedResourcesPipe, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangForwardingInfoListComponent); - component = fixture.componentInstance; - component.forwardingList = createStateResource(createCommandListResource()); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangForwardingInfoListComponent); + component = fixture.componentInstance; + component.forwardingList = createStateResource(createCommandListResource()); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.ts index 20aa2c4652b59cef89afd0b46899d1a4b593454e..47dfc5f0a18e1860cc07907f98f3931b4eaf8dcf 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info-list.component.ts @@ -27,13 +27,12 @@ import { ForwardingListLinkRel } from '@alfa-client/forwarding-shared'; import { StateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-vorgang-forwarding-info-list', - templateUrl: './vorgang-forwarding-info-list.component.html', - styleUrls: ['./vorgang-forwarding-info-list.component.scss'] + selector: 'alfa-vorgang-forwarding-info-list', + templateUrl: './vorgang-forwarding-info-list.component.html', + styleUrls: ['./vorgang-forwarding-info-list.component.scss'], }) export class VorgangForwardingInfoListComponent { + @Input() public forwardingList: StateResource<CommandListResource>; - @Input() public forwardingList: StateResource<CommandListResource>; - - readonly listLinkRel = ForwardingListLinkRel; -} \ No newline at end of file + readonly listLinkRel = ForwardingListLinkRel; +} diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.html b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.html index e5573a9275757dbbce48e7187bfe886ea8ea603f..6642dcd2756153329ac7e478e9783aa22e14db6e 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.html +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.html @@ -24,20 +24,25 @@ --> <div class="error" *ngIf="forwarding | hasLink: linkRel.ERROR; else success"> - <p data-test-id="forwarding-error-message"> - {{ forwarding.createdByName }} hat versucht, den Vorgang am {{ forwarding.createdAt | formatDateWithTimePipe }} - an {{ forwarding.zustaendigeStelle }} weiterzuleiten.<br> - Die Versendung war nicht erfolgreich, die Fehlermeldung lautet:<br> - <span class="message">{{ forwarding.errorMessage }}</span> - </p> - <mat-icon class="icon">error_outline</mat-icon> + <p data-test-id="forwarding-error-message"> + {{ forwarding.createdByName }} hat versucht, den Vorgang am + {{ forwarding.createdAt | formatDateWithTimePipe }} an + {{ forwarding.zustaendigeStelle }} weiterzuleiten.<br /> + Die Versendung war nicht erfolgreich, die Fehlermeldung lautet:<br /> + <span class="message">{{ forwarding.errorMessage }}</span> + </p> + <mat-icon class="icon">error_outline</mat-icon> </div> <ng-template #success> - <p data-test-id="forwarding-success-message"> - {{ forwarding.createdByName }} hat den Vorgang am {{ forwarding.createdAt | formatDateWithTimePipe }} an {{ forwarding.zustaendigeStelle }} weitergeleitet.<br> - Versendet am {{ forwarding.sentAt | formatDateWithTimePipe }} - </p> + <p data-test-id="forwarding-success-message"> + {{ forwarding.createdByName }} hat den Vorgang am + {{ forwarding.createdAt | formatDateWithTimePipe }} an + {{ forwarding.zustaendigeStelle }} weitergeleitet.<br /> + Versendet am {{ forwarding.sentAt | formatDateWithTimePipe }} + </p> - <alfa-vorgang-forward-zustellen-container [forwarding]="forwarding"></alfa-vorgang-forward-zustellen-container> + <alfa-vorgang-forward-zustellen-container + [forwarding]="forwarding" + ></alfa-vorgang-forward-zustellen-container> </ng-template> diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.scss b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.scss index 630fb3bd3e7c0b7b99e3c5954cd77c02da90fff8..d464bb94ff14893bafe94f2bcb0d5dd567203e0e 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.scss +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.scss @@ -22,24 +22,24 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: block; - margin-bottom: 16px; + display: block; + margin-bottom: 16px; } .error { - display: flex; + display: flex; } .icon { - margin: 0 0 4px 4px; + margin: 0 0 4px 4px; } .message { - opacity: 0.6; - margin: 4px 0; - display: inline-block; - font-size: 0.84em; + opacity: 0.6; + margin: 4px 0; + display: inline-block; + font-size: 0.84em; } p { - margin-bottom: 0; + margin-bottom: 0; } diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.spec.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.spec.ts index 3e8e321d1af87c59ca318b0221e76677c6ecba92..5a67e3eb934f2261603ff219fd4a1e8e2464ff9e 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.spec.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.spec.ts @@ -38,78 +38,76 @@ import { VorgangForwardingInfoComponent } from './vorgang-forwarding-info.compon registerLocaleData(localeDe, 'de', localeDeExtra); describe('VorgangForwardingInfoComponent', () => { - let component: VorgangForwardingInfoComponent; - let fixture: ComponentFixture<VorgangForwardingInfoComponent>; - - const errorMessage: string = '[data-test-id="forwarding-error-message"]'; - const successMessage: string = '[data-test-id="forwarding-success-message"]'; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangForwardingInfoComponent, - FormatDateWithTimePipe, - MatIcon, - HasLinkPipe, - MockComponent(VorgangForwardZustellenContainerComponent) - ], - providers: [ - { provide: LOCALE_ID, useValue: 'de' }, - { provide: MAT_DATE_LOCALE, useValue: 'de-DE' } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(VorgangForwardingInfoComponent); - component = fixture.componentInstance; - component.forwarding = createForwardingResource(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('on forwarding error', () => { - - it('should show error message', () => { - component.forwarding = createForwardingResource([ForwardingLinkRel.ERROR]); - fixture.detectChanges(); - - const message = fixture.nativeElement.querySelector(errorMessage); - - expect(message).toBeInstanceOf(HTMLElement); - }) - - it('should hide successfull message', () => { - component.forwarding = createForwardingResource([ForwardingLinkRel.ERROR]); - fixture.detectChanges(); - - const message = fixture.nativeElement.querySelector(successMessage); - - expect(message).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('on success forwarding', () => { - - it('should hide error message', () => { - component.forwarding = createForwardingResource(); - fixture.detectChanges(); - - const message = fixture.nativeElement.querySelector(errorMessage); - - expect(message).not.toBeInstanceOf(HTMLElement); - }) - - it('should show success message', () => { - component.forwarding = createForwardingResource(); - fixture.detectChanges(); - - const message = fixture.nativeElement.querySelector(successMessage); - - expect(message).toBeInstanceOf(HTMLElement); - }) - }) + let component: VorgangForwardingInfoComponent; + let fixture: ComponentFixture<VorgangForwardingInfoComponent>; + + const errorMessage: string = '[data-test-id="forwarding-error-message"]'; + const successMessage: string = '[data-test-id="forwarding-success-message"]'; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangForwardingInfoComponent, + FormatDateWithTimePipe, + MatIcon, + HasLinkPipe, + MockComponent(VorgangForwardZustellenContainerComponent), + ], + providers: [ + { provide: LOCALE_ID, useValue: 'de' }, + { provide: MAT_DATE_LOCALE, useValue: 'de-DE' }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangForwardingInfoComponent); + component = fixture.componentInstance; + component.forwarding = createForwardingResource(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('on forwarding error', () => { + it('should show error message', () => { + component.forwarding = createForwardingResource([ForwardingLinkRel.ERROR]); + fixture.detectChanges(); + + const message = fixture.nativeElement.querySelector(errorMessage); + + expect(message).toBeInstanceOf(HTMLElement); + }); + + it('should hide successfull message', () => { + component.forwarding = createForwardingResource([ForwardingLinkRel.ERROR]); + fixture.detectChanges(); + + const message = fixture.nativeElement.querySelector(successMessage); + + expect(message).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('on success forwarding', () => { + it('should hide error message', () => { + component.forwarding = createForwardingResource(); + fixture.detectChanges(); + + const message = fixture.nativeElement.querySelector(errorMessage); + + expect(message).not.toBeInstanceOf(HTMLElement); + }); + + it('should show success message', () => { + component.forwarding = createForwardingResource(); + fixture.detectChanges(); + + const message = fixture.nativeElement.querySelector(successMessage); + + expect(message).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.ts index 773cc951124adcbd39812c93c086416934c2dd15..e91685aac341cb9251ddec6b373a2c5c3cbb3d1f 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-container/vorgang-forwarding-info-list/vorgang-forwarding-info/vorgang-forwarding-info.component.ts @@ -25,13 +25,12 @@ import { Component, Input } from '@angular/core'; import { ForwardingLinkRel, ForwardingResource } from '@alfa-client/forwarding-shared'; @Component({ - selector: 'alfa-vorgang-forwarding-info', - templateUrl: './vorgang-forwarding-info.component.html', - styleUrls: ['./vorgang-forwarding-info.component.scss'] + selector: 'alfa-vorgang-forwarding-info', + templateUrl: './vorgang-forwarding-info.component.html', + styleUrls: ['./vorgang-forwarding-info.component.scss'], }) export class VorgangForwardingInfoComponent { + @Input() public forwarding: ForwardingResource; - @Input() public forwarding: ForwardingResource; - - readonly linkRel = ForwardingLinkRel; -} \ No newline at end of file + readonly linkRel = ForwardingLinkRel; +} diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.html b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.html index d09d5fb8200670f8d9975fae9e1ba9a9ab82dda0..32f528b920398e6979ade9115c5e67399d3a70fa 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.html +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.html @@ -23,32 +23,46 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<p *ngIf="forwarding | hasLink: linkRel.MARK_AS_SUCCESS">Wurde die Weiterleitung des Vorgangs bestätigt?</p> +<p *ngIf="forwarding | hasLink: linkRel.MARK_AS_SUCCESS"> + Wurde die Weiterleitung des Vorgangs bestätigt? +</p> -<div *ngIf="forwarding | hasLink: linkRel.SUCCESSFUL" class="confirmation" data-test-id="successfull-message"> - <span>Die Weiterleitung des Vorgangs wurde bestätigt.</span> - <mat-icon>check_circle_outline</mat-icon> +<div + *ngIf="forwarding | hasLink: linkRel.SUCCESSFUL" + class="confirmation" + data-test-id="successfull-message" +> + <span>Die Weiterleitung des Vorgangs wurde bestätigt.</span> + <mat-icon>check_circle_outline</mat-icon> </div> -<div *ngIf="forwarding | hasLink: linkRel.FAILED" class="confirmation" data-test-id="failed-message"> - <span>Die Weiterleitung des Vorgangs war nicht erfolgreich.</span> - <mat-icon>info_outline</mat-icon> +<div + *ngIf="forwarding | hasLink: linkRel.FAILED" + class="confirmation" + data-test-id="failed-message" +> + <span>Die Weiterleitung des Vorgangs war nicht erfolgreich.</span> + <mat-icon>info_outline</mat-icon> </div> <div class="buttons"> - <ozgcloud-stroked-button-with-spinner *ngIf="forwarding | hasLink: linkRel.MARK_AS_SUCCESS" - data-test-id="mark-as-success-button" - text="Bestätigen" - icon="check_circle_outline" - [stateResource]="markAsSuccessCommandStateResource$ | async" - (clickEmitter)="markAsSuccess()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-stroked-button-with-spinner *ngIf="forwarding | hasLink: linkRel.MARK_AS_FAIL" - data-test-id="mark-as-fail-button" - text="Widerrufen" - icon="info_outline" - [stateResource]="markAsFailCommandStateResource$ | async" - (clickEmitter)="markAsFail()"> - </ozgcloud-stroked-button-with-spinner> + <ozgcloud-stroked-button-with-spinner + *ngIf="forwarding | hasLink: linkRel.MARK_AS_SUCCESS" + data-test-id="mark-as-success-button" + text="Bestätigen" + icon="check_circle_outline" + [stateResource]="markAsSuccessCommandStateResource$ | async" + (clickEmitter)="markAsSuccess()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-stroked-button-with-spinner + *ngIf="forwarding | hasLink: linkRel.MARK_AS_FAIL" + data-test-id="mark-as-fail-button" + text="Widerrufen" + icon="info_outline" + [stateResource]="markAsFailCommandStateResource$ | async" + (clickEmitter)="markAsFail()" + > + </ozgcloud-stroked-button-with-spinner> </div> diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.scss b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.scss index fb71fab60423d679b49d557e488803eb691ce75c..c096bd8568ca625f68e556d7f397df8ead2f148d 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.scss +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.scss @@ -22,20 +22,20 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .confirmation { - display: flex; - justify-content: space-between; - align-items: center; + display: flex; + justify-content: space-between; + align-items: center; } .buttons { - margin: 16px -8px; - display: flex; + margin: 16px -8px; + display: flex; - ozgcloud-stroked-button-with-spinner { - margin: 0 8px; - } + ozgcloud-stroked-button-with-spinner { + margin: 0 8px; + } } p { - margin-top: 4px; + margin-top: 4px; } diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.spec.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.spec.ts index 15f8ce022bad28158419e3a5c678c9c671d5123a..5e93ab53c997990ccf3e71fa036559e427ae8bee 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.spec.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.spec.ts @@ -23,7 +23,11 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatIcon } from '@angular/material/icon'; -import { ForwardingLinkRel, ForwardingResource, ForwardingService } from '@alfa-client/forwarding-shared'; +import { + ForwardingLinkRel, + ForwardingResource, + ForwardingService, +} from '@alfa-client/forwarding-shared'; import { HasLinkPipe } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; @@ -32,145 +36,141 @@ import { MockComponent } from 'ng-mocks'; import { VorgangForwardZustellenContainerComponent } from './vorgang-forward-zustellen-container.component'; describe('VorgangForwardZustellenContainerComponent', () => { - let component: VorgangForwardZustellenContainerComponent; - let fixture: ComponentFixture<VorgangForwardZustellenContainerComponent>; + let component: VorgangForwardZustellenContainerComponent; + let fixture: ComponentFixture<VorgangForwardZustellenContainerComponent>; - const forwarding: ForwardingResource = createForwardingResource(); + const forwarding: ForwardingResource = createForwardingResource(); - const markAsSuccess: string = '[data-test-id="mark-as-success-button"]'; - const markAsFail: string = '[data-test-id="mark-as-fail-button"]'; + const markAsSuccess: string = '[data-test-id="mark-as-success-button"]'; + const markAsFail: string = '[data-test-id="mark-as-fail-button"]'; - const failedMessage: string = '[data-test-id="failed-message"]'; - const successfullMessage: string = '[data-test-id="successfull-message"]'; + const failedMessage: string = '[data-test-id="failed-message"]'; + const successfullMessage: string = '[data-test-id="successfull-message"]'; - const forwardingService = mock(ForwardingService); + const forwardingService = mock(ForwardingService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HasLinkPipe, - VorgangForwardZustellenContainerComponent, - MatIcon, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent) - ], - providers: [ - { - provide: ForwardingService, - useValue: forwardingService - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HasLinkPipe, + VorgangForwardZustellenContainerComponent, + MatIcon, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + ], + providers: [ + { + provide: ForwardingService, + useValue: forwardingService, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangForwardZustellenContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangForwardZustellenContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should call service mark as success', () => { - component.forwarding = forwarding; - fixture.detectChanges(); + it('should call service mark as success', () => { + component.forwarding = forwarding; + fixture.detectChanges(); - component.markAsSuccess(); + component.markAsSuccess(); - expect(forwardingService.markAsSuccess).toHaveBeenCalledWith(forwarding); - }) + expect(forwardingService.markAsSuccess).toHaveBeenCalledWith(forwarding); + }); - it('should call service mark as fail', () => { - component.forwarding = forwarding; - fixture.detectChanges(); + it('should call service mark as fail', () => { + component.forwarding = forwarding; + fixture.detectChanges(); - component.markAsFail(); + component.markAsFail(); - expect(forwardingService.markAsFail).toHaveBeenCalledWith(forwarding); - }) + expect(forwardingService.markAsFail).toHaveBeenCalledWith(forwarding); + }); - describe('mark as success button', () => { + describe('mark as success button', () => { + it('should be visible', () => { + component.forwarding = createForwardingResource([ForwardingLinkRel.MARK_AS_SUCCESS]); - it('should be visible', () => { - component.forwarding = createForwardingResource([ForwardingLinkRel.MARK_AS_SUCCESS]); + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(markAsSuccess); - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(markAsSuccess); + expect(button).toBeInstanceOf(HTMLElement); + }); - expect(button).toBeInstanceOf(HTMLElement); - }) + it('should be hidden', () => { + component.forwarding = forwarding; - it('should be hidden', () => { - component.forwarding = forwarding; + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(markAsSuccess); - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(markAsSuccess); + expect(button).not.toBeInstanceOf(HTMLElement); + }); + }); - expect(button).not.toBeInstanceOf(HTMLElement); - }) - }) + describe('mark as fail button', () => { + it('should be visible', () => { + component.forwarding = createForwardingResource([ForwardingLinkRel.MARK_AS_FAIL]); - describe('mark as fail button', () => { + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(markAsFail); - it('should be visible', () => { - component.forwarding = createForwardingResource([ForwardingLinkRel.MARK_AS_FAIL]); + expect(button).toBeInstanceOf(HTMLElement); + }); - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(markAsFail); + it('should be hidden', () => { + component.forwarding = forwarding; - expect(button).toBeInstanceOf(HTMLElement); - }) + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(markAsFail); - it('should be hidden', () => { - component.forwarding = forwarding; + expect(button).not.toBeInstanceOf(HTMLElement); + }); + }); - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(markAsFail); + describe('failed message', () => { + it('should be visible', () => { + component.forwarding = createForwardingResource([ForwardingLinkRel.FAILED]); - expect(button).not.toBeInstanceOf(HTMLElement); - }) - }) + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(failedMessage); - describe('failed message', () => { + expect(button).toBeInstanceOf(HTMLElement); + }); - it('should be visible', () => { - component.forwarding = createForwardingResource([ForwardingLinkRel.FAILED]); + it('should be hidden', () => { + component.forwarding = forwarding; - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(failedMessage); + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(failedMessage); - expect(button).toBeInstanceOf(HTMLElement); - }) + expect(button).not.toBeInstanceOf(HTMLElement); + }); + }); - it('should be hidden', () => { - component.forwarding = forwarding; + describe('successfull message', () => { + it('should be visible', () => { + component.forwarding = createForwardingResource([ForwardingLinkRel.SUCCESSFUL]); - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(failedMessage); + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(successfullMessage); - expect(button).not.toBeInstanceOf(HTMLElement); - }) - }) + expect(button).toBeInstanceOf(HTMLElement); + }); - describe('successfull message', () => { + it('should be hidden', () => { + component.forwarding = forwarding; - it('should be visible', () => { - component.forwarding = createForwardingResource([ForwardingLinkRel.SUCCESSFUL]); + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(successfullMessage); - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(successfullMessage); - - expect(button).toBeInstanceOf(HTMLElement); - }) - - it('should be hidden', () => { - component.forwarding = forwarding; - - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(successfullMessage); - - expect(button).not.toBeInstanceOf(HTMLElement); - }) - }) + expect(button).not.toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.ts b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.ts index 9f8057c4880139e8f97b2e3a7afd434dba138204..eac0685b7dd0defd8addee9f751ca96a182fa046 100644 --- a/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.ts +++ b/alfa-client/libs/forwarding/src/lib/vorgang-forwarding-zustellen-container/vorgang-forward-zustellen-container.component.ts @@ -23,31 +23,38 @@ */ import { Component, Input } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; -import { ForwardingLinkRel, ForwardingResource, ForwardingService } from '@alfa-client/forwarding-shared'; +import { + ForwardingLinkRel, + ForwardingResource, + ForwardingService, +} from '@alfa-client/forwarding-shared'; import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-forward-zustellen-container', - templateUrl: './vorgang-forward-zustellen-container.component.html', - styleUrls: ['./vorgang-forward-zustellen-container.component.scss'] + selector: 'alfa-vorgang-forward-zustellen-container', + templateUrl: './vorgang-forward-zustellen-container.component.html', + styleUrls: ['./vorgang-forward-zustellen-container.component.scss'], }) export class VorgangForwardZustellenContainerComponent { + @Input() forwarding: ForwardingResource; - @Input() forwarding: ForwardingResource; + public markAsSuccessCommandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); + public markAsFailCommandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - public markAsSuccessCommandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); - public markAsFailCommandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = ForwardingLinkRel; - readonly linkRel = ForwardingLinkRel; + constructor(private forwardingService: ForwardingService) {} - constructor(private forwardingService: ForwardingService) { } + markAsSuccess(): void { + this.markAsSuccessCommandStateResource$ = this.forwardingService.markAsSuccess(this.forwarding); + } - markAsSuccess(): void { - this.markAsSuccessCommandStateResource$ = this.forwardingService.markAsSuccess(this.forwarding); - } - - markAsFail(): void { - this.markAsFailCommandStateResource$ = this.forwardingService.markAsFail(this.forwarding); - } -} \ No newline at end of file + markAsFail(): void { + this.markAsFailCommandStateResource$ = this.forwardingService.markAsFail(this.forwarding); + } +} diff --git a/alfa-client/libs/forwarding/src/test-setup.ts b/alfa-client/libs/forwarding/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/forwarding/src/test-setup.ts +++ b/alfa-client/libs/forwarding/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/forwarding/tsconfig.json b/alfa-client/libs/forwarding/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/forwarding/tsconfig.json +++ b/alfa-client/libs/forwarding/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/forwarding/tsconfig.lib.json b/alfa-client/libs/forwarding/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/forwarding/tsconfig.lib.json +++ b/alfa-client/libs/forwarding/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/forwarding/tsconfig.spec.json b/alfa-client/libs/forwarding/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/forwarding/tsconfig.spec.json +++ b/alfa-client/libs/forwarding/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/hint-shared/.eslintrc.json b/alfa-client/libs/hint-shared/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/hint-shared/.eslintrc.json +++ b/alfa-client/libs/hint-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/hint-shared/jest.config.ts b/alfa-client/libs/hint-shared/jest.config.ts index 5b70d99b604b0cd43c91c02e79f8fa383e5a2f4a..73a174ad458aec1b6c11676f247d7e1ad084a54a 100644 --- a/alfa-client/libs/hint-shared/jest.config.ts +++ b/alfa-client/libs/hint-shared/jest.config.ts @@ -1,22 +1,22 @@ export default { - displayName: 'hint-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/hint-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'hint-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/hint-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/hint-shared/project.json b/alfa-client/libs/hint-shared/project.json index 76b5d2868421bb6c6828ba43d0975bc379eca119..21dcc992fa47724f149532dc5ace95f7d2309d13 100644 --- a/alfa-client/libs/hint-shared/project.json +++ b/alfa-client/libs/hint-shared/project.json @@ -1,28 +1,25 @@ { - "name": "hint-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/hint-shared/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/hint-shared"], - "options": { - "tsConfig": "libs/hint-shared/tsconfig.spec.json", - "jestConfig": "libs/hint-shared/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/hint-shared/**/*.ts", - "libs/hint-shared/**/*.html" - ] - } - } - }, - "tags": [] + "name": "hint-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/hint-shared/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/hint-shared"], + "options": { + "tsConfig": "libs/hint-shared/tsconfig.spec.json", + "jestConfig": "libs/hint-shared/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/hint-shared/**/*.ts", "libs/hint-shared/**/*.html"] + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.actions.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.actions.ts index 5222671c69e3407c3a0c19d56ccc15d3506c3878..07c6d2d7ed502c28f53f2c4a279494cbb3dc5044 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.actions.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.actions.ts @@ -3,8 +3,14 @@ import { createAction, props } from '@ngrx/store'; import { HintListResource } from '../hint.model'; export interface HintListProps { - hintList: HintListResource + hintList: HintListResource; } -export const loadHintListSuccess: TypedActionCreatorWithProps<HintListProps> = createAction('[Hint] Load All Success', props<HintListProps>()); -export const loadHintListFailed: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Hint] Load All Failed', props<ApiErrorAction>()); \ No newline at end of file +export const loadHintListSuccess: TypedActionCreatorWithProps<HintListProps> = createAction( + '[Hint] Load All Success', + props<HintListProps>(), +); +export const loadHintListFailed: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[Hint] Load All Failed', + props<ApiErrorAction>(), +); diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.effects.spec.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.effects.spec.ts index b50746b243dd40ed361e158bf6d596c702c2a21d..7c6e30991a275d2a4d82f1265ba5b155ed3b9429 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.effects.spec.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.effects.spec.ts @@ -18,74 +18,72 @@ import * as ApiRootActions from '../../../../api-root-shared/src/lib/+state/api- import * as HintActions from './hint.actions'; describe('HintEffects', () => { - let actions: Observable<Action>; - let effects: HintEffects; + let actions: Observable<Action>; + let effects: HintEffects; - const repository = mock(HintRepository); + const repository = mock(HintRepository); - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - HintEffects, - provideMockActions(() => actions), - provideMockStore(), - { - provide: HintRepository, - useValue: repository - } - ] - }); + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + HintEffects, + provideMockActions(() => actions), + provideMockStore(), + { + provide: HintRepository, + useValue: repository, + }, + ], + }); - effects = TestBed.inject(HintEffects); - }); + effects = TestBed.inject(HintEffects); + }); - describe('loadAll', () => { + describe('loadAll', () => { + const apiRoot: ApiRootResource = createApiRootResource([ApiRootLinkRel.HINTS]); + const action = ApiRootActions.loadApiRootSuccess({ apiRoot }); - const apiRoot: ApiRootResource = createApiRootResource([ApiRootLinkRel.HINTS]); - const action = ApiRootActions.loadApiRootSuccess({ apiRoot }); + it('should call repository', () => { + actions = of(action); - it('should call repository', () => { - actions = of(action); + effects.loadAll$.subscribe(); - effects.loadAll$.subscribe(); + expect(repository.loadAll).toHaveBeenCalledWith(apiRoot); + }); - expect(repository.loadAll).toHaveBeenCalledWith(apiRoot); - }) + it('should dispatch loadHintListSuccess action', () => { + const hintList: HintListResource = createHintListResource(); + repository.loadAll.mockReturnValue(of(hintList)); - it('should dispatch loadHintListSuccess action', () => { - const hintList: HintListResource = createHintListResource(); - repository.loadAll.mockReturnValue(of(hintList)); + actions = hot('-a-|', { a: action }); - actions = hot('-a-|', { a: action }); + const expected = hot('-a-|', { a: HintActions.loadHintListSuccess({ hintList }) }); + expect(effects.loadAll$).toBeObservable(expected); + }); - const expected = hot('-a-|', { a: HintActions.loadHintListSuccess({ hintList }) }); - expect(effects.loadAll$).toBeObservable(expected); - }) + it('should dispatch loadHintListFailed action', () => { + const apiError: ApiError = createApiError(); + const error = { error: { error: apiError } }; + const errorResponse = cold('-#', {}, error); + repository.loadAll = jest.fn(() => errorResponse); - it('should dispatch loadHintListFailed action', () => { - const apiError: ApiError = createApiError() - const error = { error: { error: apiError } }; - const errorResponse = cold('-#', {}, error); - repository.loadAll = jest.fn(() => errorResponse); + const expected = cold('--b', { b: HintActions.loadHintListFailed({ apiError }) }); + actions = hot('-a', { a: action }); - const expected = cold('--b', { b: HintActions.loadHintListFailed({ apiError }) }); - actions = hot('-a', { a: action }); + expect(effects.loadAll$).toBeObservable(expected); + }); + }); - expect(effects.loadAll$).toBeObservable(expected); - }) - }) + describe('loadAll without link', () => { + const apiRoot: ApiRootResource = createApiRootResource(); + const action = ApiRootActions.loadApiRootSuccess({ apiRoot }); - describe('loadAll without link', () => { + it('should not call repository', () => { + actions = of(action); - const apiRoot: ApiRootResource = createApiRootResource(); - const action = ApiRootActions.loadApiRootSuccess({ apiRoot }); + effects.loadAll$.subscribe(); - it('should not call repository', () => { - actions = of(action); - - effects.loadAll$.subscribe(); - - expect(repository.loadAll).not.toHaveBeenCalledWith(apiRoot); - }) - }) -}) \ No newline at end of file + expect(repository.loadAll).not.toHaveBeenCalledWith(apiRoot); + }); + }); +}); diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.effects.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.effects.ts index ba4de63a428bec62a2415bd99a1201429bcb7e82..4af5275a15292a15556e20e46faf8f54a0389939 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.effects.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.effects.ts @@ -11,14 +11,27 @@ import * as HintActions from '../../../../hint-shared/src/lib/+state/hint.action @Injectable() export class HintEffects { + constructor( + private readonly actions$: Actions, + private repository: HintRepository, + ) {} - constructor(private readonly actions$: Actions, private repository: HintRepository) { } - - loadAll$ = createEffect(() => this.actions$.pipe(ofType(ApiRootActions.loadApiRootSuccess), - filter((props: ApiRootProps) => hasLink(props.apiRoot, ApiRootLinkRel.HINTS)), - switchMap((props: ApiRootProps) => this.repository.loadAll(props.apiRoot).pipe( - map(hintList => HintActions.loadHintListSuccess({ hintList })), - catchError(apiError => of(HintActions.loadHintListFailed({ apiError: getApiErrorFromHttpErrorResponse(apiError) }))) - ))) - ) -} \ No newline at end of file + loadAll$ = createEffect(() => + this.actions$.pipe( + ofType(ApiRootActions.loadApiRootSuccess), + filter((props: ApiRootProps) => hasLink(props.apiRoot, ApiRootLinkRel.HINTS)), + switchMap((props: ApiRootProps) => + this.repository.loadAll(props.apiRoot).pipe( + map((hintList) => HintActions.loadHintListSuccess({ hintList })), + catchError((apiError) => + of( + HintActions.loadHintListFailed({ + apiError: getApiErrorFromHttpErrorResponse(apiError), + }), + ), + ), + ), + ), + ), + ); +} diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.facade.spec.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.facade.spec.ts index bd9a3fdadee73e0f2eba00a3a61e1932131d1235..0543b4c7dd91612efa67c1d466a0237edc614e74 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.facade.spec.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.facade.spec.ts @@ -6,31 +6,29 @@ import { HintFacade } from './hint.facade'; import * as HintSelectors from './hint.selectors'; describe('HintFacade', () => { + let facade: HintFacade; + let store: Mock<Store>; - let facade: HintFacade; - let store: Mock<Store>; + let selectionSubject: Subject<any>; - let selectionSubject: Subject<any>;; + beforeEach(() => { + store = mock(Store); - beforeEach(() => { - store = mock(Store); + store.select.mockReturnValue(selectionSubject); + store.dispatch = jest.fn(); - store.select.mockReturnValue(selectionSubject); - store.dispatch = jest.fn(); + facade = new HintFacade(useFromMock(<any>store)); + }); - facade = new HintFacade(useFromMock(<any>store)); - }) + it('is initialized', () => { + expect(facade).toBeTruthy(); + }); - it('is initialized', () => { - expect(facade).toBeTruthy(); - }) + describe('hasUserNoOrganisationsEinheitIdHint', () => { + it('should select from store', () => { + facade.hasUserNoOrganisationsEinheitIdHint(); - describe('hasUserNoOrganisationsEinheitIdHint', () => { - - it('should select from store', () => { - facade.hasUserNoOrganisationsEinheitIdHint(); - - expect(store.select).toHaveBeenCalledWith(HintSelectors.hasUserNoOrganisationsEinheitIdHint); - }) - }) -}) \ No newline at end of file + expect(store.select).toHaveBeenCalledWith(HintSelectors.hasUserNoOrganisationsEinheitIdHint); + }); + }); +}); diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.facade.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.facade.ts index 34867ba17b0f51525a4bc13933eef31b0603661e..6d50c753827c8b952fe965d445166f21c5795c6a 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.facade.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.facade.ts @@ -6,11 +6,9 @@ import * as HintSelectors from './hint.selectors'; @Injectable() export class HintFacade { + constructor(private store: Store) {} - constructor(private store: Store) { } - - public hasUserNoOrganisationsEinheitIdHint(): Observable<boolean> { - return this.store.select(HintSelectors.hasUserNoOrganisationsEinheitIdHint); - } + public hasUserNoOrganisationsEinheitIdHint(): Observable<boolean> { + return this.store.select(HintSelectors.hasUserNoOrganisationsEinheitIdHint); + } } - diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.reducer.spec.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.reducer.spec.ts index 0fb7f2f41a77b2aa39f93ad51aed8e2ee1c58d08..7d47190c231a10dcdacfc8b6c405fe52402e9c51 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.reducer.spec.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.reducer.spec.ts @@ -9,39 +9,35 @@ import { HintState, initialState, reducer } from './hint.reducer'; import * as HintActions from './hint.actions'; describe('HintReducer', () => { + describe('unknown action', () => { + it('should return current state', () => { + const action = {} as Action; - describe('unknown action', () => { + const result = reducer(initialState, action); - it('should return current state', () => { - const action = {} as Action; + expect(result).toBe(initialState); + }); + }); - const result = reducer(initialState, action); + describe('on loadHintListSuccess action', () => { + it('should set loaded resource into state', () => { + const hintList: HintListResource = createHintListResource(); + const action = HintActions.loadHintListSuccess(<HintListProps>{ hintList }); - expect(result).toBe(initialState); - }) - }) + const result: HintState = reducer(initialState, action); - describe('on loadHintListSuccess action', () => { + expect(result.hintList).toEqual(createStateResource(hintList)); + }); + }); - it('should set loaded resource into state', () => { - const hintList: HintListResource = createHintListResource(); - const action = HintActions.loadHintListSuccess(<HintListProps>{ hintList }); + describe('on loadHintListFailed action', () => { + it('should set error into state', () => { + const apiError: ApiError = createApiError(); + const action = HintActions.loadHintListFailed(<ApiErrorAction>{ apiError }); - const result: HintState = reducer(initialState, action); + const result: HintState = reducer(initialState, action); - expect(result.hintList).toEqual(createStateResource(hintList)); - }) - }) - - describe('on loadHintListFailed action', () => { - - it('should set error into state', () => { - const apiError: ApiError = createApiError(); - const action = HintActions.loadHintListFailed(<ApiErrorAction>{ apiError }); - - const result: HintState = reducer(initialState, action); - - expect(result.hintList.error).toBe(apiError); - }) - }) -}) \ No newline at end of file + expect(result.hintList.error).toBe(apiError); + }); + }); +}); diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.reducer.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.reducer.ts index a6386ec46042406805c651842f2ab38f66d42e7e..905f5ab2ebcf819be5a1926530d0b90144259b31 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.reducer.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.reducer.ts @@ -1,4 +1,10 @@ -import { ApiErrorAction, StateResource, createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + ApiErrorAction, + StateResource, + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Action, createReducer, on } from '@ngrx/store'; import { HintListResource } from '../hint.model'; import { HintListProps } from './hint.actions'; @@ -8,29 +14,29 @@ import * as HintActions from './hint.actions'; export const HINT_FEATURE_KEY = 'HintState'; export interface HintState { - hintList: StateResource<HintListResource>; + hintList: StateResource<HintListResource>; } export interface HintPartialState { - readonly [HINT_FEATURE_KEY]: HintState; + readonly [HINT_FEATURE_KEY]: HintState; } export const initialState: HintState = { - hintList: createEmptyStateResource<HintListResource>() -} + hintList: createEmptyStateResource<HintListResource>(), +}; const hintReducer = createReducer( - initialState, - on(HintActions.loadHintListSuccess, (state: HintState, props: HintListProps) => ({ - ...state, - hintList: createStateResource(props.hintList) - })), - on(HintActions.loadHintListFailed, (state: HintState, props: ApiErrorAction) => ({ - ...state, - hintList: createErrorStateResource(props.apiError) - })) -) + initialState, + on(HintActions.loadHintListSuccess, (state: HintState, props: HintListProps) => ({ + ...state, + hintList: createStateResource(props.hintList), + })), + on(HintActions.loadHintListFailed, (state: HintState, props: ApiErrorAction) => ({ + ...state, + hintList: createErrorStateResource(props.apiError), + })), +); export function reducer(state: HintState, action: Action) { - return hintReducer(state, action); -} \ No newline at end of file + return hintReducer(state, action); +} diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.repository.spec.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.repository.spec.ts index 6641402072b29150a169d5cedfc6490f77eae81d..78a72704702ed68d1d6152d4566efc49c0e48375 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.repository.spec.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.repository.spec.ts @@ -8,42 +8,41 @@ import { HintListResource } from '../hint.model'; import { HintRepository } from './hint.repository'; describe('HintRepository', () => { + let service: HintRepository; + let resourceFactory = mock(ResourceFactory); + let resourceWrapper = { get: jest.fn() }; - let service: HintRepository; - let resourceFactory = mock(ResourceFactory); - let resourceWrapper = { get: jest.fn() }; + beforeEach(() => { + service = new HintRepository(useFromMock(resourceFactory)); - beforeEach(() => { - service = new HintRepository(useFromMock(resourceFactory)); + resourceFactory.from.mockReturnValue(resourceWrapper); + }); - resourceFactory.from.mockReturnValue(resourceWrapper); - }) + describe('loadAll', () => { + const hintListResource: HintListResource = createHintListResource(); + const apiRoot: ApiRootResource = createApiRootResource(); - describe('loadAll', () => { - const hintListResource: HintListResource = createHintListResource(); - const apiRoot: ApiRootResource = createApiRootResource(); + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: hintListResource })); + }); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: hintListResource })); - }) + it('should call resourceFactory with given resource', () => { + service.loadAll(apiRoot); - it('should call resourceFactory with given resource', () => { - service.loadAll(apiRoot); + expect(resourceFactory.from).toHaveBeenCalledWith(apiRoot); + }); - expect(resourceFactory.from).toHaveBeenCalledWith(apiRoot); - }) + it('should call resourceWrapper with link', () => { + service.loadAll(apiRoot); - it('should call resourceWrapper with link', () => { - service.loadAll(apiRoot); + expect(resourceWrapper.get).toHaveBeenCalledWith(ApiRootLinkRel.HINTS); + }); - expect(resourceWrapper.get).toHaveBeenCalledWith(ApiRootLinkRel.HINTS); - }) + it('should return result', () => { + const result = service.loadAll(apiRoot); - it('should return result', () => { - const result = service.loadAll(apiRoot); - - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: hintListResource })); - }) - }) -}) \ No newline at end of file + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: hintListResource })); + }); + }); +}); diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.repository.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.repository.ts index 98a54995cd6453a4bc1e656f433d643dae2d8c20..702c34d0711ee787b7d092e56eea8fd46d8de49f 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.repository.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.repository.ts @@ -6,10 +6,9 @@ import { HintListResource } from '../hint.model'; @Injectable() export class HintRepository { + constructor(private resourceFactory: ResourceFactory) {} - constructor(private resourceFactory: ResourceFactory) { } - - public loadAll(apiRoot: ApiRootResource): Observable<HintListResource> { - return this.resourceFactory.from(apiRoot).get(ApiRootLinkRel.HINTS); - } -} \ No newline at end of file + public loadAll(apiRoot: ApiRootResource): Observable<HintListResource> { + return this.resourceFactory.from(apiRoot).get(ApiRootLinkRel.HINTS); + } +} diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.selectors.spec.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.selectors.spec.ts index b4c7283286908cdafe00d05cd94b96b781a7e74f..089d388d83aa3ba8fba808650bac4f05e5c7e08e 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.selectors.spec.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.selectors.spec.ts @@ -8,44 +8,52 @@ import * as HintUtil from '../hint.util'; import * as HintSelectors from './hint.selectors'; describe('Hint Selectors', () => { - - let state: HintPartialState; - - const hintList: StateResource<HintListResource> = createStateResource(createHintListResource()); - - beforeEach(() => { - state = { - HintState: { - ...initialState, - hintList - } - } - }) - - describe('hasNoOrganisationsEinheitId', () => { - - const getHasUserNoOrganisationsEinheitIdSpy: jest.SpyInstance<boolean, [hintList: HintListResource]> = jest.spyOn(HintUtil, 'hasUserNoOrganisationsEinheitIdHint'); - - it('should return stateResource with hint if exist', () => { - getHasUserNoOrganisationsEinheitIdSpy.mockReturnValue(true); - - const result: boolean = HintSelectors.hasUserNoOrganisationsEinheitIdHint.projector(state.HintState); - - expect(result).toBeTruthy(); - }) - - it('should return emptyStateResource if not exist', () => { - getHasUserNoOrganisationsEinheitIdSpy.mockReturnValue(false); - - const result: boolean = HintSelectors.hasUserNoOrganisationsEinheitIdHint.projector(state.HintState); - - expect(result).toBeFalsy(); - }) - - it('should return emptyStateResource if resource is null', () => { - const result: boolean = HintSelectors.hasUserNoOrganisationsEinheitIdHint.projector({ ...state.HintState, hintList: createEmptyListResource() }); - - expect(result).toBeFalsy(); - }) - }) -}) \ No newline at end of file + let state: HintPartialState; + + const hintList: StateResource<HintListResource> = createStateResource(createHintListResource()); + + beforeEach(() => { + state = { + HintState: { + ...initialState, + hintList, + }, + }; + }); + + describe('hasNoOrganisationsEinheitId', () => { + const getHasUserNoOrganisationsEinheitIdSpy: jest.SpyInstance< + boolean, + [hintList: HintListResource] + > = jest.spyOn(HintUtil, 'hasUserNoOrganisationsEinheitIdHint'); + + it('should return stateResource with hint if exist', () => { + getHasUserNoOrganisationsEinheitIdSpy.mockReturnValue(true); + + const result: boolean = HintSelectors.hasUserNoOrganisationsEinheitIdHint.projector( + state.HintState, + ); + + expect(result).toBeTruthy(); + }); + + it('should return emptyStateResource if not exist', () => { + getHasUserNoOrganisationsEinheitIdSpy.mockReturnValue(false); + + const result: boolean = HintSelectors.hasUserNoOrganisationsEinheitIdHint.projector( + state.HintState, + ); + + expect(result).toBeFalsy(); + }); + + it('should return emptyStateResource if resource is null', () => { + const result: boolean = HintSelectors.hasUserNoOrganisationsEinheitIdHint.projector({ + ...state.HintState, + hintList: createEmptyListResource(), + }); + + expect(result).toBeFalsy(); + }); + }); +}); diff --git a/alfa-client/libs/hint-shared/src/lib/+state/hint.selectors.ts b/alfa-client/libs/hint-shared/src/lib/+state/hint.selectors.ts index 16665c443bd83e5a43fc051f10692d6a00a2650a..62b16de0f5b4cd4501874daf9bbb864fb6e22717 100644 --- a/alfa-client/libs/hint-shared/src/lib/+state/hint.selectors.ts +++ b/alfa-client/libs/hint-shared/src/lib/+state/hint.selectors.ts @@ -4,11 +4,13 @@ import { HINT_FEATURE_KEY, HintState } from './hint.reducer'; import * as HintUtil from '../hint.util'; -export const getHintState: MemoizedSelector<object, HintState> = createFeatureSelector<HintState>(HINT_FEATURE_KEY); +export const getHintState: MemoizedSelector<object, HintState> = + createFeatureSelector<HintState>(HINT_FEATURE_KEY); -export const hasUserNoOrganisationsEinheitIdHint: MemoizedSelector<HintState, boolean> = createSelector(getHintState, (state: HintState) => { - if (isNull(state.hintList.resource)) { - return false; - } - return HintUtil.hasUserNoOrganisationsEinheitIdHint(state.hintList.resource); -}); \ No newline at end of file +export const hasUserNoOrganisationsEinheitIdHint: MemoizedSelector<HintState, boolean> = + createSelector(getHintState, (state: HintState) => { + if (isNull(state.hintList.resource)) { + return false; + } + return HintUtil.hasUserNoOrganisationsEinheitIdHint(state.hintList.resource); + }); diff --git a/alfa-client/libs/hint-shared/src/lib/hint-shared.module.spec.ts b/alfa-client/libs/hint-shared/src/lib/hint-shared.module.spec.ts index 835d6595bbfb909f925a44ed41ee6606dba268dc..755233abb31c5e1aa0a7781aecdd25f3c6a28fa7 100644 --- a/alfa-client/libs/hint-shared/src/lib/hint-shared.module.spec.ts +++ b/alfa-client/libs/hint-shared/src/lib/hint-shared.module.spec.ts @@ -2,13 +2,13 @@ import { TestBed } from '@angular/core/testing'; import { HintSharedModule } from './hint-shared.module'; describe('HintSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [HintSharedModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HintSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(HintSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(HintSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/hint-shared/src/lib/hint-shared.module.ts b/alfa-client/libs/hint-shared/src/lib/hint-shared.module.ts index c9d8e1ae861981143886ffdf7dea768dcf69b72b..3da6cc00e9d8030b0e94115b7b48551abf7f5cd5 100644 --- a/alfa-client/libs/hint-shared/src/lib/hint-shared.module.ts +++ b/alfa-client/libs/hint-shared/src/lib/hint-shared.module.ts @@ -11,13 +11,13 @@ import { HintRepository } from './+state/hint.repository'; import { HintService } from './hint.service'; @NgModule({ - imports: [ - CommonModule, - StoreModule.forFeature(HINT_FEATURE_KEY, reducer), - EffectsModule.forFeature([HintEffects]), - TechSharedModule, - ApiRootModule - ], - providers: [HintService, HintFacade, HintRepository] + imports: [ + CommonModule, + StoreModule.forFeature(HINT_FEATURE_KEY, reducer), + EffectsModule.forFeature([HintEffects]), + TechSharedModule, + ApiRootModule, + ], + providers: [HintService, HintFacade, HintRepository], }) -export class HintSharedModule { } +export class HintSharedModule {} diff --git a/alfa-client/libs/hint-shared/src/lib/hint.linkrel.ts b/alfa-client/libs/hint-shared/src/lib/hint.linkrel.ts index 7e12656f4cce2b5e1a645677b782dd5d05275bec..a86a24e7214840b40a3c046753aa9ccf5f153cff 100644 --- a/alfa-client/libs/hint-shared/src/lib/hint.linkrel.ts +++ b/alfa-client/libs/hint-shared/src/lib/hint.linkrel.ts @@ -1,3 +1,3 @@ export enum HintListLinkRel { - HINT_LIST = 'hintList' -} \ No newline at end of file + HINT_LIST = 'hintList', +} diff --git a/alfa-client/libs/hint-shared/src/lib/hint.message.ts b/alfa-client/libs/hint-shared/src/lib/hint.message.ts index 7c459b7173c3bd23f2963d62d2299f74f731c135..ef11457135e01d70b04d485756c626378a972f14 100644 --- a/alfa-client/libs/hint-shared/src/lib/hint.message.ts +++ b/alfa-client/libs/hint-shared/src/lib/hint.message.ts @@ -1,3 +1,3 @@ export enum HintMessageCode { - USER_NO_ORGANISATIONS_EINHEIT_ID = 'user.no.organisationsEinheitId' -} \ No newline at end of file + USER_NO_ORGANISATIONS_EINHEIT_ID = 'user.no.organisationsEinheitId', +} diff --git a/alfa-client/libs/hint-shared/src/lib/hint.model.ts b/alfa-client/libs/hint-shared/src/lib/hint.model.ts index e039779d7e3fcaba0a5816db72ede7983967e27b..1ff5cf0948343d95da2ff1f1acdf3fe4724a7860 100644 --- a/alfa-client/libs/hint-shared/src/lib/hint.model.ts +++ b/alfa-client/libs/hint-shared/src/lib/hint.model.ts @@ -2,8 +2,8 @@ import { ListResource } from '@alfa-client/tech-shared'; import { Resource } from '@ngxp/rest'; export interface Hint { - code: string; + code: string; } -export interface HintResource extends Resource, Hint { } -export interface HintListResource extends ListResource { } \ No newline at end of file +export interface HintResource extends Resource, Hint {} +export interface HintListResource extends ListResource {} diff --git a/alfa-client/libs/hint-shared/src/lib/hint.service.spec.ts b/alfa-client/libs/hint-shared/src/lib/hint.service.spec.ts index 05a8470830d9eb1e09f4b0eb637b23ddcbad804f..bcb055743bb34ae998916ca96efc4c5496007552 100644 --- a/alfa-client/libs/hint-shared/src/lib/hint.service.spec.ts +++ b/alfa-client/libs/hint-shared/src/lib/hint.service.spec.ts @@ -3,23 +3,21 @@ import { HintFacade } from './+state/hint.facade'; import { HintService } from './hint.service'; describe('HintService', () => { + let service: HintService; - let service: HintService; + let facade: Mock<HintFacade>; - let facade: Mock<HintFacade>; + beforeEach(() => { + facade = mock(HintFacade); - beforeEach(() => { - facade = mock(HintFacade); + service = new HintService(useFromMock(facade)); + }); - service = new HintService(useFromMock(facade)); - }) + describe('hasUserNoOrganisationsEinheitIdHint', () => { + it('should call facade', () => { + service.hasUserNoOrganisationsEinheitIdHint(); - describe('hasUserNoOrganisationsEinheitIdHint', () => { - - it('should call facade', () => { - service.hasUserNoOrganisationsEinheitIdHint(); - - expect(facade.hasUserNoOrganisationsEinheitIdHint).toHaveBeenCalled(); - }) - }) -}) \ No newline at end of file + expect(facade.hasUserNoOrganisationsEinheitIdHint).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/hint-shared/src/lib/hint.service.ts b/alfa-client/libs/hint-shared/src/lib/hint.service.ts index 06bb0883f3bca1ccac85b9215c5691acf41da223..133ebd02019194f9583ca64a6f43f178ae8b9954 100644 --- a/alfa-client/libs/hint-shared/src/lib/hint.service.ts +++ b/alfa-client/libs/hint-shared/src/lib/hint.service.ts @@ -4,10 +4,9 @@ import { HintFacade } from './+state/hint.facade'; @Injectable() export class HintService { + constructor(private facade: HintFacade) {} - constructor(private facade: HintFacade) { } - - public hasUserNoOrganisationsEinheitIdHint(): Observable<boolean> { - return this.facade.hasUserNoOrganisationsEinheitIdHint(); - } -} \ No newline at end of file + public hasUserNoOrganisationsEinheitIdHint(): Observable<boolean> { + return this.facade.hasUserNoOrganisationsEinheitIdHint(); + } +} diff --git a/alfa-client/libs/hint-shared/src/lib/hint.util.spec.ts b/alfa-client/libs/hint-shared/src/lib/hint.util.spec.ts index 61eeab4e545d665bf569ba3a5a411bab7ab8a2ee..5dc0eada752a102f1264f85cd15f03ed7c1be174 100644 --- a/alfa-client/libs/hint-shared/src/lib/hint.util.spec.ts +++ b/alfa-client/libs/hint-shared/src/lib/hint.util.spec.ts @@ -1,33 +1,45 @@ -import { createHintListResource, createHintListResourceWithResource, createHintResource } from 'libs/hint-shared/test/hint'; +import { + createHintListResource, + createHintListResourceWithResource, + createHintResource, +} from 'libs/hint-shared/test/hint'; import { HintMessageCode } from './hint.message'; import { HintResource } from './hint.model'; -import { hasUserNoOrganisationsEinheitIdHint, isUserHasNoOrganisationsEinheitIdHint } from './hint.util'; +import { + hasUserNoOrganisationsEinheitIdHint, + isUserHasNoOrganisationsEinheitIdHint, +} from './hint.util'; describe('Hint Util', () => { - - describe('isUserHasNoOrganisationsEinheitIdHint', () => { - - it('should return true if code match', () => { - const result: boolean = isUserHasNoOrganisationsEinheitIdHint({ ...createHintResource(), code: HintMessageCode.USER_NO_ORGANISATIONS_EINHEIT_ID }); - - expect(result).toBeTruthy(); - }) - }) - - describe('hasUserNoOrganisationsEinheitIdHint', () => { - - it('should return resource if code match', () => { - const hint: HintResource = { ...createHintResource(), code: HintMessageCode.USER_NO_ORGANISATIONS_EINHEIT_ID }; - - const hasUser: boolean = hasUserNoOrganisationsEinheitIdHint(createHintListResourceWithResource([hint])); - - expect(hasUser).toBeTruthy(); - }) - - it('should return false if code NOT match', () => { - const hasUser: boolean = hasUserNoOrganisationsEinheitIdHint(createHintListResource()); - - expect(hasUser).toBeFalsy(); - }) - }) -}) \ No newline at end of file + describe('isUserHasNoOrganisationsEinheitIdHint', () => { + it('should return true if code match', () => { + const result: boolean = isUserHasNoOrganisationsEinheitIdHint({ + ...createHintResource(), + code: HintMessageCode.USER_NO_ORGANISATIONS_EINHEIT_ID, + }); + + expect(result).toBeTruthy(); + }); + }); + + describe('hasUserNoOrganisationsEinheitIdHint', () => { + it('should return resource if code match', () => { + const hint: HintResource = { + ...createHintResource(), + code: HintMessageCode.USER_NO_ORGANISATIONS_EINHEIT_ID, + }; + + const hasUser: boolean = hasUserNoOrganisationsEinheitIdHint( + createHintListResourceWithResource([hint]), + ); + + expect(hasUser).toBeTruthy(); + }); + + it('should return false if code NOT match', () => { + const hasUser: boolean = hasUserNoOrganisationsEinheitIdHint(createHintListResource()); + + expect(hasUser).toBeFalsy(); + }); + }); +}); diff --git a/alfa-client/libs/hint-shared/src/lib/hint.util.ts b/alfa-client/libs/hint-shared/src/lib/hint.util.ts index 36ba8abd41ac21133f8f786095afdf738b301e37..346187fd94ec6b686a67aac741d289fdbf2d10e3 100644 --- a/alfa-client/libs/hint-shared/src/lib/hint.util.ts +++ b/alfa-client/libs/hint-shared/src/lib/hint.util.ts @@ -5,11 +5,11 @@ import { HintMessageCode } from './hint.message'; import { HintListResource, HintResource } from './hint.model'; export function isUserHasNoOrganisationsEinheitIdHint(hint: HintResource): boolean { - return hint.code === HintMessageCode.USER_NO_ORGANISATIONS_EINHEIT_ID; + return hint.code === HintMessageCode.USER_NO_ORGANISATIONS_EINHEIT_ID; } export function hasUserNoOrganisationsEinheitIdHint(hintList: HintListResource): boolean { - const hints: HintResource[] = getEmbeddedResource(hintList, HintListLinkRel.HINT_LIST); - const hint = hints.find(hint => isUserHasNoOrganisationsEinheitIdHint(hint)); - return isNotUndefined(hint); -} \ No newline at end of file + const hints: HintResource[] = getEmbeddedResource(hintList, HintListLinkRel.HINT_LIST); + const hint = hints.find((hint) => isUserHasNoOrganisationsEinheitIdHint(hint)); + return isNotUndefined(hint); +} diff --git a/alfa-client/libs/hint-shared/src/test-setup.ts b/alfa-client/libs/hint-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/hint-shared/src/test-setup.ts +++ b/alfa-client/libs/hint-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/hint-shared/test-setup.ts b/alfa-client/libs/hint-shared/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/hint-shared/test-setup.ts +++ b/alfa-client/libs/hint-shared/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/hint-shared/test/hint.ts b/alfa-client/libs/hint-shared/test/hint.ts index d00274721f2baf1658f681e56f75028b635f3cdc..c4aadd8d6654a695728fc4e067efdb9840b2fe39 100644 --- a/alfa-client/libs/hint-shared/test/hint.ts +++ b/alfa-client/libs/hint-shared/test/hint.ts @@ -5,25 +5,28 @@ import { HintListLinkRel } from '../src/lib/hint.linkrel'; import { Hint, HintListResource, HintResource } from '../src/lib/hint.model'; export function createHint(): Hint { - return { code: faker.random.alphaNumeric() }; + return { code: faker.random.alphaNumeric() }; } export function createHintResource(linkRelations: string[] = []): HintResource { - return toResource(createHint(), linkRelations); + return toResource(createHint(), linkRelations); } export function createHintResources(linkRelations: string[] = []): HintResource[] { - return times(10, () => toResource(createHintResource(), [...linkRelations])); + return times(10, () => toResource(createHintResource(), [...linkRelations])); } export function createHintListResource(linkRelations: string[] = []): HintListResource { - return toResource({}, [...linkRelations], { - [HintListLinkRel.HINT_LIST]: createHintResources([...linkRelations]) - }); + return toResource({}, [...linkRelations], { + [HintListLinkRel.HINT_LIST]: createHintResources([...linkRelations]), + }); } -export function createHintListResourceWithResource(resources: HintResource[], linkRelations: string[] = []): HintListResource { - return toResource({}, [...linkRelations], { - [HintListLinkRel.HINT_LIST]: resources - }); -} \ No newline at end of file +export function createHintListResourceWithResource( + resources: HintResource[], + linkRelations: string[] = [], +): HintListResource { + return toResource({}, [...linkRelations], { + [HintListLinkRel.HINT_LIST]: resources, + }); +} diff --git a/alfa-client/libs/hint-shared/tsconfig.json b/alfa-client/libs/hint-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/hint-shared/tsconfig.json +++ b/alfa-client/libs/hint-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/hint-shared/tsconfig.lib.json b/alfa-client/libs/hint-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/hint-shared/tsconfig.lib.json +++ b/alfa-client/libs/hint-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/hint-shared/tsconfig.spec.json b/alfa-client/libs/hint-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/hint-shared/tsconfig.spec.json +++ b/alfa-client/libs/hint-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/hint/.eslintrc.json b/alfa-client/libs/hint/.eslintrc.json index 7b7b6231394b8c5674ce1b007077d4327aea7fda..9416ef7fe3c2643718ea92627388bf35847fc788 100644 --- a/alfa-client/libs/hint/.eslintrc.json +++ b/alfa-client/libs/hint/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - }, - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ] - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + }, + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"] + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/hint/jest.config.ts b/alfa-client/libs/hint/jest.config.ts index 1eda8ae12ac80bb4fc06fb0f47a8dc65942c24ad..34cccf70c57bcc3c061a75627fd0b2ff9922f601 100644 --- a/alfa-client/libs/hint/jest.config.ts +++ b/alfa-client/libs/hint/jest.config.ts @@ -1,23 +1,23 @@ /* eslint-disable */ export default { - displayName: 'hint', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/hint', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'hint', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/hint', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/hint/project.json b/alfa-client/libs/hint/project.json index 8931a28fad637bf22ffbea8d15835083c5bd4cbf..65184c2dff52242ef446f23e98a2c966c4bc6b41 100644 --- a/alfa-client/libs/hint/project.json +++ b/alfa-client/libs/hint/project.json @@ -1,25 +1,25 @@ { - "name": "hint", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/hint/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/hint"], - "options": { - "tsConfig": "libs/hint/tsconfig.spec.json", - "jestConfig": "libs/hint/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": ["libs/hint/**/*.ts", "libs/hint/**/*.html"] - } - } - }, - "tags": [] + "name": "hint", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/hint/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/hint"], + "options": { + "tsConfig": "libs/hint/tsconfig.spec.json", + "jestConfig": "libs/hint/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/hint/**/*.ts", "libs/hint/**/*.html"] + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.html b/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.html index fa218bbbf2a4825cffc8355cad6bf42aeca587ca..c55a2b4bcb55172a16f189f6ed5948bd58dcb3ea 100644 --- a/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.html +++ b/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.html @@ -1 +1,4 @@ -<alfa-user-no-organisations-einheit-id-hint *ngIf="hasUserNoOrganisationsEinheitIdHint$ | async" data-test-id="no-organisations-einheit-id-hint"></alfa-user-no-organisations-einheit-id-hint> \ No newline at end of file +<alfa-user-no-organisations-einheit-id-hint + *ngIf="hasUserNoOrganisationsEinheitIdHint$ | async" + data-test-id="no-organisations-einheit-id-hint" +></alfa-user-no-organisations-einheit-id-hint> diff --git a/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.spec.ts b/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.spec.ts index 258c426c92256fe267d8a0d7bc283d5edcf43bd8..92d4bd295856dab54dc4ff02214000375411201d 100644 --- a/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.spec.ts +++ b/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.spec.ts @@ -8,60 +8,58 @@ import { HintContainerComponent } from './hint-container.component'; import { UserNoOrganisationsEinheitIdHintComponent } from './user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component'; describe('HintContainerComponent', () => { - let component: HintContainerComponent; - let fixture: ComponentFixture<HintContainerComponent>; + let component: HintContainerComponent; + let fixture: ComponentFixture<HintContainerComponent>; - const noOrganisationsEinheitIdHint: string = getDataTestIdOf('no-organisations-einheit-id-hint'); - const service: Mock<HintService> = mock(HintService); + const noOrganisationsEinheitIdHint: string = getDataTestIdOf('no-organisations-einheit-id-hint'); + const service: Mock<HintService> = mock(HintService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HintContainerComponent, - MockComponent(UserNoOrganisationsEinheitIdHintComponent) - ], - providers: [ - { - provide: HintService, - useValue: service - } - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HintContainerComponent, + MockComponent(UserNoOrganisationsEinheitIdHintComponent), + ], + providers: [ + { + provide: HintService, + useValue: service, + }, + ], + }).compileComponents(); - fixture = TestBed.createComponent(HintContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(HintContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should call service to get hasUserNoOrganisationsEinheitIdHint', () => { + component.ngOnInit(); - it('should call service to get hasUserNoOrganisationsEinheitIdHint', () => { - component.ngOnInit(); + expect(service.hasUserNoOrganisationsEinheitIdHint).toHaveBeenCalled(); + }); + }); - expect(service.hasUserNoOrganisationsEinheitIdHint).toHaveBeenCalled(); - }) - }) + describe('no organisationsEinehit id', () => { + it('should hide if hint resource is null', () => { + component.hasUserNoOrganisationsEinheitIdHint$ = of(false); - describe('no organisationsEinehit id', () => { + fixture.detectChanges(); - it('should hide if hint resource is null', () => { - component.hasUserNoOrganisationsEinheitIdHint$ = of(false); + notExistsAsHtmlElement(fixture, noOrganisationsEinheitIdHint); + }); - fixture.detectChanges(); + it('should show if hint resource exists', () => { + component.hasUserNoOrganisationsEinheitIdHint$ = of(true); - notExistsAsHtmlElement(fixture, noOrganisationsEinheitIdHint); - }) + fixture.detectChanges(); - it('should show if hint resource exists', () => { - component.hasUserNoOrganisationsEinheitIdHint$ = of(true); - - fixture.detectChanges(); - - existsAsHtmlElement(fixture, noOrganisationsEinheitIdHint); - }) - }) + existsAsHtmlElement(fixture, noOrganisationsEinheitIdHint); + }); + }); }); diff --git a/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.ts b/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.ts index 71c0a5e4e3984df56d5249b0fe66ae79f2d46fcc..30eccc12c1c20f16313b6e70adaa34bb2ad125e7 100644 --- a/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.ts +++ b/alfa-client/libs/hint/src/lib/hint-container/hint-container.component.ts @@ -3,17 +3,17 @@ import { HintService } from '@alfa-client/hint-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-hint-container', - templateUrl: './hint-container.component.html', - styleUrls: ['./hint-container.component.scss'], + selector: 'alfa-hint-container', + templateUrl: './hint-container.component.html', + styleUrls: ['./hint-container.component.scss'], }) export class HintContainerComponent implements OnInit { + public hasUserNoOrganisationsEinheitIdHint$: Observable<boolean>; - public hasUserNoOrganisationsEinheitIdHint$: Observable<boolean>; + constructor(private hintService: HintService) {} - constructor(private hintService: HintService){ } - - ngOnInit(): void { - this.hasUserNoOrganisationsEinheitIdHint$ = this.hintService.hasUserNoOrganisationsEinheitIdHint(); - } + ngOnInit(): void { + this.hasUserNoOrganisationsEinheitIdHint$ = + this.hintService.hasUserNoOrganisationsEinheitIdHint(); + } } diff --git a/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.html b/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.html index 73171e1bad2fe5693aa02110f3ea4f12965912c9..675a555a8f54aba77eaa538c32612225c556b251 100644 --- a/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.html +++ b/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.html @@ -3,8 +3,14 @@ <p>Prüfen Sie, ob folgendes zutrifft:</p> <ul> - <li>Es wurde keine Gruppe erstellt oder zugewiesen <br/> (fehlende <span class="mono">organisationseinheitId</span>).</li> - <li>Das Wort <span class="mono">organisationseinheitId</span> wurde falsch geschrieben <br/> (bitte genau so schreiben wie hier angegeben).</li> + <li> + Es wurde keine Gruppe erstellt oder zugewiesen <br /> + (fehlende <span class="mono">organisationseinheitId</span>). + </li> + <li> + Das Wort <span class="mono">organisationseinheitId</span> wurde falsch geschrieben <br /> + (bitte genau so schreiben wie hier angegeben). + </li> </ul> -<p>Bitte bei der verantwortlichen Person des User-Managements bzw. des Keycloaks melden.</p> \ No newline at end of file +<p>Bitte bei der verantwortlichen Person des User-Managements bzw. des Keycloaks melden.</p> diff --git a/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.scss b/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.scss index d96ad48ff1d7d8c320ad1845788863576dc9c766..8969719b48a7433ce89b7b53433c669c4805eea1 100644 --- a/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.scss +++ b/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.scss @@ -1,13 +1,13 @@ :host { - display: block; - padding: 24px 32px; + display: block; + padding: 24px 32px; } .mono { - font-family: 'Roboto Mono', monospace; - font-weight: 700; + font-family: 'Roboto Mono', monospace; + font-weight: 700; } li { - margin-bottom: 0.75rem; -} \ No newline at end of file + margin-bottom: 0.75rem; +} diff --git a/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.spec.ts b/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.spec.ts index da4511300d2c4acfd2272828e391aa8f5deff410..954bbdc37813afaf21d5da7dd43bc5b699e73b42 100644 --- a/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.spec.ts +++ b/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.spec.ts @@ -2,20 +2,20 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { UserNoOrganisationsEinheitIdHintComponent } from './user-no-organisations-einheit-id-hint.component'; describe('UserNoOrganisationsEinheitIdHintComponent', () => { - let component: UserNoOrganisationsEinheitIdHintComponent; - let fixture: ComponentFixture<UserNoOrganisationsEinheitIdHintComponent>; + let component: UserNoOrganisationsEinheitIdHintComponent; + let fixture: ComponentFixture<UserNoOrganisationsEinheitIdHintComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [UserNoOrganisationsEinheitIdHintComponent], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UserNoOrganisationsEinheitIdHintComponent], + }).compileComponents(); - fixture = TestBed.createComponent(UserNoOrganisationsEinheitIdHintComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(UserNoOrganisationsEinheitIdHintComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.ts b/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.ts index ce6c2746a29b911be1ab62ebd31121a17cf533b0..62412c771239c5dccee8ad47e34b20380ba12ae1 100644 --- a/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.ts +++ b/alfa-client/libs/hint/src/lib/hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component.ts @@ -1,8 +1,8 @@ import { Component } from '@angular/core'; @Component({ - selector: 'alfa-user-no-organisations-einheit-id-hint', - templateUrl: './user-no-organisations-einheit-id-hint.component.html', - styleUrls: ['./user-no-organisations-einheit-id-hint.component.scss'], + selector: 'alfa-user-no-organisations-einheit-id-hint', + templateUrl: './user-no-organisations-einheit-id-hint.component.html', + styleUrls: ['./user-no-organisations-einheit-id-hint.component.scss'], }) -export class UserNoOrganisationsEinheitIdHintComponent { } +export class UserNoOrganisationsEinheitIdHintComponent {} diff --git a/alfa-client/libs/hint/src/lib/hint.module.spec.ts b/alfa-client/libs/hint/src/lib/hint.module.spec.ts index 0588400cbd290d02bc84273db8c98e5789d7d2a7..392a6c1e9438c965636cfe9ec8e6260c05253349 100644 --- a/alfa-client/libs/hint/src/lib/hint.module.spec.ts +++ b/alfa-client/libs/hint/src/lib/hint.module.spec.ts @@ -2,13 +2,13 @@ import { TestBed } from '@angular/core/testing'; import { HintModule } from './hint.module'; describe('HintModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [HintModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HintModule], + }).compileComponents(); + }); - it('should create', () => { - expect(HintModule).toBeDefined(); - }); + it('should create', () => { + expect(HintModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/hint/src/lib/hint.module.ts b/alfa-client/libs/hint/src/lib/hint.module.ts index 33c929e536f609f961b53ba5f1ef69585ec5463d..03d1abfaae0205d6d7dde3cc9891f37da59ab341 100644 --- a/alfa-client/libs/hint/src/lib/hint.module.ts +++ b/alfa-client/libs/hint/src/lib/hint.module.ts @@ -7,16 +7,8 @@ import { HintContainerComponent } from './hint-container/hint-container.componen import { UserNoOrganisationsEinheitIdHintComponent } from './hint-container/user-no-organisations-einheit-id-hint/user-no-organisations-einheit-id-hint.component'; @NgModule({ - imports: [ - CommonModule, - TechSharedModule, - ApiRootModule, - HintSharedModule - ], - declarations: [ - UserNoOrganisationsEinheitIdHintComponent, - HintContainerComponent - ], - exports: [HintContainerComponent], + imports: [CommonModule, TechSharedModule, ApiRootModule, HintSharedModule], + declarations: [UserNoOrganisationsEinheitIdHintComponent, HintContainerComponent], + exports: [HintContainerComponent], }) export class HintModule {} diff --git a/alfa-client/libs/hint/src/test-setup.ts b/alfa-client/libs/hint/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/hint/src/test-setup.ts +++ b/alfa-client/libs/hint/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/hint/tsconfig.json b/alfa-client/libs/hint/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/hint/tsconfig.json +++ b/alfa-client/libs/hint/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/hint/tsconfig.lib.json b/alfa-client/libs/hint/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/hint/tsconfig.lib.json +++ b/alfa-client/libs/hint/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/hint/tsconfig.spec.json b/alfa-client/libs/hint/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/hint/tsconfig.spec.json +++ b/alfa-client/libs/hint/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/historie-shared/.eslintrc.json b/alfa-client/libs/historie-shared/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/historie-shared/.eslintrc.json +++ b/alfa-client/libs/historie-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/historie-shared/jest.config.ts b/alfa-client/libs/historie-shared/jest.config.ts index 4cba4ebd5170e2ed46fe3cafd97bd14469dca5b9..011ebf08300584c8ff737fb311d4a979f8b876e4 100644 --- a/alfa-client/libs/historie-shared/jest.config.ts +++ b/alfa-client/libs/historie-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'historie-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/historie-shared', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + displayName: 'historie-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/historie-shared', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], }; diff --git a/alfa-client/libs/historie-shared/project.json b/alfa-client/libs/historie-shared/project.json index 71244733fd8a65731188c34cae3ed0361a6bbbd9..b846cf4cac2d5d614576ddf69c3acae644358b0d 100644 --- a/alfa-client/libs/historie-shared/project.json +++ b/alfa-client/libs/historie-shared/project.json @@ -1,28 +1,28 @@ { - "name": "historie-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/historie-shared/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/historie-shared"], - "options": { - "tsConfig": "libs/historie-shared/tsconfig.spec.json", - "jestConfig": "libs/historie-shared/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/historie-shared/src/**/*.ts", - "libs/historie-shared/src/**/*.html" - ] - } - } - }, - "tags": [] + "name": "historie-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/historie-shared/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/historie-shared"], + "options": { + "tsConfig": "libs/historie-shared/tsconfig.spec.json", + "jestConfig": "libs/historie-shared/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/historie-shared/src/**/*.ts", + "libs/historie-shared/src/**/*.html" + ] + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.actions.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.actions.ts index f8951da010d579468f4f9949d33d3208132022d8..ca456e5fcd6538188af300ee68d84c6301f5e9e8 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.actions.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.actions.ts @@ -21,16 +21,26 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { ApiErrorAction, TypedActionCreator, TypedActionCreatorWithProps } from '@alfa-client/tech-shared'; +import { + ApiErrorAction, + TypedActionCreator, + TypedActionCreatorWithProps, +} from '@alfa-client/tech-shared'; import { createAction, props } from '@ngrx/store'; import { HistorieListResource } from './historie.model'; export interface HistorieListProps { - historieList: HistorieListResource + historieList: HistorieListResource; } export const loadHistorie: TypedActionCreator = createAction('[Historie] Load All'); -export const loadHistorieSuccess: TypedActionCreatorWithProps<HistorieListProps> = createAction('[Historie] Load All Success', props<HistorieListProps>()); -export const loadHistorieFailed: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Historie] Load All Failed', props<ApiErrorAction>()); +export const loadHistorieSuccess: TypedActionCreatorWithProps<HistorieListProps> = createAction( + '[Historie] Load All Success', + props<HistorieListProps>(), +); +export const loadHistorieFailed: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[Historie] Load All Failed', + props<ApiErrorAction>(), +); -export const reloadHistorie: TypedActionCreator = createAction('[Historie] Set Reload'); \ No newline at end of file +export const reloadHistorie: TypedActionCreator = createAction('[Historie] Set Reload'); diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.effects.spec.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.effects.spec.ts index 8d49f144284f8888af452312f858bd40ca101d60..dc90ab586d34f64346a9773740659ad8b44e0810 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.effects.spec.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.effects.spec.ts @@ -38,74 +38,77 @@ import { HistorieListResource } from './historie.model'; import { HistorieService } from './historie.service'; describe('HistorieEffects', () => { - let actions: Observable<Action>; - let effects: HistorieEffects; - - const historieService = mock(HistorieService); - const vorgangService = mock(VorgangService); - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - HistorieEffects, - provideMockActions(() => actions), - provideMockStore(), - { - provide: HistorieService, - useValue: historieService - }, - { - provide: VorgangService, - useValue: vorgangService - } - ] - }); - effects = TestBed.inject(HistorieEffects); - }); - - describe('loadAll', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - beforeEach(() => { - vorgangService.getVorgangWithEingang.mockReturnValue(of(createStateResource(vorgangWithEingang))); - }) - - it('should call vorgang service', () => { - actions = of(HistorieActions.loadHistorie()); - - effects.loadAll.subscribe(); - - expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); - }) - - it('should call historie service', () => { - actions = of(HistorieActions.loadHistorie()); - - effects.loadAll.subscribe(); - - expect(historieService.loadAll).toHaveBeenCalledWith(vorgangWithEingang); - }) - - it('should dispatch loadHistorieSucess action', () => { - const historieList: HistorieListResource = createHistorieListResource(); - historieService.loadAll.mockReturnValue(of(historieList)); - - actions = hot('-a-|', { a: HistorieActions.loadHistorie() }); - - const expected = hot('-a-|', { a: HistorieActions.loadHistorieSuccess({ historieList }) }); - expect(effects.loadAll).toBeObservable(expected); - }) - - it('should dispatch loadHistorieFailed action', () => { - const apiError = 'an error occured'; - const errorResponse = cold('-#', {}, apiError); - historieService.loadAll = jest.fn(() => errorResponse); - - const expected = cold('--c', { c: HistorieActions.loadHistorieFailed(<ApiErrorAction><unknown>{ apiError }) }); - actions = hot('-a', { a: HistorieActions.loadHistorie() }); - - expect(effects.loadAll).toBeObservable(expected); - }) - }) + let actions: Observable<Action>; + let effects: HistorieEffects; + + const historieService = mock(HistorieService); + const vorgangService = mock(VorgangService); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + HistorieEffects, + provideMockActions(() => actions), + provideMockStore(), + { + provide: HistorieService, + useValue: historieService, + }, + { + provide: VorgangService, + useValue: vorgangService, + }, + ], + }); + effects = TestBed.inject(HistorieEffects); + }); + + describe('loadAll', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + beforeEach(() => { + vorgangService.getVorgangWithEingang.mockReturnValue( + of(createStateResource(vorgangWithEingang)), + ); + }); + + it('should call vorgang service', () => { + actions = of(HistorieActions.loadHistorie()); + + effects.loadAll.subscribe(); + + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); + + it('should call historie service', () => { + actions = of(HistorieActions.loadHistorie()); + + effects.loadAll.subscribe(); + + expect(historieService.loadAll).toHaveBeenCalledWith(vorgangWithEingang); + }); + + it('should dispatch loadHistorieSucess action', () => { + const historieList: HistorieListResource = createHistorieListResource(); + historieService.loadAll.mockReturnValue(of(historieList)); + + actions = hot('-a-|', { a: HistorieActions.loadHistorie() }); + + const expected = hot('-a-|', { a: HistorieActions.loadHistorieSuccess({ historieList }) }); + expect(effects.loadAll).toBeObservable(expected); + }); + + it('should dispatch loadHistorieFailed action', () => { + const apiError = 'an error occured'; + const errorResponse = cold('-#', {}, apiError); + historieService.loadAll = jest.fn(() => errorResponse); + + const expected = cold('--c', { + c: HistorieActions.loadHistorieFailed(<ApiErrorAction>(<unknown>{ apiError })), + }); + actions = hot('-a', { a: HistorieActions.loadHistorie() }); + + expect(effects.loadAll).toBeObservable(expected); + }); + }); }); diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.effects.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.effects.ts index a34589cb2bb9d8617cb313f9d6b03e05fb058b37..c324c86a470784c8dd62b3fe595321b6b484aba6 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.effects.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.effects.ts @@ -32,16 +32,22 @@ import * as HistorieActions from './historie.actions'; @Injectable() export class HistorieEffects { + constructor( + private readonly actions$: Actions, + private service: HistorieService, + private vorgangService: VorgangService, + ) {} - constructor(private readonly actions$: Actions, private service: HistorieService, private vorgangService: VorgangService) { } - - loadAll = createEffect(() => this.actions$.pipe(ofType(HistorieActions.loadHistorie), - concatLatestFrom(() => this.vorgangService.getVorgangWithEingang()), - switchMap(([, vorgang]) => { - return this.service.loadAll(vorgang.resource).pipe( - map(historieList => HistorieActions.loadHistorieSuccess({ historieList })), - catchError(apiError => of(HistorieActions.loadHistorieFailed({ apiError }))) - ) - })) - ) -} \ No newline at end of file + loadAll = createEffect(() => + this.actions$.pipe( + ofType(HistorieActions.loadHistorie), + concatLatestFrom(() => this.vorgangService.getVorgangWithEingang()), + switchMap(([, vorgang]) => { + return this.service.loadAll(vorgang.resource).pipe( + map((historieList) => HistorieActions.loadHistorieSuccess({ historieList })), + catchError((apiError) => of(HistorieActions.loadHistorieFailed({ apiError }))), + ); + }), + ), + ); +} diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.facade.spec.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.facade.spec.ts index c619fcc4c37cf41d2633a92333a9cf4136e1e836..2a0a47c4bb022120de58549e733fc6ada504d732 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.facade.spec.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.facade.spec.ts @@ -24,7 +24,11 @@ import { NgModule } from '@angular/core'; import { TestBed } from '@angular/core/testing'; import { CommandResource } from '@alfa-client/command-shared'; -import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { useFromMock } from '@alfa-client/test-utils'; import { UserProfileResource, UserProfileService } from '@alfa-client/user-profile-shared'; import { VorgangService } from '@alfa-client/vorgang-shared'; @@ -47,196 +51,191 @@ import { HistorieService } from './historie.service'; import * as HistorieActions from './historie.actions'; describe('HistorieFacade ITCase', () => { - let facade: HistorieFacade; - let store: Store<HistoriePartialState>; - - const historieService = mock(HistorieService); - const vorgangService = mock(VorgangService); - const userProfileService = mock(UserProfileService); - - beforeEach(() => { - @NgModule({ - imports: [ - StoreModule.forFeature(HISTORIE_FEATURE_KEY, reducer), - EffectsModule.forFeature([HistorieEffects]), - ], - providers: [HistorieFacade, - { - provide: HistorieService, - useValue: historieService - }, - { - provide: VorgangService, - useValue: vorgangService - }, - { - provide: UserProfileService, - useValue: userProfileService - } - ] - }) - class CustomFeatureModule { } - - @NgModule({ - imports: [ - StoreModule.forRoot({}), - EffectsModule.forRoot([]), - CustomFeatureModule, - ] - }) - class RootModule { } - TestBed.configureTestingModule({ imports: [RootModule] }); - - store = TestBed.inject(Store); - facade = TestBed.inject(HistorieFacade); - }); - - - - it('is initialized', () => { - expect(facade).toBeTruthy(); - }) - - describe('get historie', () => { - - beforeEach(() => { - historieService.loadAll.mockReturnValue(of(createHistorieListResource())); - vorgangService.getVorgangWithEingang.mockReturnValue(of(createVorgangResource())); - }) - - it('should return loading list on required loading resource', async () => { - let stateList = await readFirst(facade.getHistorie()); - - expect(stateList.resource).toBeNull(); - expect(stateList.loading).toEqual(true); - }) - - it('should return the loaded list', async () => { - const historieList: HistorieListResource = <HistorieListResource>createHistorieListResource(); - let stateList = await readFirst(facade.getHistorie()); - expect(stateList.resource).toBeNull(); - expect(stateList.loading).toEqual(true); - - store.dispatch(HistorieActions.loadHistorieSuccess(<HistorieListProps>{ historieList })); - - stateList = await readFirst(facade.getHistorie()); - expect(stateList.resource).toBe(historieList); - expect(stateList.loading).toBe(false); - }); - }) - - describe('reload historie', () => { - - it('should dispatch action', () => { - (<any>store).dispatch = jest.fn(); - - facade.reloadHistorie(); - - expect(store.dispatch).toHaveBeenCalledWith(HistorieActions.reloadHistorie()); - }) - }) - - describe('get assigned to', () => { - - const userProfile: UserProfileResource = createUserProfileResource(); - const command: CommandResource = createCommandResource(); - - beforeEach(() => { - userProfileService.getAssignedUserProfile.mockReturnValue(of(createStateResource(userProfile))); - }) - - it('should call userProfileService', async () => { - facade.getAssignedTo(command); - - expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith(command, 'assignedTo'); - }) - - it('should return user profile', async () => { - const assignedTo = await readFirst(facade.getAssignedTo(command)); - - expect(assignedTo.resource).toBe(userProfile); - }) - }) + let facade: HistorieFacade; + let store: Store<HistoriePartialState>; + + const historieService = mock(HistorieService); + const vorgangService = mock(VorgangService); + const userProfileService = mock(UserProfileService); + + beforeEach(() => { + @NgModule({ + imports: [ + StoreModule.forFeature(HISTORIE_FEATURE_KEY, reducer), + EffectsModule.forFeature([HistorieEffects]), + ], + providers: [ + HistorieFacade, + { + provide: HistorieService, + useValue: historieService, + }, + { + provide: VorgangService, + useValue: vorgangService, + }, + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }) + class CustomFeatureModule {} + + @NgModule({ + imports: [StoreModule.forRoot({}), EffectsModule.forRoot([]), CustomFeatureModule], + }) + class RootModule {} + TestBed.configureTestingModule({ imports: [RootModule] }); + + store = TestBed.inject(Store); + facade = TestBed.inject(HistorieFacade); + }); + + it('is initialized', () => { + expect(facade).toBeTruthy(); + }); + + describe('get historie', () => { + beforeEach(() => { + historieService.loadAll.mockReturnValue(of(createHistorieListResource())); + vorgangService.getVorgangWithEingang.mockReturnValue(of(createVorgangResource())); + }); + + it('should return loading list on required loading resource', async () => { + let stateList = await readFirst(facade.getHistorie()); + + expect(stateList.resource).toBeNull(); + expect(stateList.loading).toEqual(true); + }); + + it('should return the loaded list', async () => { + const historieList: HistorieListResource = <HistorieListResource>createHistorieListResource(); + let stateList = await readFirst(facade.getHistorie()); + expect(stateList.resource).toBeNull(); + expect(stateList.loading).toEqual(true); + + store.dispatch(HistorieActions.loadHistorieSuccess(<HistorieListProps>{ historieList })); + + stateList = await readFirst(facade.getHistorie()); + expect(stateList.resource).toBe(historieList); + expect(stateList.loading).toBe(false); + }); + }); + + describe('reload historie', () => { + it('should dispatch action', () => { + (<any>store).dispatch = jest.fn(); + + facade.reloadHistorie(); + + expect(store.dispatch).toHaveBeenCalledWith(HistorieActions.reloadHistorie()); + }); + }); + + describe('get assigned to', () => { + const userProfile: UserProfileResource = createUserProfileResource(); + const command: CommandResource = createCommandResource(); + + beforeEach(() => { + userProfileService.getAssignedUserProfile.mockReturnValue( + of(createStateResource(userProfile)), + ); + }); + + it('should call userProfileService', async () => { + facade.getAssignedTo(command); + + expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith(command, 'assignedTo'); + }); + + it('should return user profile', async () => { + const assignedTo = await readFirst(facade.getAssignedTo(command)); + + expect(assignedTo.resource).toBe(userProfile); + }); + }); }); describe('HistorieFacade UnitTest', () => { - let facade: HistorieFacade; - let store; + let facade: HistorieFacade; + let store; - let selectionSubject: Subject<StateResource<HistorieListResource>>; + let selectionSubject: Subject<StateResource<HistorieListResource>>; - const userProfileService = mock(UserProfileService); + const userProfileService = mock(UserProfileService); - beforeEach(() => { - store = mock(Store); + beforeEach(() => { + store = mock(Store); - selectionSubject = new Subject(); + selectionSubject = new Subject(); - store.select.mockReturnValue(selectionSubject); - store.dispatch = jest.fn(); + store.select.mockReturnValue(selectionSubject); + store.dispatch = jest.fn(); - facade = new HistorieFacade(useFromMock(<any>store), useFromMock(<any>userProfileService)); - }) + facade = new HistorieFacade(useFromMock(<any>store), useFromMock(<any>userProfileService)); + }); - it('is initialized', () => { - expect(facade).toBeTruthy(); - }) + it('is initialized', () => { + expect(facade).toBeTruthy(); + }); - describe('get historie', () => { + describe('get historie', () => { + it('should return selected value', (done) => { + const historieListResource: StateResource<HistorieListResource> = createStateResource( + createHistorieListResource(), + ); - it('should return selected value', (done) => { - const historieListResource: StateResource<HistorieListResource> = createStateResource(createHistorieListResource()); + facade.getHistorie().subscribe((selectorValue) => { + expect(selectorValue).toBe(historieListResource); + done(); + }); - facade.getHistorie().subscribe(selectorValue => { - expect(selectorValue).toBe(historieListResource); - done(); - }); + selectionSubject.next(historieListResource); + }); - selectionSubject.next(historieListResource); - }); + it('should dispatch action if not loaded', (done) => { + facade.getHistorie().subscribe((historieList) => { + expect(store.dispatch).toHaveBeenCalledWith(HistorieActions.loadHistorie()); + expect(historieList.loading).toBe(true); + done(); + }); - it('should dispatch action if not loaded', (done) => { - facade.getHistorie().subscribe(historieList => { - expect(store.dispatch).toHaveBeenCalledWith(HistorieActions.loadHistorie()); - expect(historieList.loading).toBe(true); - done(); - }); + selectionSubject.next(createEmptyStateResource()); + selectionSubject.next(createEmptyStateResource(true)); + }); + }); - selectionSubject.next(createEmptyStateResource()); - selectionSubject.next(createEmptyStateResource(true)); - }); - }) + describe('reload historie', () => { + it('should dispatch action', () => { + (<any>store).dispatch = jest.fn(); - describe('reload historie', () => { + facade.reloadHistorie(); - it('should dispatch action', () => { - (<any>store).dispatch = jest.fn(); + expect(store.dispatch).toHaveBeenCalledWith(HistorieActions.reloadHistorie()); + }); + }); - facade.reloadHistorie(); + describe('get assigned to', () => { + const userProfile: UserProfileResource = createUserProfileResource(); + const command: CommandResource = createCommandResource(); - expect(store.dispatch).toHaveBeenCalledWith(HistorieActions.reloadHistorie()); - }) - }) + beforeEach(() => { + userProfileService.getAssignedUserProfile.mockReturnValue( + of(createStateResource(userProfile)), + ); + }); - describe('get assigned to', () => { + it('should call userProfileService', async () => { + facade.getAssignedTo(command); - const userProfile: UserProfileResource = createUserProfileResource(); - const command: CommandResource = createCommandResource(); + expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith(command, 'assignedTo'); + }); - beforeEach(() => { - userProfileService.getAssignedUserProfile.mockReturnValue(of(createStateResource(userProfile))); - }) + it('should return user profile', async () => { + const assignedTo = await readFirst(facade.getAssignedTo(command)); - it('should call userProfileService', async () => { - facade.getAssignedTo(command); - - expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith(command, 'assignedTo'); - }) - - it('should return user profile', async () => { - const assignedTo = await readFirst(facade.getAssignedTo(command)); - - expect(assignedTo.resource).toBe(userProfile); - }) - }) -}); \ No newline at end of file + expect(assignedTo.resource).toBe(userProfile); + }); + }); +}); diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.facade.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.facade.ts index 20c06e85fccfc89f4fac0f42f6b455e05485534b..2ea13b42753baf994452527e5cd21afed50a4fd6 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.facade.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.facade.ts @@ -35,21 +35,27 @@ import * as HistorieSelectors from './historie.selectors'; @Injectable() export class HistorieFacade { + constructor( + private readonly store: Store, + private userProfileService: UserProfileService, + ) {} - constructor(private readonly store: Store, private userProfileService: UserProfileService) { } + getHistorie(): Observable<StateResource<HistorieListResource>> { + return this.store.select(HistorieSelectors.historieSelector).pipe( + filter( + (historieList) => + !doIfLoadingRequired(historieList, () => { + this.store.dispatch(HistorieActions.loadHistorie()); + }), + ), + ); + } - getHistorie(): Observable<StateResource<HistorieListResource>> { - return this.store.select(HistorieSelectors.historieSelector).pipe( - filter(historieList => !doIfLoadingRequired(historieList, () => { - this.store.dispatch(HistorieActions.loadHistorie()); - }))); - } + reloadHistorie(): void { + this.store.dispatch(HistorieActions.reloadHistorie()); + } - reloadHistorie(): void { - this.store.dispatch(HistorieActions.reloadHistorie()); - } - - getAssignedTo(command: CommandResource): Observable<StateResource<UserProfileResource>> { - return this.userProfileService.getAssignedUserProfile(command, 'assignedTo'); - } -} \ No newline at end of file + getAssignedTo(command: CommandResource): Observable<StateResource<UserProfileResource>> { + return this.userProfileService.getAssignedUserProfile(command, 'assignedTo'); + } +} diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.model.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.model.ts index be880704a529cfd8e275ab1075ccff78b43e17b6..ab6e83bccf57397e9790bccc0b7e3ccf942c86cb 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.model.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.model.ts @@ -25,15 +25,15 @@ import { ListResource } from '@alfa-client/tech-shared'; import { Resource } from '@ngxp/rest'; export interface Historie { - createdAt: Date, - createdByName: string, - status: any, - finishedAt: Date, - errorMessage: string, - order: any - body: object + createdAt: Date; + createdByName: string; + status: any; + finishedAt: Date; + errorMessage: string; + order: any; + body: object; } -export interface HistorieResource extends Historie, Resource { } +export interface HistorieResource extends Historie, Resource {} -export interface HistorieListResource extends ListResource { } \ No newline at end of file +export interface HistorieListResource extends ListResource {} diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.reducer.spec.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.reducer.spec.ts index 1958dd7bec334969fc2768dffb36393763b14608..2dcfa4a7465313c6783a7097e7b01c9e1a9db88a 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.reducer.spec.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.reducer.spec.ts @@ -30,61 +30,55 @@ import { HistorieState, initialState, reducer } from './historie.reducer'; import * as HistorieActions from './historie.actions'; describe('Historie Reducer', () => { + describe('unknown action', () => { + it('should return the previous state', () => { + const action = {} as Action; - describe('unknown action', () => { + const result = reducer(initialState, action); - it('should return the previous state', () => { - const action = {} as Action; + expect(result).toBe(initialState); + }); + }); - const result = reducer(initialState, action); + describe('on loadHistorie action', () => { + it('should set loading to true', () => { + const action = HistorieActions.loadHistorie(); - expect(result).toBe(initialState); - }) - }) + const result: HistorieState = reducer(initialState, action); - describe('on loadHistorie action', () => { + expect(result.historieList.loading).toBeTruthy(); + }); + }); - it('should set loading to true', () => { - const action = HistorieActions.loadHistorie(); + describe('on loadHistorieSuccess action', () => { + it('should set loaded resource into state', () => { + const historieList: HistorieListResource = <HistorieListResource>{}; + const action = HistorieActions.loadHistorieSuccess(<HistorieListProps>{ historieList }); - const result: HistorieState = reducer(initialState, action); + const result: HistorieState = reducer(initialState, action); - expect(result.historieList.loading).toBeTruthy(); - }) - }) + expect(result.historieList).toEqual(createStateResource(historieList)); + }); + }); - describe('on loadHistorieSuccess action', () => { + describe('on loadHistorieFailed action', () => { + it('should set error into state', () => { + const apiError = <Error>{}; //TODO durch richtigen Error ersetzt + const action = HistorieActions.loadHistorieFailed(<ApiErrorAction>(<unknown>{ apiError })); - it('should set loaded resource into state', () => { - const historieList: HistorieListResource = <HistorieListResource>{}; - const action = HistorieActions.loadHistorieSuccess(<HistorieListProps>{ historieList }); + const result: HistorieState = reducer(initialState, action); - const result: HistorieState = reducer(initialState, action); + expect(result.historieList.error).toBe(apiError); + }); + }); - expect(result.historieList).toEqual(createStateResource(historieList)); - }) - }) + describe('on reloadHistorie action', () => { + it('should set reload on stateresource to true', () => { + const action = HistorieActions.reloadHistorie(); - describe('on loadHistorieFailed action', () => { + const result: HistorieState = reducer(initialState, action); - it('should set error into state', () => { - const apiError = <Error>{};//TODO durch richtigen Error ersetzt - const action = HistorieActions.loadHistorieFailed(<ApiErrorAction><unknown>{ apiError }); - - const result: HistorieState = reducer(initialState, action); - - expect(result.historieList.error).toBe(apiError); - }) - }) - - describe('on reloadHistorie action', () => { - - it('should set reload on stateresource to true', () => { - const action = HistorieActions.reloadHistorie(); - - const result: HistorieState = reducer(initialState, action); - - expect(result.historieList.reload).toBeTruthy(); - }) - }) + expect(result.historieList.reload).toBeTruthy(); + }); + }); }); diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.reducer.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.reducer.ts index f64c6e8a2c90e2e4b1559167b79bb0a0e7211f51..f147072ecf610f511ef7cba5a6c660241b1eed6a 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.reducer.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.reducer.ts @@ -21,7 +21,13 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { ApiErrorAction, createEmptyStateResource, createErrorStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + ApiErrorAction, + createEmptyStateResource, + createErrorStateResource, + createStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { Action, createReducer, on } from '@ngrx/store'; import { HistorieListProps } from './historie.actions'; import { HistorieListResource } from './historie.model'; @@ -31,37 +37,37 @@ import * as HistorieActions from './historie.actions'; export const HISTORIE_FEATURE_KEY = 'HistorieState'; export interface HistorieState { - historieList: StateResource<HistorieListResource>; + historieList: StateResource<HistorieListResource>; } export interface HistoriePartialState { - readonly [HISTORIE_FEATURE_KEY]: HistorieState; + readonly [HISTORIE_FEATURE_KEY]: HistorieState; } export const initialState: HistorieState = { - historieList: createEmptyStateResource<HistorieListResource>() -} + historieList: createEmptyStateResource<HistorieListResource>(), +}; const historieReducer = createReducer( - initialState, - on(HistorieActions.loadHistorie, (state: HistorieState) => ({ - ...state, - historieList: { ...state.historieList, loading: true }, - })), - on(HistorieActions.loadHistorieSuccess, (state: HistorieState, props: HistorieListProps) => ({ - ...state, - historieList: createStateResource(props.historieList) - })), - on(HistorieActions.loadHistorieFailed, (state: HistorieState, props: ApiErrorAction) => ({ - ...state, - historieList: createErrorStateResource(props.apiError) - })), - on(HistorieActions.reloadHistorie, (state: HistorieState) => ({ - ...state, - historieList: { ...state.historieList, reload: true }, - })) -) + initialState, + on(HistorieActions.loadHistorie, (state: HistorieState) => ({ + ...state, + historieList: { ...state.historieList, loading: true }, + })), + on(HistorieActions.loadHistorieSuccess, (state: HistorieState, props: HistorieListProps) => ({ + ...state, + historieList: createStateResource(props.historieList), + })), + on(HistorieActions.loadHistorieFailed, (state: HistorieState, props: ApiErrorAction) => ({ + ...state, + historieList: createErrorStateResource(props.apiError), + })), + on(HistorieActions.reloadHistorie, (state: HistorieState) => ({ + ...state, + historieList: { ...state.historieList, reload: true }, + })), +); export function reducer(state: HistorieState, action: Action) { - return historieReducer(state, action); -} \ No newline at end of file + return historieReducer(state, action); +} diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.selectors.spec.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.selectors.spec.ts index 0be8dde0877927446aa8cf60e3c49e7b7faa6ac3..3b3d50d9b3928009c7b0842b0a6d3128e84b9f77 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.selectors.spec.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.selectors.spec.ts @@ -29,30 +29,32 @@ import { HistoriePartialState, initialState } from './historie.reducer'; import * as HistorieSelectors from './historie.selectors'; describe('Historie Selectors', () => { - - let state: HistoriePartialState; - - const historieList: StateResource<CommandListResource> = createStateResource(createCommandListResource()); - - beforeEach(() => { - state = { - HistorieState: { - ...initialState, - historieList - } - } - }) - - describe('historieSelector', () => { - - it('should return historieList', () => { - const result = HistorieSelectors.historieSelector.projector(state.HistorieState); - - expect(result).toBe(historieList); - }) - - it('should return historieList with projector', () => { - expect(HistorieSelectors.historieSelector.projector(state.HistorieState)).toEqual(historieList); - }) - }) -}) \ No newline at end of file + let state: HistoriePartialState; + + const historieList: StateResource<CommandListResource> = createStateResource( + createCommandListResource(), + ); + + beforeEach(() => { + state = { + HistorieState: { + ...initialState, + historieList, + }, + }; + }); + + describe('historieSelector', () => { + it('should return historieList', () => { + const result = HistorieSelectors.historieSelector.projector(state.HistorieState); + + expect(result).toBe(historieList); + }); + + it('should return historieList with projector', () => { + expect(HistorieSelectors.historieSelector.projector(state.HistorieState)).toEqual( + historieList, + ); + }); + }); +}); diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.selectors.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.selectors.ts index bb9ef744e1d34ce2bdaa6ccced92d3cf0e00bbca..d6d8800c8c9896b5fd1f930653c3b88e850d3962 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.selectors.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.selectors.ts @@ -26,6 +26,10 @@ import { MemoizedSelector, createFeatureSelector, createSelector } from '@ngrx/s import { HistorieListResource } from './historie.model'; import { HISTORIE_FEATURE_KEY, HistorieState } from './historie.reducer'; -export const getHistorieState: MemoizedSelector<object, HistorieState> = createFeatureSelector<HistorieState>(HISTORIE_FEATURE_KEY); +export const getHistorieState: MemoizedSelector<object, HistorieState> = + createFeatureSelector<HistorieState>(HISTORIE_FEATURE_KEY); -export const historieSelector: MemoizedSelector<HistorieState, StateResource<HistorieListResource>> = createSelector(getHistorieState, (state: HistorieState) => state.historieList); \ No newline at end of file +export const historieSelector: MemoizedSelector< + HistorieState, + StateResource<HistorieListResource> +> = createSelector(getHistorieState, (state: HistorieState) => state.historieList); diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.service.spec.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.service.spec.ts index 2c061bd5c6a73a124fc753aebf682f0c80fb0253..9592c0d7387bb8012085713b0d7d5f43fbca37ca 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.service.spec.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.service.spec.ts @@ -31,41 +31,41 @@ import { HistorieListResource } from './historie.model'; import { HistorieService } from './historie.service'; describe('HistorieService', () => { - let service: HistorieService; - let resourceFactory = mock(ResourceFactory); - let resourceWrapper = { get: jest.fn() }; + let service: HistorieService; + let resourceFactory = mock(ResourceFactory); + let resourceWrapper = { get: jest.fn() }; - beforeEach(() => { - service = new HistorieService(useFromMock(resourceFactory)); + beforeEach(() => { + service = new HistorieService(useFromMock(resourceFactory)); - resourceFactory.from.mockReturnValue(resourceWrapper); - }) + resourceFactory.from.mockReturnValue(resourceWrapper); + }); - describe('loadHistorieList', () => { - const historieListResource: HistorieListResource = createHistorieListResource(); - const vorgang: VorgangResource = createVorgangResource(); + describe('loadHistorieList', () => { + const historieListResource: HistorieListResource = createHistorieListResource(); + const vorgang: VorgangResource = createVorgangResource(); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: historieListResource })); - }) + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: historieListResource })); + }); - it('should call resourceFactory with given resource', () => { - service.loadAll(vorgang); + it('should call resourceFactory with given resource', () => { + service.loadAll(vorgang); - expect(resourceFactory.from).toHaveBeenCalledWith(vorgang); - }) + expect(resourceFactory.from).toHaveBeenCalledWith(vorgang); + }); - it('should call resourceWrapper with link', () => { - service.loadAll(vorgang); + it('should call resourceWrapper with link', () => { + service.loadAll(vorgang); - expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangWithEingangLinkRel.HISTORIE); - }) + expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangWithEingangLinkRel.HISTORIE); + }); - it('should return result', () => { - const result = service.loadAll(vorgang); + it('should return result', () => { + const result = service.loadAll(vorgang); - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: historieListResource })); - }) - }) -}) \ No newline at end of file + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: historieListResource })); + }); + }); +}); diff --git a/alfa-client/libs/historie-shared/src/lib/+state/historie.service.ts b/alfa-client/libs/historie-shared/src/lib/+state/historie.service.ts index edaef3ca0a9812cbcc44568b1e3c963f9b6ad5e5..3e0a23b6fd9b46f0076d72b2263aed4dc1cebe84 100644 --- a/alfa-client/libs/historie-shared/src/lib/+state/historie.service.ts +++ b/alfa-client/libs/historie-shared/src/lib/+state/historie.service.ts @@ -29,10 +29,9 @@ import { HistorieListResource } from './historie.model'; @Injectable() export class HistorieService { + constructor(private resourceFactory: ResourceFactory) {} - constructor(private resourceFactory: ResourceFactory) { } - - public loadAll(vorgang: VorgangResource): Observable<HistorieListResource> { - return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.HISTORIE); - } -} \ No newline at end of file + public loadAll(vorgang: VorgangResource): Observable<HistorieListResource> { + return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.HISTORIE); + } +} diff --git a/alfa-client/libs/historie-shared/src/lib/historie-shared.module.spec.ts b/alfa-client/libs/historie-shared/src/lib/historie-shared.module.spec.ts index 9578b3c756e3ef722e36015d487392f639b5ac4f..199a8baa9698b989ac239697c57bba58f018222b 100644 --- a/alfa-client/libs/historie-shared/src/lib/historie-shared.module.spec.ts +++ b/alfa-client/libs/historie-shared/src/lib/historie-shared.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { HistorieSharedModule } from './historie-shared.module'; describe('HistorieSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [HistorieSharedModule] - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HistorieSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(HistorieSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(HistorieSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/historie-shared/src/lib/historie-shared.module.ts b/alfa-client/libs/historie-shared/src/lib/historie-shared.module.ts index 96846fd0b4d684c43ea5a399caa3acf4968094a1..9ecc80a9e1957ab3d65e32a04879c3f7c7fe5c89 100644 --- a/alfa-client/libs/historie-shared/src/lib/historie-shared.module.ts +++ b/alfa-client/libs/historie-shared/src/lib/historie-shared.module.ts @@ -32,12 +32,12 @@ import { HISTORIE_FEATURE_KEY, reducer } from './+state/historie.reducer'; import { HistorieService } from './+state/historie.service'; @NgModule({ - imports: [ - CommonModule, - StoreModule.forFeature(HISTORIE_FEATURE_KEY, reducer), - EffectsModule.forFeature([HistorieEffects]), - VorgangSharedModule - ], - providers: [HistorieFacade, HistorieService] + imports: [ + CommonModule, + StoreModule.forFeature(HISTORIE_FEATURE_KEY, reducer), + EffectsModule.forFeature([HistorieEffects]), + VorgangSharedModule, + ], + providers: [HistorieFacade, HistorieService], }) -export class HistorieSharedModule { } \ No newline at end of file +export class HistorieSharedModule {} diff --git a/alfa-client/libs/historie-shared/src/lib/historie.util.ts b/alfa-client/libs/historie-shared/src/lib/historie.util.ts index 67d5f3100758f0eb937e391c9936d5075478d430..fa0d7546e8f945d3fcda34f7c221a523adffa68e 100644 --- a/alfa-client/libs/historie-shared/src/lib/historie.util.ts +++ b/alfa-client/libs/historie-shared/src/lib/historie.util.ts @@ -23,11 +23,14 @@ */ import { Type } from '@angular/core'; -export type Mock<T> = { [K in keyof T]: jest.Mock; }; +export type Mock<T> = { [K in keyof T]: jest.Mock }; export function mock<T>(service: Type<T>): Mock<T> { - return <Mock<T>>Object.getOwnPropertyNames(service.prototype).reduce((mockValue, key) => ({ - ...mockValue, - [key]: jest.fn() - }), (<any>{})); -} \ No newline at end of file + return <Mock<T>>Object.getOwnPropertyNames(service.prototype).reduce( + (mockValue, key) => ({ + ...mockValue, + [key]: jest.fn(), + }), + <any>{}, + ); +} diff --git a/alfa-client/libs/historie-shared/test/historie.ts b/alfa-client/libs/historie-shared/test/historie.ts index fac1efc2c1e86317520dd033387bccb03cdf4620..5a4fa3178a1de7897acd265ff7747984433f9d9e 100644 --- a/alfa-client/libs/historie-shared/test/historie.ts +++ b/alfa-client/libs/historie-shared/test/historie.ts @@ -27,8 +27,12 @@ import { createCommandResources } from 'libs/command-shared/test/command'; import { toResource } from 'libs/tech-shared/test/resource'; import { HistorieListResource } from '../src/lib/+state/historie.model'; -export function createHistorieListResource(linkRelations: string[] = [], resources?: CommandResource[]): HistorieListResource { - return toResource({}, [...linkRelations], { - [CommandListLinkRel.COMMAND_LIST]: resources ? resources : createCommandResources([...linkRelations]) - }); -} \ No newline at end of file +export function createHistorieListResource( + linkRelations: string[] = [], + resources?: CommandResource[], +): HistorieListResource { + return toResource({}, [...linkRelations], { + [CommandListLinkRel.COMMAND_LIST]: + resources ? resources : createCommandResources([...linkRelations]), + }); +} diff --git a/alfa-client/libs/historie-shared/tsconfig.json b/alfa-client/libs/historie-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/historie-shared/tsconfig.json +++ b/alfa-client/libs/historie-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/historie-shared/tsconfig.lib.json b/alfa-client/libs/historie-shared/tsconfig.lib.json index 8b8d236c4af5dba3d6c448b1f61147e3f9c68406..8ed448082e9531f7fe39bc149a1a30ec2b3f4edc 100644 --- a/alfa-client/libs/historie-shared/tsconfig.lib.json +++ b/alfa-client/libs/historie-shared/tsconfig.lib.json @@ -1,24 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": [ - "src/test-setup.ts", - "**/*.spec.ts", - "**/*.test.ts", - "jest.config.ts" - ], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "**/*.test.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/historie-shared/tsconfig.spec.json b/alfa-client/libs/historie-shared/tsconfig.spec.json index 4950ae2f7859509b300543bff1c1e5ce4b1e2d5c..c3cb17f784fa2f7b9a4b0e7c9b03663500f4ee3d 100644 --- a/alfa-client/libs/historie-shared/tsconfig.spec.json +++ b/alfa-client/libs/historie-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/historie/.eslintrc.json b/alfa-client/libs/historie/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/historie/.eslintrc.json +++ b/alfa-client/libs/historie/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/historie/jest.config.ts b/alfa-client/libs/historie/jest.config.ts index f31cf0d58bc2072fd9986d94fcaeb3e231952e47..8c6ba935ff49ffef0931840b6e1e8a47fbcdcc2f 100644 --- a/alfa-client/libs/historie/jest.config.ts +++ b/alfa-client/libs/historie/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'historie', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/historie', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'historie', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/historie', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/historie/project.json b/alfa-client/libs/historie/project.json index 54e1c00a85ab8a2113c0321ce05db6334f82a234..45ec1ef0e38ac77735fd618337473403b53aaf4c 100644 --- a/alfa-client/libs/historie/project.json +++ b/alfa-client/libs/historie/project.json @@ -1,28 +1,25 @@ { - "name": "historie", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/historie/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/historie"], - "options": { - "tsConfig": "libs/historie/tsconfig.spec.json", - "jestConfig": "libs/historie/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/historie/src/**/*.ts", - "libs/historie/src/**/*.html" - ] - } - } - }, - "tags": [] + "name": "historie", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/historie/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/historie"], + "options": { + "tsConfig": "libs/historie/tsconfig.spec.json", + "jestConfig": "libs/historie/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/historie/src/**/*.ts", "libs/historie/src/**/*.html"] + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/historie/src/index.ts b/alfa-client/libs/historie/src/index.ts index 8cae5821f68511f1f691916a8ae8874692ed14b5..64da90c0ea80293581e3478532f8751ac264bc7d 100644 --- a/alfa-client/libs/historie/src/index.ts +++ b/alfa-client/libs/historie/src/index.ts @@ -23,4 +23,3 @@ */ export * from './lib/historie-container/historie-container.component'; export * from './lib/historie.module'; - diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.html index 277dfb1c82e5bd5f23eb684aa07b2eb2604a0c54..0d3e080aa9da79223791be7f796c475c8b8b6aaf 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.html @@ -23,4 +23,9 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-historie-list data-test-id="tab-historie-list-container" [commandStateListResource]="historieListResource$ | async" [vorgangWithEingang]="vorgangWithEingang" data-test-id="historie-in-vorgang-container"></alfa-historie-list> \ No newline at end of file +<alfa-historie-list + data-test-id="tab-historie-list-container" + [commandStateListResource]="historieListResource$ | async" + [vorgangWithEingang]="vorgangWithEingang" + data-test-id="historie-in-vorgang-container" +></alfa-historie-list> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.spec.ts index 4dbcda1e08c5d78699f704c5cee0cd4662b2c5da..b677f2ea5e4ead88e1a726f753c325389fc333e1 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.spec.ts @@ -29,51 +29,46 @@ import { HistorieContainerComponent } from './historie-container.component'; import { HistorieListComponent } from './historie-list/historie-list.component'; describe('HistorieContainerComponent', () => { - let component: HistorieContainerComponent; - let fixture: ComponentFixture<HistorieContainerComponent>; + let component: HistorieContainerComponent; + let fixture: ComponentFixture<HistorieContainerComponent>; - const historieFacade = mock(HistorieFacade); + const historieFacade = mock(HistorieFacade); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieContainerComponent, - MockComponent(HistorieListComponent) - ], - providers: [ - { - provide: HistorieFacade, - useValue: historieFacade - } - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HistorieContainerComponent, MockComponent(HistorieListComponent)], + providers: [ + { + provide: HistorieFacade, + useValue: historieFacade, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should load historie', () => { + component.ngOnInit(); - it('should load historie', () => { - component.ngOnInit(); + expect(historieFacade.getHistorie).toHaveBeenCalled(); + }); + }); - expect(historieFacade.getHistorie).toHaveBeenCalled(); - }) - }) + describe('ngOnDestroy', () => { + it('should call facade', () => { + component.ngOnDestroy(); - describe('ngOnDestroy', () => { - - it('should call facade', () => { - component.ngOnDestroy(); - - expect(historieFacade.reloadHistorie).toHaveBeenCalled(); - }) - }) -}) \ No newline at end of file + expect(historieFacade.reloadHistorie).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.ts index 8bd720e0fa03c62ce79bd5402ab15ac4db846e28..2f675efad57ea92d49b67e46fc92354eb7cd1016 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-container.component.ts @@ -28,23 +28,22 @@ import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-historie-container', - templateUrl: './historie-container.component.html', - styleUrls: ['./historie-container.component.scss'], + selector: 'alfa-historie-container', + templateUrl: './historie-container.component.html', + styleUrls: ['./historie-container.component.scss'], }) export class HistorieContainerComponent implements OnInit, OnDestroy { + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() vorgangWithEingang: VorgangWithEingangResource; + historieListResource$: Observable<StateResource<HistorieListResource>>; - historieListResource$: Observable<StateResource<HistorieListResource>>; + constructor(private historieFacade: HistorieFacade) {} - constructor(private historieFacade: HistorieFacade) { } + ngOnInit(): void { + this.historieListResource$ = this.historieFacade.getHistorie(); + } - ngOnInit(): void { - this.historieListResource$ = this.historieFacade.getHistorie(); - } - - ngOnDestroy(): void { - this.historieFacade.reloadHistorie(); - } -} \ No newline at end of file + ngOnDestroy(): void { + this.historieFacade.reloadHistorie(); + } +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.html index 2ccef7b268e43aedfaa11f1df1599ee5f47e3c9f..75c5bb9cebdca0b8c7a4b176072c25880cb76587 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.html @@ -24,16 +24,38 @@ --> <ng-container *ngIf="resource"> - <mat-expansion-panel hideToggle [expanded]="expanded" data-test-class="expansion-panel-with-user" #expansionPanel> - <mat-expansion-panel-header> - <mat-panel-title> - <alfa-historie-item-header [resource]="resource" [headline]="headline"></alfa-historie-item-header> - </mat-panel-title> - <button data-test-class="expansion-button" mat-icon-button tabindex="-1" [attr.aria-label]="'Historie-Eintrag ' + (expansionPanel.expanded? 'reduzieren': 'erweitern')"> - <mat-icon>chevron_right</mat-icon> - </button> - </mat-expansion-panel-header> + <mat-expansion-panel + hideToggle + [expanded]="expanded" + data-test-class="expansion-panel-with-user" + #expansionPanel + > + <mat-expansion-panel-header> + <mat-panel-title> + <alfa-historie-item-header + [resource]="resource" + [headline]="headline" + ></alfa-historie-item-header> + </mat-panel-title> + <button + data-test-class="expansion-button" + mat-icon-button + tabindex="-1" + [attr.aria-label]=" + 'Historie-Eintrag ' + (expansionPanel.expanded ? 'reduzieren' : 'erweitern') + " + > + <mat-icon>chevron_right</mat-icon> + </button> + </mat-expansion-panel-header> - <div [ngStyle]="{visibility: expansionPanel.expanded ? 'visible' : 'hidden', display: expansionPanel.expanded ? 'block' : 'none'}"><ng-content></ng-content></div> - </mat-expansion-panel> -</ng-container> \ No newline at end of file + <div + [ngStyle]="{ + visibility: expansionPanel.expanded ? 'visible' : 'hidden', + display: expansionPanel.expanded ? 'block' : 'none' + }" + > + <ng-content></ng-content> + </div> + </mat-expansion-panel> +</ng-container> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.scss index 381d2ff88fc319ad2b31563609fa019bb4415f12..ebd031a1c517c01e20226273ec9e4e09ea7b8578 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.scss @@ -22,38 +22,37 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .mat-expansion-panel-header { + &:hover, + &.cdk-focused { + background-color: inherit !important; + } - &:hover, - &.cdk-focused { - background-color: inherit !important; - } + &.cdk-focused { + button { + background-color: rgba(#777, 0.16); + } + } - &.cdk-focused { - button { - background-color: rgba(#777, 0.16); - } - } + mat-icon { + transition: transform 0.1s ease-in-out; + padding-right: 4px; + } - mat-icon { - transition: transform 0.1s ease-in-out; - padding-right: 4px; - } - - &.mat-expanded { - mat-icon { - transform: rotate(90deg); - } - } + &.mat-expanded { + mat-icon { + transform: rotate(90deg); + } + } } .mat-expansion-panel-header-title { - align-items: center; - white-space: nowrap; - overflow: hidden; + align-items: center; + white-space: nowrap; + overflow: hidden; } .mat-expansion-panel { - background-color: inherit; - box-shadow: none; - border-radius: 0; + background-color: inherit; + box-shadow: none; + border-radius: 0; } diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.spec.ts index 46baf325b2dd83062f245f912a5d8bf1b0dfa8dc..46f2ef93f78734f7191f447852f61ea201918a8b 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.spec.ts @@ -23,7 +23,12 @@ */ import { PortalModule } from '@angular/cdk/portal'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatAccordion, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle } from '@angular/material/expansion'; +import { + MatAccordion, + MatExpansionPanel, + MatExpansionPanelHeader, + MatExpansionPanelTitle, +} from '@angular/material/expansion'; import { MatIcon } from '@angular/material/icon'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { ExpansionPanelComponent } from '@alfa-client/ui'; @@ -33,36 +38,33 @@ import { HistorieItemHeaderComponent } from '../historie-item-header/historie-it import { ExpansionPanelWithUserComponent } from './expansion-panel-with-user.component'; describe('ExpansionPanelWithUserComponent', () => { - let component: ExpansionPanelWithUserComponent; - let fixture: ComponentFixture<ExpansionPanelWithUserComponent>; + let component: ExpansionPanelWithUserComponent; + let fixture: ComponentFixture<ExpansionPanelWithUserComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - PortalModule - ], - declarations: [ - ExpansionPanelComponent, - MatExpansionPanel, - MatExpansionPanelTitle, - MatAccordion, - MatIcon, - MatExpansionPanelHeader, - ExpansionPanelWithUserComponent, - MockComponent(HistorieItemHeaderComponent) - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [NoopAnimationsModule, PortalModule], + declarations: [ + ExpansionPanelComponent, + MatExpansionPanel, + MatExpansionPanelTitle, + MatAccordion, + MatIcon, + MatExpansionPanelHeader, + ExpansionPanelWithUserComponent, + MockComponent(HistorieItemHeaderComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(ExpansionPanelWithUserComponent); - component = fixture.componentInstance; - component.resource = createCommandResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ExpansionPanelWithUserComponent); + component = fixture.componentInstance; + component.resource = createCommandResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }) + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.ts index ceafc69be734a1fc6002f2cbfec07c35fedde1d9..5a6979c2d68ecaf5633bcf2b89401dae3fc3c520 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/expansion-panel-with-user/expansion-panel-with-user.component.ts @@ -25,15 +25,14 @@ import { Component, Input } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; @Component({ - selector: 'alfa-expansion-panel-with-user', - templateUrl: './expansion-panel-with-user.component.html', - styleUrls: ['./expansion-panel-with-user.component.scss'], + selector: 'alfa-expansion-panel-with-user', + templateUrl: './expansion-panel-with-user.component.html', + styleUrls: ['./expansion-panel-with-user.component.scss'], }) export class ExpansionPanelWithUserComponent { + @Input() headline: string; + @Input() expanded: boolean = false; + @Input() resource: CommandResource; - @Input() headline: string; - @Input() expanded: boolean = false; - @Input() resource: CommandResource; - - readonly createdByLinkRelName: string = 'createdBy'; -} \ No newline at end of file + readonly createdByLinkRelName: string = 'createdBy'; +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.html index 8173f4e59c04d34c8773723f9f255f0e9687a7d0..992de90c5217c12d0074169522c81ff9ce7eec3d 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.html @@ -1,8 +1,12 @@ <div class="mat-expansion-panel" *ngIf="aktenzeichenDeleted; else expandable"> - <alfa-historie-item-header [headline]="headline" [resource]="command" data-test-id="historie-item-aktenzeichen-header"></alfa-historie-item-header> + <alfa-historie-item-header + [headline]="headline" + [resource]="command" + data-test-id="historie-item-aktenzeichen-header" + ></alfa-historie-item-header> </div> <ng-template #expandable> - <alfa-expansion-panel-with-user [headline]="headline" [resource]="command"> - <p data-test-class="aktenzeichen-text">Aktenzeichen: {{ aktenzeichen }}</p> - </alfa-expansion-panel-with-user> -</ng-template> \ No newline at end of file + <alfa-expansion-panel-with-user [headline]="headline" [resource]="command"> + <p data-test-class="aktenzeichen-text">Aktenzeichen: {{ aktenzeichen }}</p> + </alfa-expansion-panel-with-user> +</ng-template> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.spec.ts index 8adb768803ff01696e1fa9acff65647346e00328..133d87fad1abe21454581e0aeb1f45238a44743e 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.spec.ts @@ -10,102 +10,103 @@ import { getDataTestClassOf, getDataTestIdOf } from '../../../../../../tech-shar import { HistorieItemHeaderComponent } from '../historie-item-header/historie-item-header.component'; describe('HistorieItemAktenzeichenComponent', () => { - let component: HistorieItemAktenzeichenComponent; - let fixture: ComponentFixture<HistorieItemAktenzeichenComponent>; + let component: HistorieItemAktenzeichenComponent; + let fixture: ComponentFixture<HistorieItemAktenzeichenComponent>; - const kommentarCommand: CommandResource = { - ...createCommandResource(), - order: CommandOrder.CREATE_KOMMENTAR, - body: { item: { text: 'Beispiel text fuer einen Kommentar' } } - }; + const kommentarCommand: CommandResource = { + ...createCommandResource(), + order: CommandOrder.CREATE_KOMMENTAR, + body: { item: { text: 'Beispiel text fuer einen Kommentar' } }, + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieItemAktenzeichenComponent, - MockComponent(ExpansionPanelWithUserComponent), - MockComponent(HistorieItemAttachmentComponent), - MockComponent(HistorieItemHeaderComponent), - ], - }).compileComponents(); - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HistorieItemAktenzeichenComponent, + MockComponent(ExpansionPanelWithUserComponent), + MockComponent(HistorieItemAttachmentComponent), + MockComponent(HistorieItemHeaderComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemAktenzeichenComponent); - component = fixture.componentInstance; - component.command = kommentarCommand; - fixture.detectChanges(); - }) + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemAktenzeichenComponent); + component = fixture.componentInstance; + component.command = kommentarCommand; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }) + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should render non expandable historie item', () => { - component.aktenzeichenDeleted = true; - fixture.detectChanges(); + it('should render non expandable historie item', () => { + component.aktenzeichenDeleted = true; + fixture.detectChanges(); - const historieItem = getElementFromFixture(fixture, getDataTestIdOf('historie-item-aktenzeichen-header')); + const historieItem = getElementFromFixture( + fixture, + getDataTestIdOf('historie-item-aktenzeichen-header'), + ); - expect(historieItem).toBeInstanceOf(HTMLElement); - }) + expect(historieItem).toBeInstanceOf(HTMLElement); + }); - it('should render expandable historie item', () => { - component.aktenzeichenDeleted = false; - fixture.detectChanges(); + it('should render expandable historie item', () => { + component.aktenzeichenDeleted = false; + fixture.detectChanges(); - const aktenzeichenText = getElementFromFixture(fixture, getDataTestClassOf('aktenzeichen-text')); + const aktenzeichenText = getElementFromFixture( + fixture, + getDataTestClassOf('aktenzeichen-text'), + ); - expect(aktenzeichenText).toBeInstanceOf(HTMLElement); - }) + expect(aktenzeichenText).toBeInstanceOf(HTMLElement); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should set headline', () => { + component.setHeadline = jest.fn(); - it('should set headline', () => { - component.setHeadline = jest.fn(); + component.ngOnInit(); - component.ngOnInit(); + expect(component.setHeadline).toHaveBeenCalled(); + }); - expect(component.setHeadline).toHaveBeenCalled(); - }) + it('should mark aktenzeichen as deleted', () => { + component.command.body.aktenzeichen = null; - it('should mark aktenzeichen as deleted', () => { - component.command.body.aktenzeichen = null; + component.ngOnInit(); - component.ngOnInit(); + expect(component.aktenzeichenDeleted).toBeTruthy(); + }); - expect(component.aktenzeichenDeleted).toBeTruthy(); - }) + it('should mark aktenzeichen as NOT deleted', () => { + component.command.body.aktenzeichen = '1'; - it('should mark aktenzeichen as NOT deleted', () => { - component.command.body.aktenzeichen = '1'; + component.ngOnInit(); - component.ngOnInit(); + expect(component.aktenzeichenDeleted).toBeFalsy(); + }); + }); - expect(component.aktenzeichenDeleted).toBeFalsy(); - }) + describe('setHeadline', () => { + it('should set headline for order ' + CommandOrder.SET_AKTENZEICHEN, () => { + component.aktenzeichenDeleted = false; + component.command = { ...kommentarCommand, order: CommandOrder.SET_AKTENZEICHEN }; - }) + component.setHeadline(); - describe('setHeadline', () => { + expect(component.headline).toBe('das Aktenzeichen geändert.'); + }); - it('should set headline for order ' + CommandOrder.SET_AKTENZEICHEN, () => { - component.aktenzeichenDeleted = false; - component.command = { ...kommentarCommand, order: CommandOrder.SET_AKTENZEICHEN }; + it('should set headline for deleted aktenzeichen', () => { + component.aktenzeichenDeleted = true; - component.setHeadline() - - expect(component.headline).toBe('das Aktenzeichen geändert.'); - }) - - it('should set headline for deleted aktenzeichen', () => { - component.aktenzeichenDeleted = true; - - component.setHeadline() - - expect(component.headline).toBe('das Aktenzeichen gelöscht.'); - - }) - }) + component.setHeadline(); + expect(component.headline).toBe('das Aktenzeichen gelöscht.'); + }); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.ts index 265c2c5c8c9b31bfd7d7f0f072a4ac223c0ee298..a837054e7f636a27abeb7bbc79a456a7dda0560d 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component.ts @@ -5,35 +5,34 @@ import { isEmpty, isNull } from 'lodash-es'; import { hasContent } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-historie-item-aktenzeichen', - templateUrl: './historie-item-aktenzeichen.component.html', - styleUrls: ['./historie-item-aktenzeichen.component.scss'], + selector: 'alfa-historie-item-aktenzeichen', + templateUrl: './historie-item-aktenzeichen.component.html', + styleUrls: ['./historie-item-aktenzeichen.component.scss'], }) export class HistorieItemAktenzeichenComponent implements OnInit { + @Input() command: CommandResource; - @Input() command: CommandResource; + headline: string; + aktenzeichenDeleted = false; - headline: string; - aktenzeichenDeleted = false; + get aktenzeichen(): any { + return this.command.body.aktenzeichen; + } - get aktenzeichen(): any { - return this.command.body.aktenzeichen; - } + ngOnInit(): void { + this.aktenzeichenDeleted = isEmpty(this.aktenzeichen); + this.setHeadline(); + } - ngOnInit(): void { - this.aktenzeichenDeleted = isEmpty(this.aktenzeichen); - this.setHeadline(); - } - - setHeadline(): void { - if (this.aktenzeichenDeleted) { - this.headline = 'das Aktenzeichen gelöscht.'; - } else { - this.headline = HISTORIE_TEXT_BY_KOMMENTAR_ORDER[this.command.order]; - } - } + setHeadline(): void { + if (this.aktenzeichenDeleted) { + this.headline = 'das Aktenzeichen gelöscht.'; + } else { + this.headline = HISTORIE_TEXT_BY_KOMMENTAR_ORDER[this.command.order]; + } + } } const HISTORIE_TEXT_BY_KOMMENTAR_ORDER: { [order: string]: string } = { - [CommandOrder.SET_AKTENZEICHEN]: 'das Aktenzeichen geändert.', -} \ No newline at end of file + [CommandOrder.SET_AKTENZEICHEN]: 'das Aktenzeichen geändert.', +}; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.html index 010dc6184bc5ec50441616168c6e009b6d9d41e0..6165776943ead91fdc54008e6d90468f2f30a81e 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.html @@ -24,5 +24,8 @@ --> <div class="mat-expansion-panel"> - <alfa-historie-item-assign-user [command]="command" [userProfile]="(userProfile$ | async)?.resource"></alfa-historie-item-assign-user> -</div> \ No newline at end of file + <alfa-historie-item-assign-user + [command]="command" + [userProfile]="(userProfile$ | async)?.resource" + ></alfa-historie-item-assign-user> +</div> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.spec.ts index f7af1bcd8c8520a717d78b89f2319218ca16b18b..217bb970e73f708ddf28bf93e5c8a26398be8276 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.spec.ts @@ -31,44 +31,43 @@ import { HistorieItemAssignUserContainerComponent } from './historie-item-assign import { HistorieItemAssignUserComponent } from './historie-item-assign-user/historie-item-assign-user.component'; describe('HistorieItemAssignUserContainerComponent', () => { - let component: HistorieItemAssignUserContainerComponent; - let fixture: ComponentFixture<HistorieItemAssignUserContainerComponent>; + let component: HistorieItemAssignUserContainerComponent; + let fixture: ComponentFixture<HistorieItemAssignUserContainerComponent>; - const command: CommandResource = createCommandResource(); - const historieFacade = mock(HistorieFacade); + const command: CommandResource = createCommandResource(); + const historieFacade = mock(HistorieFacade); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieItemAssignUserContainerComponent, - MockComponent(HistorieItemAssignUserComponent) - ], - providers: [ - { - provide: HistorieFacade, - useValue: historieFacade - } - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HistorieItemAssignUserContainerComponent, + MockComponent(HistorieItemAssignUserComponent), + ], + providers: [ + { + provide: HistorieFacade, + useValue: historieFacade, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemAssignUserContainerComponent); - component = fixture.componentInstance; - component.command = command; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemAssignUserContainerComponent); + component = fixture.componentInstance; + component.command = command; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should call facade getAssignedTo', () => { + component.ngOnInit(); - it('should call facade getAssignedTo', () => { - component.ngOnInit(); - - expect(historieFacade.getAssignedTo).toHaveBeenCalledWith(command); - }) - }) + expect(historieFacade.getAssignedTo).toHaveBeenCalledWith(command); + }); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.ts index f170ada132a0553362449ca085c491fe90c863b7..741d10c7addc60e93f48b8e898e522499967200a 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user-container.component.ts @@ -29,19 +29,18 @@ import { UserProfileResource } from '@alfa-client/user-profile-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-historie-item-assign-user-container', - templateUrl: './historie-item-assign-user-container.component.html', - styleUrls: ['./historie-item-assign-user-container.component.scss'], + selector: 'alfa-historie-item-assign-user-container', + templateUrl: './historie-item-assign-user-container.component.html', + styleUrls: ['./historie-item-assign-user-container.component.scss'], }) export class HistorieItemAssignUserContainerComponent implements OnInit { + @Input() command: CommandResource; - @Input() command: CommandResource; + userProfile$: Observable<StateResource<UserProfileResource>>; - userProfile$: Observable<StateResource<UserProfileResource>>; + constructor(private historieFacade: HistorieFacade) {} - constructor(private historieFacade: HistorieFacade) { } - - ngOnInit(): void { - this.userProfile$ = this.historieFacade.getAssignedTo(this.command); - } -} \ No newline at end of file + ngOnInit(): void { + this.userProfile$ = this.historieFacade.getAssignedTo(this.command); + } +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.html index a716ca690bf257223a8c3b96da4afeae5169cf74..7a0b718185e204886f493fe32539233523730716 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.html @@ -23,4 +23,4 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-historie-item-header [headline]="headline" [resource]="command"></alfa-historie-item-header> \ No newline at end of file +<alfa-historie-item-header [headline]="headline" [resource]="command"></alfa-historie-item-header> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.scss index bfb9873f0c02956ef48c1f09a7cc2fbc00a33231..6f3521ec93d11e126c6bfd74e19aa02ad269d54c 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.scss @@ -24,4 +24,4 @@ :host { width: 100%; -} \ No newline at end of file +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.spec.ts index d44ede0b9594b2cf62ee0828de9eb3493e038bdc..1a656e74765d02cde34867be909f834fe197a421 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.spec.ts @@ -29,42 +29,40 @@ import { HistorieItemHeaderComponent } from '../../historie-item-header/historie import { HistorieItemAssignUserComponent } from './historie-item-assign-user.component'; describe('HistorieItemAssignUserComponent', () => { - let component: HistorieItemAssignUserComponent; - let fixture: ComponentFixture<HistorieItemAssignUserComponent>; + let component: HistorieItemAssignUserComponent; + let fixture: ComponentFixture<HistorieItemAssignUserComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieItemAssignUserComponent, - MockComponent(HistorieItemHeaderComponent) - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HistorieItemAssignUserComponent, MockComponent(HistorieItemHeaderComponent)], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemAssignUserComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemAssignUserComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('build headline', () => { + describe('build headline', () => { + it('should return "Unbekannter Benutzer" on user profile is null', () => { + const headline: string = component.buildHeadline(null); - it('should return "Unbekannter Benutzer" on user profile is null', () => { - const headline: string = component.buildHeadline(null); + expect(headline).toBe('Unbekannter Benutzer den Vorgang zugewiesen.'); + }); - expect(headline).toBe('Unbekannter Benutzer den Vorgang zugewiesen.'); - }) + it('should return firstName lastName on user profile exists', () => { + const userProfile: UserProfileResource = createUserProfileResource(); - it('should return firstName lastName on user profile exists', () => { - const userProfile: UserProfileResource = createUserProfileResource(); + const headline: string = component.buildHeadline(userProfile); - const headline: string = component.buildHeadline(userProfile); - - expect(headline).toBe(`${userProfile.firstName} ${userProfile.lastName} den Vorgang zugewiesen.`); - }) - }) + expect(headline).toBe( + `${userProfile.firstName} ${userProfile.lastName} den Vorgang zugewiesen.`, + ); + }); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.ts index de3845a42d6b5f3914d6064c2f708919a8c296c4..05283d03b7b4d05647a270440c95b166217c01a0 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-assign-user-container/historie-item-assign-user/historie-item-assign-user.component.ts @@ -26,21 +26,20 @@ import { CommandResource } from '@alfa-client/command-shared'; import { getUserName, UserProfileResource } from '@alfa-client/user-profile-shared'; @Component({ - selector: 'alfa-historie-item-assign-user', - templateUrl: './historie-item-assign-user.component.html', - styleUrls: ['./historie-item-assign-user.component.scss'], + selector: 'alfa-historie-item-assign-user', + templateUrl: './historie-item-assign-user.component.html', + styleUrls: ['./historie-item-assign-user.component.scss'], }) export class HistorieItemAssignUserComponent { + @Input() command: CommandResource; + @Input() + public set userProfile(userProfile: UserProfileResource) { + this.headline = this.buildHeadline(userProfile); + } - @Input() command: CommandResource; - @Input() - public set userProfile(userProfile: UserProfileResource) { - this.headline = this.buildHeadline(userProfile); - } + headline: string; - headline: string; - - buildHeadline(userProfile: UserProfileResource): string { - return `${getUserName(userProfile)} den Vorgang zugewiesen.`; - } -} \ No newline at end of file + buildHeadline(userProfile: UserProfileResource): string { + return `${getUserName(userProfile)} den Vorgang zugewiesen.`; + } +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.html index 7e2bfe951c8a948fd01e901d3a9c2a0cdb3142de..90ee65b34d9eaab7a57ff629a733cc9cf8d0c305 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.html @@ -23,4 +23,4 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<p data-test-class="historie-item-attachment">{{text}}</p> \ No newline at end of file +<p data-test-class="historie-item-attachment">{{ text }}</p> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.spec.ts index 419925788bf06470d47f26af33f98c315b7008ad..bce1c5ac373f1417c3312507ad490824708ab813 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.spec.ts @@ -26,38 +26,40 @@ import { faker } from '@faker-js/faker'; import { HistorieItemAttachmentComponent } from './historie-item-attachment.component'; describe('HistorieItemAttachmentComponent', () => { - let component: HistorieItemAttachmentComponent; - let fixture: ComponentFixture<HistorieItemAttachmentComponent>; + let component: HistorieItemAttachmentComponent; + let fixture: ComponentFixture<HistorieItemAttachmentComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [HistorieItemAttachmentComponent], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HistorieItemAttachmentComponent], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemAttachmentComponent); - component = fixture.componentInstance; - component.attachments = faker.datatype.uuid(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemAttachmentComponent); + component = fixture.componentInstance; + component.attachments = faker.datatype.uuid(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('build attachment text', () => { + describe('build attachment text', () => { + it('should return text for single attachment', () => { + const text: string = component.buildAttachmentText(faker.datatype.uuid()); - it('should return text for single attachment', () => { - const text: string = component.buildAttachmentText(faker.datatype.uuid()); + expect(text).toBe('Es existiert ein Anhang zu diesem Eintrag.'); + }); - expect(text).toBe('Es existiert ein Anhang zu diesem Eintrag.'); - }) + it('should return text for multiple attachment', () => { + const text: string = component.buildAttachmentText([ + faker.datatype.uuid(), + faker.datatype.uuid(), + ]); - it('should return text for multiple attachment', () => { - const text: string = component.buildAttachmentText([faker.datatype.uuid(), faker.datatype.uuid()]); - - expect(text).toBe(`Es existieren 2 Anhänge zu diesem Eintrag.`); - }) - }) + expect(text).toBe(`Es existieren 2 Anhänge zu diesem Eintrag.`); + }); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.ts index 35cb6917069ca429b3627e748e6af12923ce472d..256d21f54357838adad27979a26eab293c5858e4 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-attachment/historie-item-attachment.component.ts @@ -25,25 +25,24 @@ import { Component, Input, OnInit } from '@angular/core'; import { isString } from 'lodash-es'; @Component({ - selector: 'alfa-historie-item-attachment', - templateUrl: './historie-item-attachment.component.html', - styleUrls: ['./historie-item-attachment.component.scss'], + selector: 'alfa-historie-item-attachment', + templateUrl: './historie-item-attachment.component.html', + styleUrls: ['./historie-item-attachment.component.scss'], }) export class HistorieItemAttachmentComponent implements OnInit { + @Input() attachments: object | string; - @Input() attachments: object | string; + text: string; - text: string; + ngOnInit(): void { + this.text = this.buildAttachmentText(this.attachments); + } - ngOnInit(): void { - this.text = this.buildAttachmentText(this.attachments); - } - - buildAttachmentText(attachments: any): string { - if (isString(attachments)) { - return 'Es existiert ein Anhang zu diesem Eintrag.' - } else { - return `Es existieren ${attachments.length} Anhänge zu diesem Eintrag.`; - } - } -} \ No newline at end of file + buildAttachmentText(attachments: any): string { + if (isString(attachments)) { + return 'Es existiert ein Anhang zu diesem Eintrag.'; + } else { + return `Es existieren ${attachments.length} Anhänge zu diesem Eintrag.`; + } + } +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.html index 47f1b8630a6e85fb0a2a9693be66fe31f6233264..96413c3588b559cd8ae5b0723624cebdfc991e89 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.html @@ -24,5 +24,9 @@ --> <div class="mat-expansion-panel"> - <alfa-historie-item-header [headline]="headline" [resource]="command" data-test-id="historie-item-forwarding-header"></alfa-historie-item-header> -</div> \ No newline at end of file + <alfa-historie-item-header + [headline]="headline" + [resource]="command" + data-test-id="historie-item-forwarding-header" + ></alfa-historie-item-header> +</div> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.scss index 5bdff0dea3cbaef97bcaef245352e2e6af1c6f73..d6238211bb493815e84e9e0c249c4cb0acc816e7 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.scss @@ -21,4 +21,4 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -@import 'expansion-panel' \ No newline at end of file +@import 'expansion-panel'; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.spec.ts index a4f5427e6e92214c6547039d8c31e05764b55be5..b5ee40caed35b6fbfdec92657cd168b62319c9f6 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.spec.ts @@ -29,59 +29,55 @@ import { HistorieItemHeaderComponent } from '../historie-item-header/historie-it import { HistorieItemForwardingComponent } from './historie-item-forwarding.component'; describe('HistorieItemForwardingComponent', () => { - let component: HistorieItemForwardingComponent; - let fixture: ComponentFixture<HistorieItemForwardingComponent>; + let component: HistorieItemForwardingComponent; + let fixture: ComponentFixture<HistorieItemForwardingComponent>; - const forwardingCommand: CommandResource = { - ...createCommandResource(), - order: CommandOrder.REDIRECT_VORGANG, - body: { item: {} } - }; + const forwardingCommand: CommandResource = { + ...createCommandResource(), + order: CommandOrder.REDIRECT_VORGANG, + body: { item: {} }, + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieItemForwardingComponent, - MockComponent(HistorieItemHeaderComponent) - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HistorieItemForwardingComponent, MockComponent(HistorieItemHeaderComponent)], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemForwardingComponent); - component = fixture.componentInstance; - component.command = forwardingCommand; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemForwardingComponent); + component = fixture.componentInstance; + component.command = forwardingCommand; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should set headline for order ' + CommandOrder.REDIRECT_VORGANG, () => { + component.command = { ...forwardingCommand, order: CommandOrder.REDIRECT_VORGANG }; - it('should set headline for order ' + CommandOrder.REDIRECT_VORGANG, () => { - component.command = { ...forwardingCommand, order: CommandOrder.REDIRECT_VORGANG }; + component.ngOnInit(); - component.ngOnInit(); + expect(component.headline).toBe('den Vorgang weitergeleitet.'); + }); - expect(component.headline).toBe('den Vorgang weitergeleitet.'); - }) + it('should set headline for order' + CommandOrder.FORWARD_SUCCESSFULL, () => { + component.command = { ...forwardingCommand, order: CommandOrder.FORWARD_SUCCESSFULL }; - it('should set headline for order' + CommandOrder.FORWARD_SUCCESSFULL, () => { - component.command = { ...forwardingCommand, order: CommandOrder.FORWARD_SUCCESSFULL }; + component.ngOnInit(); - component.ngOnInit(); + expect(component.headline).toBe('die Weiterleitung bestätigt.'); + }); - expect(component.headline).toBe('die Weiterleitung bestätigt.'); - }) + it('should set headline for order' + CommandOrder.FORWARD_FAILED, () => { + component.command = { ...forwardingCommand, order: CommandOrder.FORWARD_FAILED }; - it('should set headline for order' + CommandOrder.FORWARD_FAILED, () => { - component.command = { ...forwardingCommand, order: CommandOrder.FORWARD_FAILED }; + component.ngOnInit(); - component.ngOnInit(); - - expect(component.headline).toBe('die Weiterleitung widerrufen.'); - }) - }) -}); \ No newline at end of file + expect(component.headline).toBe('die Weiterleitung widerrufen.'); + }); + }); +}); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.ts index 09b0d6bb517cfbca3dd4ff13544b721d0b758a27..438c564a2cfef9bac5937c1130a2e9f35463b9d9 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component.ts @@ -25,27 +25,26 @@ import { Component, Input } from '@angular/core'; import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; @Component({ - selector: 'alfa-historie-item-forwarding', - templateUrl: './historie-item-forwarding.component.html', - styleUrls: ['./historie-item-forwarding.component.scss'], + selector: 'alfa-historie-item-forwarding', + templateUrl: './historie-item-forwarding.component.html', + styleUrls: ['./historie-item-forwarding.component.scss'], }) export class HistorieItemForwardingComponent { + @Input() command: CommandResource; - @Input() command: CommandResource; + headline: string; - headline: string; + get forwarding(): any { + return this.command.body.item; + } - get forwarding(): any { - return this.command.body.item; - } - - ngOnInit(): void { - this.headline = HISTORIE_TEXT_BY_FORWARDING_ORDER[this.command.order]; - } + ngOnInit(): void { + this.headline = HISTORIE_TEXT_BY_FORWARDING_ORDER[this.command.order]; + } } const HISTORIE_TEXT_BY_FORWARDING_ORDER: { [order: string]: string } = { - [CommandOrder.REDIRECT_VORGANG]: 'den Vorgang weitergeleitet.', - [CommandOrder.FORWARD_SUCCESSFULL]: 'die Weiterleitung bestätigt.', - [CommandOrder.FORWARD_FAILED]: 'die Weiterleitung widerrufen.' -} \ No newline at end of file + [CommandOrder.REDIRECT_VORGANG]: 'den Vorgang weitergeleitet.', + [CommandOrder.FORWARD_SUCCESSFULL]: 'die Weiterleitung bestätigt.', + [CommandOrder.FORWARD_FAILED]: 'die Weiterleitung widerrufen.', +}; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.html index 276e4de711df7054dd2a26ad8059323117c73a38..5c3b90fe33b7e3fd1a02dfdc5f8812866434d659 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.html @@ -23,5 +23,18 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-user-profile-in-historie-container *ngIf="resource | hasLink: commandLinkRel.CREATED_BY; else nonUserCommand" [command]="resource" class="username" data-test-class="user-profile-in-historie-item-header"></alfa-user-profile-in-historie-container> -<ng-template #nonUserCommand><ozgcloud-app-icon></ozgcloud-app-icon><span class="username" data-test-class="system-user-in-historie-item-header">Die Anwendung</span></ng-template><p class="headline" data-test-class="historie-item-header">hat am {{(resource.createdAt | formatDateWithTimePipe: false)}} {{headline}}</p> \ No newline at end of file +<alfa-user-profile-in-historie-container + *ngIf="resource | hasLink: commandLinkRel.CREATED_BY; else nonUserCommand" + [command]="resource" + class="username" + data-test-class="user-profile-in-historie-item-header" +></alfa-user-profile-in-historie-container> +<ng-template #nonUserCommand + ><ozgcloud-app-icon></ozgcloud-app-icon + ><span class="username" data-test-class="system-user-in-historie-item-header" + >Die Anwendung</span + ></ng-template +> +<p class="headline" data-test-class="historie-item-header"> + hat am {{ resource.createdAt | formatDateWithTimePipe: false }} {{ headline }} +</p> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.scss index 55f635a2b2293ed992748f63fcfbf9491d9f3380..9eea5298d9ed6bb65a9907b621cd78aad006e467 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.scss @@ -22,30 +22,30 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - white-space: nowrap; - align-items: center; - min-height: 44px; - font-size: 14px; - width: 100%; + display: flex; + white-space: nowrap; + align-items: center; + min-height: 44px; + font-size: 14px; + width: 100%; } ozgcloud-app-icon { - margin: 0 6px 0 2px; - flex-shrink: 0; + margin: 0 6px 0 2px; + flex-shrink: 0; } .username { - flex-shrink: 1; - min-width: 0; - max-width: 30%; - overflow: hidden; - text-overflow: ellipsis; + flex-shrink: 1; + min-width: 0; + max-width: 30%; + overflow: hidden; + text-overflow: ellipsis; } .headline { - flex-shrink: 2; - margin: 0 0 0 0.5rem; - overflow: hidden; - text-overflow: ellipsis; -} \ No newline at end of file + flex-shrink: 2; + margin: 0 0 0 0.5rem; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.spec.ts index f0d6fc93937b4d73c4daa1f14c6eedb9138bcd2f..1066eac855b5dad7aa40588ac110d94e9395e592 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.spec.ts @@ -37,75 +37,72 @@ import { HistorieItemHeaderComponent } from './historie-item-header.component'; registerLocaleData(localeDe); describe('HistorieItemHeaderComponent', () => { - let component: HistorieItemHeaderComponent; - let fixture: ComponentFixture<HistorieItemHeaderComponent>; - - const userProfile: string = getDataTestClassOf('user-profile-in-historie-item-header'); - const nonUserCommandText: string = getDataTestClassOf('system-user-in-historie-item-header'); - - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - FormatDateWithTimePipe, - HasLinkPipe, - HistorieItemHeaderComponent, - MockComponent(UserProfileInHistorieContainerComponent), - MockComponent(AppIconComponent) - ], - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemHeaderComponent); - component = fixture.componentInstance; - component.resource = createCommandResource(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }) - - describe('user profile', () => { - - it('should show if link is present', () => { - component.resource = createCommandResource([CommandLinkRel.CREATED_BY]); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, userProfile); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should NOT show if link not exists', () => { - component.resource = createCommandResource(); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, userProfile); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('non user text', () => { - - it('should show if link NOT exists', () => { - component.resource = createCommandResource(); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, nonUserCommandText); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should NOT show if link is present', () => { - component.resource = createCommandResource([CommandLinkRel.CREATED_BY]); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, nonUserCommandText); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) + let component: HistorieItemHeaderComponent; + let fixture: ComponentFixture<HistorieItemHeaderComponent>; + + const userProfile: string = getDataTestClassOf('user-profile-in-historie-item-header'); + const nonUserCommandText: string = getDataTestClassOf('system-user-in-historie-item-header'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + FormatDateWithTimePipe, + HasLinkPipe, + HistorieItemHeaderComponent, + MockComponent(UserProfileInHistorieContainerComponent), + MockComponent(AppIconComponent), + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemHeaderComponent); + component = fixture.componentInstance; + component.resource = createCommandResource(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('user profile', () => { + it('should show if link is present', () => { + component.resource = createCommandResource([CommandLinkRel.CREATED_BY]); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, userProfile); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should NOT show if link not exists', () => { + component.resource = createCommandResource(); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, userProfile); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('non user text', () => { + it('should show if link NOT exists', () => { + component.resource = createCommandResource(); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, nonUserCommandText); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should NOT show if link is present', () => { + component.resource = createCommandResource([CommandLinkRel.CREATED_BY]); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, nonUserCommandText); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.ts index a9c7a602de3b7a4152a27ce01e0793afd4420af4..23c70faa05585cd6bdc500f1f9ba7c03a0857001 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-header/historie-item-header.component.ts @@ -26,14 +26,13 @@ import { CommandResource } from '@alfa-client/command-shared'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; @Component({ - selector: 'alfa-historie-item-header', - templateUrl: './historie-item-header.component.html', - styleUrls: ['./historie-item-header.component.scss'], + selector: 'alfa-historie-item-header', + templateUrl: './historie-item-header.component.html', + styleUrls: ['./historie-item-header.component.scss'], }) export class HistorieItemHeaderComponent { + @Input() headline: string; + @Input() resource: CommandResource; - @Input() headline: string; - @Input() resource: CommandResource; - - readonly commandLinkRel = CommandLinkRel; + readonly commandLinkRel = CommandLinkRel; } diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.html index bb74108604b5575c70f3e995f9e12425b6dbfbd8..a811cc064ea78f4599531a88857fc5a5682b1c97 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.html @@ -24,6 +24,10 @@ --> <alfa-expansion-panel-with-user [headline]="headline" [resource]="command"> - <p data-test-class="kommentar-text">{{ kommentar.text }}</p> - <alfa-historie-item-attachment *ngIf="kommentar.attachments" [attachments]="kommentar.attachments" data-test-class="historie-item-kommentar-attachment"></alfa-historie-item-attachment> + <p data-test-class="kommentar-text">{{ kommentar.text }}</p> + <alfa-historie-item-attachment + *ngIf="kommentar.attachments" + [attachments]="kommentar.attachments" + data-test-class="historie-item-kommentar-attachment" + ></alfa-historie-item-attachment> </alfa-expansion-panel-with-user> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.spec.ts index b2bbcd274f51199cb6862b62614f66519b506568..579c83cd2a6885639924a8baaf38d0cf116a9dda 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.spec.ts @@ -34,85 +34,83 @@ import { HistorieItemAttachmentComponent } from '../historie-item-attachment/his import { HistorieItemKommentarComponent } from './historie-item-kommentar.component'; describe('HistorieItemKommentarComponent', () => { - let component: HistorieItemKommentarComponent; - let fixture: ComponentFixture<HistorieItemKommentarComponent>; + let component: HistorieItemKommentarComponent; + let fixture: ComponentFixture<HistorieItemKommentarComponent>; - const kommentarCommand: CommandResource = { - ...createCommandResource(), - order: CommandOrder.CREATE_KOMMENTAR, - body: { item: { text: 'Beispiel text fuer einen Kommentar' } } - }; + const kommentarCommand: CommandResource = { + ...createCommandResource(), + order: CommandOrder.CREATE_KOMMENTAR, + body: { item: { text: 'Beispiel text fuer einen Kommentar' } }, + }; - const attachment: string = getDataTestClassOf('historie-item-kommentar-attachment'); + const attachment: string = getDataTestClassOf('historie-item-kommentar-attachment'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieItemKommentarComponent, - MockComponent(ExpansionPanelWithUserComponent), - MockComponent(HistorieItemAttachmentComponent) - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HistorieItemKommentarComponent, + MockComponent(ExpansionPanelWithUserComponent), + MockComponent(HistorieItemAttachmentComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemKommentarComponent); - component = fixture.componentInstance; - component.command = kommentarCommand; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemKommentarComponent); + component = fixture.componentInstance; + component.command = kommentarCommand; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should set headline for order ' + CommandOrder.CREATE_KOMMENTAR, () => { + component.command = { ...kommentarCommand, order: CommandOrder.CREATE_KOMMENTAR }; - it('should set headline for order ' + CommandOrder.CREATE_KOMMENTAR, () => { - component.command = { ...kommentarCommand, order: CommandOrder.CREATE_KOMMENTAR }; + component.ngOnInit(); - component.ngOnInit(); + expect(component.headline).toBe(`ein Kommentar hinzugefügt.`); + }); - expect(component.headline).toBe(`ein Kommentar hinzugefügt.`); - }) + it('should set headline for order' + CommandOrder.EDIT_KOMMENTAR, () => { + component.command = { ...kommentarCommand, order: CommandOrder.EDIT_KOMMENTAR }; - it('should set headline for order' + CommandOrder.EDIT_KOMMENTAR, () => { - component.command = { ...kommentarCommand, order: CommandOrder.EDIT_KOMMENTAR }; + component.ngOnInit(); - component.ngOnInit() + expect(component.headline).toBe(`ein Kommentar bearbeitet.`); + }); + }); - expect(component.headline).toBe(`ein Kommentar bearbeitet.`); - }) - }) + describe('attachments', () => { + beforeEach(() => { + component.command = createCommand(createKommentarResource()); + }); - describe('attachments', () => { + it('should hide of NOT exists', () => { + const item: KommentarResource = createKommentarResource(); + delete item['attachments']; + component.command = createCommand(item); + fixture.detectChanges(); - beforeEach(() => { - component.command = createCommand(createKommentarResource()); - }) + const attachmentElement = getElementFromFixture(fixture, attachment); - it('should hide of NOT exists', () => { - const item: KommentarResource = createKommentarResource(); - delete item['attachments']; - component.command = createCommand(item); - fixture.detectChanges(); + expect(attachmentElement).not.toBeInstanceOf(HTMLElement); + }); - const attachmentElement = getElementFromFixture(fixture, attachment); + it('should show if exists', () => { + component.command = createCommand(createKommentarResource()); + fixture.detectChanges(); - expect(attachmentElement).not.toBeInstanceOf(HTMLElement); - }) + const attachmentElement = getElementFromFixture(fixture, attachment); - it('should show if exists', () => { - component.command = createCommand(createKommentarResource()); - fixture.detectChanges(); + expect(attachmentElement).toBeInstanceOf(HTMLElement); + }); - const attachmentElement = getElementFromFixture(fixture, attachment); - - expect(attachmentElement).toBeInstanceOf(HTMLElement); - }) - - function createCommand(item: KommentarResource): CommandResource{ - return { ...createCommandResource(), order: CommandOrder.CREATE_KOMMENTAR, body: { item } }; - } - }) + function createCommand(item: KommentarResource): CommandResource { + return { ...createCommandResource(), order: CommandOrder.CREATE_KOMMENTAR, body: { item } }; + } + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.ts index e5236492308b20551e9d91ca7e342e6cc2032f7e..131ad6c0299a8170eeb910102f40aac4db431dac 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component.ts @@ -26,28 +26,27 @@ import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; @Component({ - selector: 'alfa-historie-item-kommentar', - templateUrl: './historie-item-kommentar.component.html', - styleUrls: ['./historie-item-kommentar.component.scss'], + selector: 'alfa-historie-item-kommentar', + templateUrl: './historie-item-kommentar.component.html', + styleUrls: ['./historie-item-kommentar.component.scss'], }) export class HistorieItemKommentarComponent implements OnInit { + @Input() command: CommandResource; - @Input() command: CommandResource; + headline: string; - headline: string; + readonly commandLinkRel = CommandLinkRel; - readonly commandLinkRel = CommandLinkRel; + get kommentar(): any { + return this.command.body.item; + } - get kommentar(): any { - return this.command.body.item; - } - - ngOnInit(): void { - this.headline = HISTORIE_TEXT_BY_KOMMENTAR_ORDER[this.command.order]; - } + ngOnInit(): void { + this.headline = HISTORIE_TEXT_BY_KOMMENTAR_ORDER[this.command.order]; + } } const HISTORIE_TEXT_BY_KOMMENTAR_ORDER: { [order: string]: string } = { - [CommandOrder.CREATE_KOMMENTAR]: 'ein Kommentar hinzugefügt.', - [CommandOrder.EDIT_KOMMENTAR]: 'ein Kommentar bearbeitet.' -} \ No newline at end of file + [CommandOrder.CREATE_KOMMENTAR]: 'ein Kommentar hinzugefügt.', + [CommandOrder.EDIT_KOMMENTAR]: 'ein Kommentar bearbeitet.', +}; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.html index b3c63c9f34ef4153d71c24468e20fc45311c1bed..48effc837153c6366e2d3e4c63616b6ce4f78d3d 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.html @@ -1,3 +1,3 @@ <div class="mat-expansion-panel"> - <alfa-historie-item-header [headline]="headline" [resource]="command"></alfa-historie-item-header> -</div> \ No newline at end of file + <alfa-historie-item-header [headline]="headline" [resource]="command"></alfa-historie-item-header> +</div> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.scss index c2da3a09a9604bcebb5ffbc56e496c884eb9987a..bd4f6bc887a23bad0e174ef5644e7e5ce01462d7 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.scss @@ -1 +1 @@ -@import 'expansion-panel'; \ No newline at end of file +@import 'expansion-panel'; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.spec.ts index 3385f94224343e6726434d525313d88df0e994e0..64d1b297c3988c6e33d024c76b39d859301319b8 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.spec.ts @@ -29,47 +29,50 @@ import { HistorieItemHeaderComponent } from '../historie-item-header/historie-it import { HistorieItemLoeschAnforderungComponent } from './historie-item-loesch-anforderung.component'; describe('HistorieItemLoeschAnforderungComponent', () => { - let component: HistorieItemLoeschAnforderungComponent; - let fixture: ComponentFixture<HistorieItemLoeschAnforderungComponent>; + let component: HistorieItemLoeschAnforderungComponent; + let fixture: ComponentFixture<HistorieItemLoeschAnforderungComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieItemLoeschAnforderungComponent, - MockComponent(HistorieItemHeaderComponent) - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HistorieItemLoeschAnforderungComponent, + MockComponent(HistorieItemHeaderComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent( - HistorieItemLoeschAnforderungComponent - ); - component = fixture.componentInstance; - component.command = createCommandResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemLoeschAnforderungComponent); + component = fixture.componentInstance; + component.command = createCommandResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should set headline for order VORGANG_ZUM_LOESCHEN_MARKIEREN', () => { + component.command = { + ...createCommandResource(), + order: CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN, + }; - it('should set headline for order VORGANG_ZUM_LOESCHEN_MARKIEREN', () => { - component.command = { ...createCommandResource(), order: CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN }; + component.ngOnInit(); - component.ngOnInit(); + expect(component.headline).toEqual('eine Löschanforderung gestellt.'); + }); - expect(component.headline).toEqual('eine Löschanforderung gestellt.'); - }) + it('should set headline for order LOESCH_ANFORDERUNG_ZURUECKNEHMEN', () => { + component.command = { + ...createCommandResource(), + order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN, + }; - it('should set headline for order LOESCH_ANFORDERUNG_ZURUECKNEHMEN', () => { - component.command = { ...createCommandResource(), order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN }; + component.ngOnInit(); - component.ngOnInit(); - - expect(component.headline).toEqual('die Löschanforderung zurückgenommen.'); - }) - }) + expect(component.headline).toEqual('die Löschanforderung zurückgenommen.'); + }); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.ts index a48187373e8cb3c3f5b80f68bdefbfd7bf317fce..2fdacc0ff52e1cb35ff98dd591ce2d96af34eaa1 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component.ts @@ -25,22 +25,21 @@ import { Component, Input } from '@angular/core'; import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; @Component({ - selector: 'alfa-historie-item-loesch-anforderung', - templateUrl: './historie-item-loesch-anforderung.component.html', - styleUrls: ['./historie-item-loesch-anforderung.component.scss'], + selector: 'alfa-historie-item-loesch-anforderung', + templateUrl: './historie-item-loesch-anforderung.component.html', + styleUrls: ['./historie-item-loesch-anforderung.component.scss'], }) export class HistorieItemLoeschAnforderungComponent { + @Input() command: CommandResource; - @Input() command: CommandResource; + headline: string; - headline: string; - - ngOnInit(): void { - this.headline = HISTORIE_TEXT_BY_COMMAND_ORDER[this.command.order]; - } + ngOnInit(): void { + this.headline = HISTORIE_TEXT_BY_COMMAND_ORDER[this.command.order]; + } } const HISTORIE_TEXT_BY_COMMAND_ORDER: { [order: string]: string } = { - [CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN]: 'eine Löschanforderung gestellt.', - [CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN]: 'die Löschanforderung zurückgenommen.' -} \ No newline at end of file + [CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN]: 'eine Löschanforderung gestellt.', + [CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN]: 'die Löschanforderung zurückgenommen.', +}; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.html index e767b464d95dda50eb60edb264f1940413fa7906..7dc33cc2208222ca6912bb2698b16aa0f9fb9d3f 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.html @@ -23,14 +23,29 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-expansion-panel-with-user *ngIf="postfachNachricht; else headlineOnly" [headline]="headline" [resource]="command" data-test-class="historie-item-postfach-nachricht-user-expansion-panel-with-body"> - <p data-test-class="postfach-nachricht-subject" class="subject">{{postfachNachricht.subject}}</p> - <p data-test-class="postfach-nachricht-mail-body">{{postfachNachricht.mailBody}}</p> - <alfa-historie-item-attachment *ngIf="postfachNachricht.attachments" [attachments]="postfachNachricht.attachments" data-test-class="historie-item-postfach-nachricht-attachment"></alfa-historie-item-attachment> +<alfa-expansion-panel-with-user + *ngIf="postfachNachricht; else headlineOnly" + [headline]="headline" + [resource]="command" + data-test-class="historie-item-postfach-nachricht-user-expansion-panel-with-body" +> + <p data-test-class="postfach-nachricht-subject" class="subject"> + {{ postfachNachricht.subject }} + </p> + <p data-test-class="postfach-nachricht-mail-body">{{ postfachNachricht.mailBody }}</p> + <alfa-historie-item-attachment + *ngIf="postfachNachricht.attachments" + [attachments]="postfachNachricht.attachments" + data-test-class="historie-item-postfach-nachricht-attachment" + ></alfa-historie-item-attachment> </alfa-expansion-panel-with-user> <ng-template #headlineOnly> - <div class="mat-expansion-panel"> - <alfa-historie-item-header [resource]="command" [headline]="headline" data-test-class="historie-item-postfach-nachricht-user-expansion-panel"></alfa-historie-item-header> - </div> -</ng-template> \ No newline at end of file + <div class="mat-expansion-panel"> + <alfa-historie-item-header + [resource]="command" + [headline]="headline" + data-test-class="historie-item-postfach-nachricht-user-expansion-panel" + ></alfa-historie-item-header> + </div> +</ng-template> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.scss index a329a524aa72eeeb5e5785155a9e6c9367bf3170..5f690b71e9f378c7d85cfe1d9467d460b8839b02 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.scss @@ -24,5 +24,5 @@ @import 'expansion-panel'; .subject { - font-weight: bold -} \ No newline at end of file + font-weight: bold; +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.spec.ts index 0aa2d1763fb2c8fec9b5f22f4d3ed3836fcc7377..a02c1e095179a1b51253c361fc8019aa764eb8b6 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.spec.ts @@ -35,149 +35,158 @@ import { HistorieItemHeaderComponent } from '../historie-item-header/historie-it import { HistorieItemPostfachNachrichtComponent } from './historie-item-postfach-nachricht.component'; describe('HistorieItemPostfachNachrichtComponent', () => { - let component: HistorieItemPostfachNachrichtComponent; - let fixture: ComponentFixture<HistorieItemPostfachNachrichtComponent>; + let component: HistorieItemPostfachNachrichtComponent; + let fixture: ComponentFixture<HistorieItemPostfachNachrichtComponent>; + + const item: PostfachMail = createPostfachMail(); + const postfachNachrichtCommand: CommandResource = { + ...createCommandResource(), + body: { item: item }, + }; + + const attachment: string = getDataTestClassOf('historie-item-postfach-nachricht-attachment'); + const expansionPanel: string = getDataTestClassOf( + 'historie-item-postfach-nachricht-user-expansion-panel', + ); + const mailBody: string = getDataTestClassOf('postfach-nachricht-mail-body'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HistorieItemPostfachNachrichtComponent, + MockComponent(ExpansionPanelWithUserComponent), + MockComponent(HistorieItemAttachmentComponent), + MockComponent(HistorieItemHeaderComponent), + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemPostfachNachrichtComponent); + component = fixture.componentInstance; + component.command = postfachNachrichtCommand; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should set headline for ' + CommandOrder.SEND_POSTFACH_NACHRICHT, () => { + component.command = { + ...postfachNachrichtCommand, + order: CommandOrder.SEND_POSTFACH_NACHRICHT, + }; + + component.ngOnInit(); + + expect(component.headline).toBe('eine Nachricht geschrieben.'); + }); + + it('should set headline by order' + CommandOrder.RECEIVE_POSTFACH_NACHRICHT, () => { + component.command = { + ...postfachNachrichtCommand, + order: CommandOrder.RECEIVE_POSTFACH_NACHRICHT, + }; + + component.ngOnInit(); + + expect(component.headline).toBe('eine Nachricht des Antragstellers empfangen.'); + }); + + it('should set postfach nachricht', () => { + component.getPostfachNachricht = jest.fn(); + + component.ngOnInit(); + + expect(component.getPostfachNachricht).toHaveBeenCalled(); + }); + + describe('get postfach nachricht', () => { + it('should return body if order is SEND_POSTFACH_NACHRICHT', () => { + component.command = { + ...postfachNachrichtCommand, + order: CommandOrder.SEND_POSTFACH_NACHRICHT, + }; + fixture.detectChanges(); + + const postfachNachricht = component.getPostfachNachricht(); + + expect(postfachNachricht).toEqual({ item }); + }); + + it('should return item in body if order is NOT SEND_POSTFACH_NACHRICHT', () => { + component.command = { + ...postfachNachrichtCommand, + order: CommandOrder.RECEIVE_POSTFACH_NACHRICHT, + }; + fixture.detectChanges(); + + const postfachNachricht = component.getPostfachNachricht(); + + expect(postfachNachricht).toEqual(item); + }); + }); + }); + + describe('attachments', () => { + it('should hide of NOT exists', () => { + const item: PostfachMail = createPostfachMail(); + delete item['attachments']; + component.postfachNachricht = item; + fixture.detectChanges(); + + const attachmentElement = getElementFromFixture(fixture, attachment); + + expect(attachmentElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should show if exists', () => { + component.postfachNachricht = createPostfachMail(); + fixture.detectChanges(); + + const attachmentElement = getElementFromFixture(fixture, attachment); + + expect(attachmentElement).toBeInstanceOf(HTMLElement); + }); + }); + + describe('postfach nachricht body exists', () => { + beforeEach(() => { + component.postfachNachricht = createPostfachMailResource(); + fixture.detectChanges(); + }); - const item: PostfachMail = createPostfachMail(); - const postfachNachrichtCommand: CommandResource = { ...createCommandResource(), body: { item: item } }; + it('should show postfach nachricht with body', () => { + const element = getElementFromFixture(fixture, mailBody); - const attachment: string = getDataTestClassOf('historie-item-postfach-nachricht-attachment'); - const expansionPanel: string = getDataTestClassOf('historie-item-postfach-nachricht-user-expansion-panel'); - const mailBody: string = getDataTestClassOf('postfach-nachricht-mail-body'); + expect(element).toBeInstanceOf(HTMLElement); + }); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieItemPostfachNachrichtComponent, - MockComponent(ExpansionPanelWithUserComponent), - MockComponent(HistorieItemAttachmentComponent), - MockComponent(HistorieItemHeaderComponent) - ], - }).compileComponents(); - }); + it('should hide postfach nachricht', () => { + const element = getElementFromFixture(fixture, expansionPanel); - beforeEach(() => { - fixture = TestBed.createComponent( - HistorieItemPostfachNachrichtComponent - ); - component = fixture.componentInstance; - component.command = postfachNachrichtCommand; - fixture.detectChanges(); - }); + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + describe('postfach nachricht body not exists', () => { + beforeEach(() => { + component.postfachNachricht = undefined; + fixture.detectChanges(); + }); - describe('ngOnInit', () => { + it('should show postfach nachricht', () => { + const element = getElementFromFixture(fixture, expansionPanel); - it('should set headline for ' + CommandOrder.SEND_POSTFACH_NACHRICHT, () => { - component.command = { ...postfachNachrichtCommand, order: CommandOrder.SEND_POSTFACH_NACHRICHT }; + expect(element).toBeInstanceOf(HTMLElement); + }); - component.ngOnInit(); + it('should hide postfach nachricht with body', () => { + const element = getElementFromFixture(fixture, mailBody); - expect(component.headline).toBe('eine Nachricht geschrieben.'); - }) - - it('should set headline by order' + CommandOrder.RECEIVE_POSTFACH_NACHRICHT, () => { - component.command = { ...postfachNachrichtCommand, order: CommandOrder.RECEIVE_POSTFACH_NACHRICHT }; - - component.ngOnInit(); - - expect(component.headline).toBe('eine Nachricht des Antragstellers empfangen.'); - }) - - it('should set postfach nachricht', () => { - component.getPostfachNachricht = jest.fn(); - - component.ngOnInit(); - - expect(component.getPostfachNachricht).toHaveBeenCalled(); - }) - - describe('get postfach nachricht', () => { - - it('should return body if order is SEND_POSTFACH_NACHRICHT', () => { - component.command = { ...postfachNachrichtCommand, order: CommandOrder.SEND_POSTFACH_NACHRICHT }; - fixture.detectChanges(); - - const postfachNachricht = component.getPostfachNachricht(); - - expect(postfachNachricht).toEqual({ item }); - }) - - it('should return item in body if order is NOT SEND_POSTFACH_NACHRICHT', () => { - component.command = { ...postfachNachrichtCommand, order: CommandOrder.RECEIVE_POSTFACH_NACHRICHT }; - fixture.detectChanges(); - - const postfachNachricht = component.getPostfachNachricht(); - - expect(postfachNachricht).toEqual(item); - }) - }) - }) - - describe('attachments', () => { - - it('should hide of NOT exists', () => { - const item: PostfachMail = createPostfachMail(); - delete item['attachments']; - component.postfachNachricht = item; - fixture.detectChanges(); - - const attachmentElement = getElementFromFixture(fixture, attachment); - - expect(attachmentElement).not.toBeInstanceOf(HTMLElement); - }) - - it('should show if exists', () => { - component.postfachNachricht = createPostfachMail(); - fixture.detectChanges(); - - const attachmentElement = getElementFromFixture(fixture, attachment); - - expect(attachmentElement).toBeInstanceOf(HTMLElement); - }) - }) - - describe('postfach nachricht body exists', () => { - - beforeEach(() => { - component.postfachNachricht = createPostfachMailResource(); - fixture.detectChanges(); - }) - - it('should show postfach nachricht with body', () => { - const element = getElementFromFixture(fixture, mailBody); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should hide postfach nachricht', () => { - const element = getElementFromFixture(fixture, expansionPanel); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - - describe('postfach nachricht body not exists', () => { - - beforeEach(() => { - component.postfachNachricht = undefined; - fixture.detectChanges(); - }) - - it('should show postfach nachricht', () => { - const element = getElementFromFixture(fixture, expansionPanel); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should hide postfach nachricht with body', () => { - const element = getElementFromFixture(fixture, mailBody); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.ts index 52d48882defb39e6c8c40e290ddbac14d84b23f4..5043d10aeca74e8fbc090b9e8d99a69842eabd17 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component.ts @@ -26,32 +26,31 @@ import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; import { PostfachMail } from '@alfa-client/postfach-shared'; @Component({ - selector: 'alfa-historie-item-postfach-nachricht', - templateUrl: './historie-item-postfach-nachricht.component.html', - styleUrls: ['./historie-item-postfach-nachricht.component.scss'], + selector: 'alfa-historie-item-postfach-nachricht', + templateUrl: './historie-item-postfach-nachricht.component.html', + styleUrls: ['./historie-item-postfach-nachricht.component.scss'], }) export class HistorieItemPostfachNachrichtComponent { + @Input() command: CommandResource; - @Input() command: CommandResource; + headline: string; + postfachNachricht: PostfachMail; - headline: string; - postfachNachricht: PostfachMail; + ngOnInit(): void { + this.headline = HISTORIE_TEXT_BY_POSTFACH_NACHRICHT_ORDER[this.command.order]; + this.postfachNachricht = this.getPostfachNachricht(); + } - ngOnInit(): void { - this.headline = HISTORIE_TEXT_BY_POSTFACH_NACHRICHT_ORDER[this.command.order]; - this.postfachNachricht = this.getPostfachNachricht(); - } - - getPostfachNachricht(): PostfachMail { - if (this.command.order == CommandOrder.SEND_POSTFACH_NACHRICHT) { - return this.command.body; - } - return this.command.body.item; - } + getPostfachNachricht(): PostfachMail { + if (this.command.order == CommandOrder.SEND_POSTFACH_NACHRICHT) { + return this.command.body; + } + return this.command.body.item; + } } const HISTORIE_TEXT_BY_POSTFACH_NACHRICHT_ORDER: { [order: string]: string } = { - [CommandOrder.SEND_POSTFACH_NACHRICHT]: 'eine Nachricht geschrieben.', - [CommandOrder.RECEIVE_POSTFACH_NACHRICHT]: 'eine Nachricht des Antragstellers empfangen.', - [CommandOrder.RESEND_POSTFACH_NACHRICHT]: 'eine Nachricht erneut versendet.' -} \ No newline at end of file + [CommandOrder.SEND_POSTFACH_NACHRICHT]: 'eine Nachricht geschrieben.', + [CommandOrder.RECEIVE_POSTFACH_NACHRICHT]: 'eine Nachricht des Antragstellers empfangen.', + [CommandOrder.RESEND_POSTFACH_NACHRICHT]: 'eine Nachricht erneut versendet.', +}; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.html index a549a3aeaa109fb335c040df9ea23344f73e164d..3e75fa03e9491768c726ae25d6282e9c2a603a3f 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.html @@ -24,5 +24,8 @@ --> <div class="mat-expansion-panel"> - <alfa-historie-item-header [headline]="headline" [resource]="resource"></alfa-historie-item-header> + <alfa-historie-item-header + [headline]="headline" + [resource]="resource" + ></alfa-historie-item-header> </div> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.scss index c85698e574b5c212b494a3951d656e50dbf38b6c..d6238211bb493815e84e9e0c249c4cb0acc816e7 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.scss @@ -21,4 +21,4 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -@import 'expansion-panel'; \ No newline at end of file +@import 'expansion-panel'; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.spec.ts index 864af95137c50a06e9bcf35de39a8c47d41baf4a..959f94a173fd4c62c181a84e9bc887564c4dbe9f 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.spec.ts @@ -27,25 +27,22 @@ import { HistorieItemHeaderComponent } from '../historie-item-header/historie-it import { HistorieItemUnknownComponent } from './historie-item-unknown.component'; describe('HistorieItemUnknownComponent', () => { - let component: HistorieItemUnknownComponent; - let fixture: ComponentFixture<HistorieItemUnknownComponent>; + let component: HistorieItemUnknownComponent; + let fixture: ComponentFixture<HistorieItemUnknownComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieItemUnknownComponent, - MockComponent(HistorieItemHeaderComponent) - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HistorieItemUnknownComponent, MockComponent(HistorieItemHeaderComponent)], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemUnknownComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemUnknownComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.ts index 705d276e0cc840d96524125bf3c869afc467d783..db66fa106a340238b7ed63a15bee66cad2805a89 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-unknown/historie-item-unknown.component.ts @@ -25,13 +25,11 @@ import { Component, Input } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; @Component({ - selector: 'alfa-historie-item-unknown', - templateUrl: './historie-item-unknown.component.html', - styleUrls: ['./historie-item-unknown.component.scss'], + selector: 'alfa-historie-item-unknown', + templateUrl: './historie-item-unknown.component.html', + styleUrls: ['./historie-item-unknown.component.scss'], }) export class HistorieItemUnknownComponent { - - @Input() headline: string; - @Input() resource: CommandResource; - + @Input() headline: string; + @Input() resource: CommandResource; } diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.html index c823d77eea64cdfc748a9311f267dab9544b2044..f549c14431c204fda49d5f890f56b224c601a4b9 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.html @@ -24,5 +24,8 @@ --> <div class="mat-expansion-panel"> - <p data-test-id="historie-vorgang-created-at">Der Vorgang wurde am {{ vorgangWithEingang.createdAt | formatDateWithTimePipe:false }} erstellt.</p> -</div> \ No newline at end of file + <p data-test-id="historie-vorgang-created-at"> + Der Vorgang wurde am + {{ vorgangWithEingang.createdAt | formatDateWithTimePipe: false }} erstellt. + </p> +</div> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.scss index 13ffdbdf74b14c777722e352dba64d724a0a2647..f4e6e49e807966d56e3f9beae6b8a010ba4ed9a7 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.scss @@ -25,20 +25,20 @@ @import 'expansion-panel'; :host { - border-bottom: 1px solid $greyLight; - display: block; - margin-top: 0.5rem; - min-height: 44px; - font-size: 14px; + border-bottom: 1px solid $greyLight; + display: block; + margin-top: 0.5rem; + min-height: 44px; + font-size: 14px; } p { - margin: 0; + margin: 0; } .mat-expansion-panel { - padding-left: 1px; + padding-left: 1px; } :host-context(.dark) .mat-expansion-panel { - padding-left: 6px; -} \ No newline at end of file + padding-left: 6px; +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.spec.ts index bcaad34ffc1aac33cde7d7f8ec3da12d06bddcb6..3106ccf52bd671e01370ede71473e7561a012a91 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.spec.ts @@ -34,42 +34,38 @@ import { HistorieItemVorgangCreatedComponent } from './historie-item-vorgang-cre registerLocaleData(localeDe); describe('HistorieItemVorgangCreatedComponent', () => { - let component: HistorieItemVorgangCreatedComponent; - let fixture: ComponentFixture<HistorieItemVorgangCreatedComponent>; + let component: HistorieItemVorgangCreatedComponent; + let fixture: ComponentFixture<HistorieItemVorgangCreatedComponent>; - const createdAtElement: string = getDataTestIdOf('historie-vorgang-created-at'); + const createdAtElement: string = getDataTestIdOf('historie-vorgang-created-at'); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - FormatDateWithTimePipe, - HistorieItemVorgangCreatedComponent - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [FormatDateWithTimePipe, HistorieItemVorgangCreatedComponent], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemVorgangCreatedComponent); - component = fixture.componentInstance; - component.vorgangWithEingang = vorgangWithEingang; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemVorgangCreatedComponent); + component = fixture.componentInstance; + component.vorgangWithEingang = vorgangWithEingang; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('on vorgang', () => { + describe('on vorgang', () => { + it('should have Historie list', () => { + component.vorgangWithEingang = vorgangWithEingang; + fixture.detectChanges(); - it('should have Historie list', () => { - component.vorgangWithEingang = vorgangWithEingang; - fixture.detectChanges(); + const element = getElementFromFixture(fixture, createdAtElement); - const element = getElementFromFixture(fixture, createdAtElement); - - expect(element).toBeInstanceOf(HTMLElement); - }) - }) -}); \ No newline at end of file + expect(element).toBeInstanceOf(HTMLElement); + }); + }); +}); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.ts index a8b32184ec085a91c4fc3d1342df0f5cecb2f1af..d338924050c69d1395a185e0ce84d6564134824c 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component.ts @@ -25,11 +25,10 @@ import { Component, Input } from '@angular/core'; import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-historie-item-vorgang-created', - templateUrl: './historie-item-vorgang-created.component.html', - styleUrls: ['./historie-item-vorgang-created.component.scss'], + selector: 'alfa-historie-item-vorgang-created', + templateUrl: './historie-item-vorgang-created.component.html', + styleUrls: ['./historie-item-vorgang-created.component.scss'], }) export class HistorieItemVorgangCreatedComponent { - - @Input() vorgangWithEingang: VorgangWithEingangResource; + @Input() vorgangWithEingang: VorgangWithEingangResource; } diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.html index 802bc1a8cd25384b0063d0c35dc860f455e03d68..e7f1fd7274f6913a555d581485e47b0017604641 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.html @@ -24,5 +24,5 @@ --> <div class="mat-expansion-panel"> - <alfa-historie-item-header [headline]="headline" [resource]="command"></alfa-historie-item-header> -</div> \ No newline at end of file + <alfa-historie-item-header [headline]="headline" [resource]="command"></alfa-historie-item-header> +</div> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.scss index c85698e574b5c212b494a3951d656e50dbf38b6c..d6238211bb493815e84e9e0c249c4cb0acc816e7 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.scss @@ -21,4 +21,4 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -@import 'expansion-panel'; \ No newline at end of file +@import 'expansion-panel'; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.spec.ts index 2932d4386d106d6d970ab4a5ca27902eae403fe1..9ad09b587b9aa6398c3d1dfdcffd0cf87aa615e0 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.spec.ts @@ -30,57 +30,68 @@ import { HistorieItemHeaderComponent } from '../historie-item-header/historie-it import { HistorieItemVorgangStatusComponent } from './historie-item-vorgang-status.component'; describe('HistorieItemVorgangStatusComponent', () => { - let component: HistorieItemVorgangStatusComponent; - let fixture: ComponentFixture<HistorieItemVorgangStatusComponent>; + let component: HistorieItemVorgangStatusComponent; + let fixture: ComponentFixture<HistorieItemVorgangStatusComponent>; - const vorgangStatusCommand: CommandResource = { - ...createCommandResource(), - order: CommandOrder.VORGANG_ANNEHMEN - }; + const vorgangStatusCommand: CommandResource = { + ...createCommandResource(), + order: CommandOrder.VORGANG_ANNEHMEN, + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieItemVorgangStatusComponent, - MockComponent(HistorieItemHeaderComponent) - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HistorieItemVorgangStatusComponent, + MockComponent(HistorieItemHeaderComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemVorgangStatusComponent); - component = fixture.componentInstance; - component.command = vorgangStatusCommand; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemVorgangStatusComponent); + component = fixture.componentInstance; + component.command = vorgangStatusCommand; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + const allVorgangStatusCommandOrder: CommandOrder[] = [ + CommandOrder.VORGANG_ANNEHMEN, + CommandOrder.VORGANG_VERWERFEN, + CommandOrder.VORGANG_ZURUECKHOLEN, + CommandOrder.VORGANG_BEARBEITEN, + CommandOrder.VORGANG_BESCHEIDEN, + CommandOrder.VORGANG_ZURUECKSTELLEN, + CommandOrder.VORGANG_ABSCHLIESSEN, + CommandOrder.VORGANG_WIEDEREROEFFNEN, + ]; - const allVorgangStatusCommandOrder: CommandOrder[] = [CommandOrder.VORGANG_ANNEHMEN, CommandOrder.VORGANG_VERWERFEN, CommandOrder.VORGANG_ZURUECKHOLEN, - CommandOrder.VORGANG_BEARBEITEN, CommandOrder.VORGANG_BESCHEIDEN, CommandOrder.VORGANG_ZURUECKSTELLEN, - CommandOrder.VORGANG_ABSCHLIESSEN, CommandOrder.VORGANG_WIEDEREROEFFNEN] + const vorgangStatusLabelByCommandOrder = { + [CommandOrder.VORGANG_ANNEHMEN]: VorgangStatusLabel.ANGENOMMEN, + [CommandOrder.VORGANG_VERWERFEN]: VorgangStatusLabel.VERWORFEN, + [CommandOrder.VORGANG_ZURUECKHOLEN]: VorgangStatusLabel.NEU, + [CommandOrder.VORGANG_BEARBEITEN]: VorgangStatusLabel.IN_BEARBEITUNG, + [CommandOrder.VORGANG_BESCHEIDEN]: VorgangStatusLabel.BESCHIEDEN, + [CommandOrder.VORGANG_ZURUECKSTELLEN]: VorgangStatusLabel.ANGENOMMEN, + [CommandOrder.VORGANG_ABSCHLIESSEN]: VorgangStatusLabel.ABGESCHLOSSEN, + [CommandOrder.VORGANG_WIEDEREROEFFNEN]: VorgangStatusLabel.IN_BEARBEITUNG, + }; - const vorgangStatusLabelByCommandOrder = { - [CommandOrder.VORGANG_ANNEHMEN]: VorgangStatusLabel.ANGENOMMEN, - [CommandOrder.VORGANG_VERWERFEN]: VorgangStatusLabel.VERWORFEN, - [CommandOrder.VORGANG_ZURUECKHOLEN]: VorgangStatusLabel.NEU, - [CommandOrder.VORGANG_BEARBEITEN]: VorgangStatusLabel.IN_BEARBEITUNG, - [CommandOrder.VORGANG_BESCHEIDEN]: VorgangStatusLabel.BESCHIEDEN, - [CommandOrder.VORGANG_ZURUECKSTELLEN]: VorgangStatusLabel.ANGENOMMEN, - [CommandOrder.VORGANG_ABSCHLIESSEN]: VorgangStatusLabel.ABGESCHLOSSEN, - [CommandOrder.VORGANG_WIEDEREROEFFNEN]: VorgangStatusLabel.IN_BEARBEITUNG, - } + it.each(allVorgangStatusCommandOrder)( + 'should set headline for order %s', + (order: CommandOrder) => { + component.command = { ...vorgangStatusCommand, order }; - it.each(allVorgangStatusCommandOrder)('should set headline for order %s', (order: CommandOrder) => { - component.command = { ...vorgangStatusCommand, order }; + component.ngOnInit(); - component.ngOnInit(); - - expect(component.headline).toBe(`den Vorgang in den Status ${vorgangStatusLabelByCommandOrder[order]} versetzt.`); - }) - }) -}); \ No newline at end of file + expect(component.headline).toBe( + `den Vorgang in den Status ${vorgangStatusLabelByCommandOrder[order]} versetzt.`, + ); + }, + ); + }); +}); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.ts index 9e0b2f5034a39484a3a29bcb51b33c5247301dba..31aec4cd02f989a52efcb735be7eb1fd08e19ee8 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-vorgang-status/historie-item-vorgang-status.component.ts @@ -25,29 +25,28 @@ import { Component, Input, OnInit } from '@angular/core'; import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; @Component({ - selector: 'alfa-historie-item-vorgang-status', - templateUrl: './historie-item-vorgang-status.component.html', - styleUrls: ['./historie-item-vorgang-status.component.scss'], + selector: 'alfa-historie-item-vorgang-status', + templateUrl: './historie-item-vorgang-status.component.html', + styleUrls: ['./historie-item-vorgang-status.component.scss'], }) export class HistorieItemVorgangStatusComponent implements OnInit { + @Input() command: CommandResource; - @Input() command: CommandResource; + headline: string; - headline: string; - - ngOnInit(): void { - this.headline = HISTORIE_TEXT_BY_VORGANG_STATUS_ORDER[this.command.order]; - } + ngOnInit(): void { + this.headline = HISTORIE_TEXT_BY_VORGANG_STATUS_ORDER[this.command.order]; + } } const HISTORIE_TEXT_BY_VORGANG_STATUS_ORDER: { [order: string]: string } = { - [CommandOrder.VORGANG_ANNEHMEN]: 'den Vorgang in den Status Angenommen versetzt.', - [CommandOrder.VORGANG_VERWERFEN]: 'den Vorgang in den Status Verworfen versetzt.', - [CommandOrder.VORGANG_ZURUECKHOLEN]: 'den Vorgang in den Status Neu versetzt.', - [CommandOrder.VORGANG_BEARBEITEN]: 'den Vorgang in den Status In Bearbeitung versetzt.', - [CommandOrder.VORGANG_BESCHEIDEN]: 'den Vorgang in den Status Beschieden versetzt.', - [CommandOrder.VORGANG_ZURUECKSTELLEN]: 'den Vorgang in den Status Angenommen versetzt.', - [CommandOrder.VORGANG_ABSCHLIESSEN]: 'den Vorgang in den Status Abgeschlossen versetzt.', - [CommandOrder.VORGANG_WIEDEREROEFFNEN]: 'den Vorgang in den Status In Bearbeitung versetzt.', - [CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN]: 'eine Löschanforderung gestellt.' -} + [CommandOrder.VORGANG_ANNEHMEN]: 'den Vorgang in den Status Angenommen versetzt.', + [CommandOrder.VORGANG_VERWERFEN]: 'den Vorgang in den Status Verworfen versetzt.', + [CommandOrder.VORGANG_ZURUECKHOLEN]: 'den Vorgang in den Status Neu versetzt.', + [CommandOrder.VORGANG_BEARBEITEN]: 'den Vorgang in den Status In Bearbeitung versetzt.', + [CommandOrder.VORGANG_BESCHEIDEN]: 'den Vorgang in den Status Beschieden versetzt.', + [CommandOrder.VORGANG_ZURUECKSTELLEN]: 'den Vorgang in den Status Angenommen versetzt.', + [CommandOrder.VORGANG_ABSCHLIESSEN]: 'den Vorgang in den Status Abgeschlossen versetzt.', + [CommandOrder.VORGANG_WIEDEREROEFFNEN]: 'den Vorgang in den Status In Bearbeitung versetzt.', + [CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN]: 'eine Löschanforderung gestellt.', +}; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.html index 111557cc8b06fa694c868d73b6b985a9bc0558d4..3b31c58fe7da199534ef3c41971f487e73eae069 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.html @@ -23,4 +23,4 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<p data-test-class="wiedervorlage-status">{{text}}</p> \ No newline at end of file +<p data-test-class="wiedervorlage-status">{{ text }}</p> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.spec.ts index 7ad68166508761e2e5f1a532da8b328d4d764849..bd67e2ea618327107d0dfa0b4a8ee63dcc6f6b90 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.spec.ts @@ -25,39 +25,36 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HistorieItemWiedervorlageStatusComponent } from './historie-item-wiedervorlage-status.component'; describe('HistorieItemWiedervorlageStatusComponent', () => { - let component: HistorieItemWiedervorlageStatusComponent; - let fixture: ComponentFixture<HistorieItemWiedervorlageStatusComponent>; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [HistorieItemWiedervorlageStatusComponent], - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent( - HistorieItemWiedervorlageStatusComponent - ); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('set status text for "done" value', () => { - - it('should return "offen" on false', () => { - component.done = 'false'; - - expect(component.text).toBe('offen'); - }) - - it('should return "geschlossen" on true', () => { - component.done = 'true'; - - expect(component.text).toBe('geschlossen'); - }) - }) + let component: HistorieItemWiedervorlageStatusComponent; + let fixture: ComponentFixture<HistorieItemWiedervorlageStatusComponent>; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HistorieItemWiedervorlageStatusComponent], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemWiedervorlageStatusComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('set status text for "done" value', () => { + it('should return "offen" on false', () => { + component.done = 'false'; + + expect(component.text).toBe('offen'); + }); + + it('should return "geschlossen" on true', () => { + component.done = 'true'; + + expect(component.text).toBe('geschlossen'); + }); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.ts index 71daca14857718d316c88c4af8905d40392e870c..27ec925e4a9e6535b174fd63699e96a03218141c 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage-status/historie-item-wiedervorlage-status.component.ts @@ -24,16 +24,15 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'alfa-historie-item-wiedervorlage-status', - templateUrl: './historie-item-wiedervorlage-status.component.html', - styleUrls: ['./historie-item-wiedervorlage-status.component.scss'], + selector: 'alfa-historie-item-wiedervorlage-status', + templateUrl: './historie-item-wiedervorlage-status.component.html', + styleUrls: ['./historie-item-wiedervorlage-status.component.scss'], }) export class HistorieItemWiedervorlageStatusComponent { + @Input() + public set done(done: string) { + this.text = Boolean(JSON.parse(done)) ? 'geschlossen' : 'offen'; + } - @Input() - public set done(done: string) { - this.text = Boolean(JSON.parse(done)) ? 'geschlossen' : 'offen'; - } - - text: string; + text: string; } diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.html index 379847055c85616a51fe5137628021a83dd35923..960350bac7e370b067988c069a699abf13aa19f8 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.html @@ -23,14 +23,32 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-expansion-panel-with-user *ngIf="hasBody; else headlineOnly" [headline]="headline" [resource]="command" data-test-class="historie-item-wiedervorlage-user-expansion-panel"> - <alfa-historie-item-wiedervorlage-status [done]="wiedervorlage.done"></alfa-historie-item-wiedervorlage-status> - <p><span class="betreff" data-test-class="wiedervorlage-betreff">{{wiedervorlage.betreff}}</span>, {{wiedervorlage.frist | formatToPrettyDate}}</p> - <p data-test-class="wiedervorlage-beschreibung">{{wiedervorlage.beschreibung}}</p> - <alfa-historie-item-attachment *ngIf="wiedervorlage.attachments" [attachments]="wiedervorlage.attachments" data-test-class="historie-item-wiedervorlage-attachment"></alfa-historie-item-attachment> +<alfa-expansion-panel-with-user + *ngIf="hasBody; else headlineOnly" + [headline]="headline" + [resource]="command" + data-test-class="historie-item-wiedervorlage-user-expansion-panel" +> + <alfa-historie-item-wiedervorlage-status + [done]="wiedervorlage.done" + ></alfa-historie-item-wiedervorlage-status> + <p> + <span class="betreff" data-test-class="wiedervorlage-betreff">{{ wiedervorlage.betreff }}</span + >, {{ wiedervorlage.frist | formatToPrettyDate }} + </p> + <p data-test-class="wiedervorlage-beschreibung">{{ wiedervorlage.beschreibung }}</p> + <alfa-historie-item-attachment + *ngIf="wiedervorlage.attachments" + [attachments]="wiedervorlage.attachments" + data-test-class="historie-item-wiedervorlage-attachment" + ></alfa-historie-item-attachment> </alfa-expansion-panel-with-user> <ng-template #headlineOnly> - <div class="mat-expansion-panel"> - <alfa-historie-item-header [headline]="headline" [resource]="command" data-test-class="historie-item-wiedervorlage-header"></alfa-historie-item-header> - </div> -</ng-template> \ No newline at end of file + <div class="mat-expansion-panel"> + <alfa-historie-item-header + [headline]="headline" + [resource]="command" + data-test-class="historie-item-wiedervorlage-header" + ></alfa-historie-item-header> + </div> +</ng-template> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.scss index bdd65401afadc7fff678b48f8d12431050f47127..2e02fed5e8272fa5465e71bf7e5d30d25ac2aee1 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.scss @@ -24,5 +24,5 @@ @import 'expansion-panel'; .betreff { - font-weight: bold -} \ No newline at end of file + font-weight: bold; +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.spec.ts index f0aaaa3a9a58e2602a5cba592b35ed199ac2b1cf..8612ce23171cc33c5ee7f457dc54aca7b5e540a1 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.spec.ts @@ -40,188 +40,211 @@ import { HistorieItemWiedervorlageComponent } from './historie-item-wiedervorlag registerLocaleData(localeDe); describe('HistorieItemWiedervorlageComponent', () => { - let component: HistorieItemWiedervorlageComponent; - let fixture: ComponentFixture<HistorieItemWiedervorlageComponent>; - - const wiedervorlageCommand: CommandResource = { - ...createCommandResource(), - order: CommandOrder.CREATE_WIEDERVORLAGE, - body: { - item: { ...createWiedervorlageResource() } - } - }; - - const userExpansionPanel: string = getDataTestClassOf('historie-item-wiedervorlage-user-expansion-panel'); - const itemHeadline: string = getDataTestClassOf('historie-item-wiedervorlage-header'); - const attachment: string = getDataTestClassOf('historie-item-wiedervorlage-attachment'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - FormatToPrettyDatePipe, - HistorieItemWiedervorlageComponent, - MockComponent(HistorieItemHeaderComponent), - MockComponent(ExpansionPanelWithUserComponent), - MockComponent(HistorieItemWiedervorlageStatusComponent), - MockComponent(HistorieItemAttachmentComponent) - ], - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(HistorieItemWiedervorlageComponent); - component = fixture.componentInstance; - component.command = wiedervorlageCommand; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should set headline for ' + CommandOrder.CREATE_WIEDERVORLAGE, () => { - component.command = { ...wiedervorlageCommand, order: CommandOrder.CREATE_WIEDERVORLAGE }; - - component.ngOnInit(); - - expect(component.headline).toBe('eine Wiedervorlage hinzugefügt.'); - }) - - it('should set headline by %s order' + CommandOrder.EDIT_WIEDERVORLAGE, () => { - component.command = { ...wiedervorlageCommand, order: CommandOrder.EDIT_WIEDERVORLAGE }; - - component.ngOnInit(); - - expect(component.headline).toBe('eine Wiedervorlage bearbeitet.'); - }) - - it('should set headline by %s order' + CommandOrder.WIEDERVORLAGE_ERLEDIGEN, () => { - component.command = { ...wiedervorlageCommand, order: CommandOrder.WIEDERVORLAGE_ERLEDIGEN }; - - component.ngOnInit(); - - expect(component.headline).toBe('eine Wiedervorlage als erledigt markiert.'); - }) - - it('should set headline by %s order' + CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN, () => { - component.command = { ...wiedervorlageCommand, order: CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN }; - - component.ngOnInit(); - - expect(component.headline).toBe('eine Wiedervorlage als offen markiert.'); - }) - }) - - describe('has item body', () => { - - it.each([CommandOrder.WIEDERVORLAGE_ERLEDIGEN, CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN])('should return false on order %s', (order: CommandOrder) => { - component.command = { ...createCommandResource(), order }; - - const hasItemBody: boolean = component.hasItemBody(); - - expect(hasItemBody).toBeFalsy(); - }) - - it.each([CommandOrder.CREATE_WIEDERVORLAGE, CommandOrder.EDIT_WIEDERVORLAGE])('should return true on order %s', (order: CommandOrder) => { - component.command = { ...createCommandResource(), order }; - - const hasItemBody: boolean = component.hasItemBody(); - - expect(hasItemBody).toBeTruthy(); - }) - }) - - describe('show item body', () => { - - describe('on create/edit order', () => { - - beforeEach(() => { - component.command = { ...createCommandResource(), order: CommandOrder.CREATE_WIEDERVORLAGE, body: { item: createWiedervorlageResource() } }; - }) - - it('should show expansion panel', () => { - component.ngOnInit(); - fixture.detectChanges(); - - const userPanel = getElementFromFixture(fixture, userExpansionPanel); - expect(userPanel).toBeInstanceOf(HTMLElement); - }) - it('should hide header only', () => { - component.ngOnInit(); - fixture.detectChanges(); - - const userPanel = getElementFromFixture(fixture, itemHeadline); - expect(userPanel).not.toBeInstanceOf(HTMLElement); - }) - - describe('attachments', () => { - - it('should hide of NOT exists', () => { - const item = createWiedervorlageResource(); - delete item['attachments']; - component.command = { ...createCommandResource(), order: CommandOrder.CREATE_WIEDERVORLAGE, body: { item } }; - fixture.detectChanges(); - - const attachmentElement = getElementFromFixture(fixture, attachment); - - expect(attachmentElement).not.toBeInstanceOf(HTMLElement); - }) - - it('should show if exists', () => { - component.command = { ...createCommandResource(), order: CommandOrder.CREATE_WIEDERVORLAGE, body: { item: { ...createWiedervorlageResource(), attachment: '' } } }; - fixture.detectChanges(); - - const attachmentElement = getElementFromFixture(fixture, attachment); - - expect(attachmentElement).toBeInstanceOf(HTMLElement); - }) - }) - }) - - describe('on erledigen/wiedereroeffnen order', () => { - - beforeEach(() => { - component.command = { ...createCommandResource(), order: CommandOrder.WIEDERVORLAGE_ERLEDIGEN, body: { item: createWiedervorlageResource() } }; - }) - - it('should hide expansion panel', () => { - component.ngOnInit(); - fixture.detectChanges(); - - const userPanel = getElementFromFixture(fixture, userExpansionPanel); - expect(userPanel).not.toBeInstanceOf(HTMLElement); - }) - it('should show header only', () => { - component.ngOnInit(); - fixture.detectChanges(); - - const userPanel = getElementFromFixture(fixture, itemHeadline); - expect(userPanel).toBeInstanceOf(HTMLElement); - }) - }) - - describe('on non body order', () => { - - beforeEach(() => { - component.command = { ...createCommandResource(), order: CommandOrder.WIEDERVORLAGE_ERLEDIGEN }; - }) - - it('should hide expansion panel', () => { - component.ngOnInit(); - fixture.detectChanges(); - - const userPanel = getElementFromFixture(fixture, userExpansionPanel); - expect(userPanel).not.toBeInstanceOf(HTMLElement); - }) - it('should show header only', () => { - component.ngOnInit(); - fixture.detectChanges(); - - const userPanel = getElementFromFixture(fixture, itemHeadline); - expect(userPanel).toBeInstanceOf(HTMLElement); - }) - }) - }) + let component: HistorieItemWiedervorlageComponent; + let fixture: ComponentFixture<HistorieItemWiedervorlageComponent>; + + const wiedervorlageCommand: CommandResource = { + ...createCommandResource(), + order: CommandOrder.CREATE_WIEDERVORLAGE, + body: { + item: { ...createWiedervorlageResource() }, + }, + }; + + const userExpansionPanel: string = getDataTestClassOf( + 'historie-item-wiedervorlage-user-expansion-panel', + ); + const itemHeadline: string = getDataTestClassOf('historie-item-wiedervorlage-header'); + const attachment: string = getDataTestClassOf('historie-item-wiedervorlage-attachment'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + FormatToPrettyDatePipe, + HistorieItemWiedervorlageComponent, + MockComponent(HistorieItemHeaderComponent), + MockComponent(ExpansionPanelWithUserComponent), + MockComponent(HistorieItemWiedervorlageStatusComponent), + MockComponent(HistorieItemAttachmentComponent), + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HistorieItemWiedervorlageComponent); + component = fixture.componentInstance; + component.command = wiedervorlageCommand; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should set headline for ' + CommandOrder.CREATE_WIEDERVORLAGE, () => { + component.command = { ...wiedervorlageCommand, order: CommandOrder.CREATE_WIEDERVORLAGE }; + + component.ngOnInit(); + + expect(component.headline).toBe('eine Wiedervorlage hinzugefügt.'); + }); + + it('should set headline by %s order' + CommandOrder.EDIT_WIEDERVORLAGE, () => { + component.command = { ...wiedervorlageCommand, order: CommandOrder.EDIT_WIEDERVORLAGE }; + + component.ngOnInit(); + + expect(component.headline).toBe('eine Wiedervorlage bearbeitet.'); + }); + + it('should set headline by %s order' + CommandOrder.WIEDERVORLAGE_ERLEDIGEN, () => { + component.command = { ...wiedervorlageCommand, order: CommandOrder.WIEDERVORLAGE_ERLEDIGEN }; + + component.ngOnInit(); + + expect(component.headline).toBe('eine Wiedervorlage als erledigt markiert.'); + }); + + it('should set headline by %s order' + CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN, () => { + component.command = { + ...wiedervorlageCommand, + order: CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN, + }; + + component.ngOnInit(); + + expect(component.headline).toBe('eine Wiedervorlage als offen markiert.'); + }); + }); + + describe('has item body', () => { + it.each([CommandOrder.WIEDERVORLAGE_ERLEDIGEN, CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN])( + 'should return false on order %s', + (order: CommandOrder) => { + component.command = { ...createCommandResource(), order }; + + const hasItemBody: boolean = component.hasItemBody(); + + expect(hasItemBody).toBeFalsy(); + }, + ); + + it.each([CommandOrder.CREATE_WIEDERVORLAGE, CommandOrder.EDIT_WIEDERVORLAGE])( + 'should return true on order %s', + (order: CommandOrder) => { + component.command = { ...createCommandResource(), order }; + + const hasItemBody: boolean = component.hasItemBody(); + + expect(hasItemBody).toBeTruthy(); + }, + ); + }); + + describe('show item body', () => { + describe('on create/edit order', () => { + beforeEach(() => { + component.command = { + ...createCommandResource(), + order: CommandOrder.CREATE_WIEDERVORLAGE, + body: { item: createWiedervorlageResource() }, + }; + }); + + it('should show expansion panel', () => { + component.ngOnInit(); + fixture.detectChanges(); + + const userPanel = getElementFromFixture(fixture, userExpansionPanel); + expect(userPanel).toBeInstanceOf(HTMLElement); + }); + it('should hide header only', () => { + component.ngOnInit(); + fixture.detectChanges(); + + const userPanel = getElementFromFixture(fixture, itemHeadline); + expect(userPanel).not.toBeInstanceOf(HTMLElement); + }); + + describe('attachments', () => { + it('should hide of NOT exists', () => { + const item = createWiedervorlageResource(); + delete item['attachments']; + component.command = { + ...createCommandResource(), + order: CommandOrder.CREATE_WIEDERVORLAGE, + body: { item }, + }; + fixture.detectChanges(); + + const attachmentElement = getElementFromFixture(fixture, attachment); + + expect(attachmentElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should show if exists', () => { + component.command = { + ...createCommandResource(), + order: CommandOrder.CREATE_WIEDERVORLAGE, + body: { item: { ...createWiedervorlageResource(), attachment: '' } }, + }; + fixture.detectChanges(); + + const attachmentElement = getElementFromFixture(fixture, attachment); + + expect(attachmentElement).toBeInstanceOf(HTMLElement); + }); + }); + }); + + describe('on erledigen/wiedereroeffnen order', () => { + beforeEach(() => { + component.command = { + ...createCommandResource(), + order: CommandOrder.WIEDERVORLAGE_ERLEDIGEN, + body: { item: createWiedervorlageResource() }, + }; + }); + + it('should hide expansion panel', () => { + component.ngOnInit(); + fixture.detectChanges(); + + const userPanel = getElementFromFixture(fixture, userExpansionPanel); + expect(userPanel).not.toBeInstanceOf(HTMLElement); + }); + it('should show header only', () => { + component.ngOnInit(); + fixture.detectChanges(); + + const userPanel = getElementFromFixture(fixture, itemHeadline); + expect(userPanel).toBeInstanceOf(HTMLElement); + }); + }); + + describe('on non body order', () => { + beforeEach(() => { + component.command = { + ...createCommandResource(), + order: CommandOrder.WIEDERVORLAGE_ERLEDIGEN, + }; + }); + + it('should hide expansion panel', () => { + component.ngOnInit(); + fixture.detectChanges(); + + const userPanel = getElementFromFixture(fixture, userExpansionPanel); + expect(userPanel).not.toBeInstanceOf(HTMLElement); + }); + it('should show header only', () => { + component.ngOnInit(); + fixture.detectChanges(); + + const userPanel = getElementFromFixture(fixture, itemHeadline); + expect(userPanel).toBeInstanceOf(HTMLElement); + }); + }); + }); }); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.ts index 2425a8b3e16d80fc7c7cedf4b2d787a42167d1ec..87298b8cc730920a8fd11573be0f0bd48d732ed6 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-item-wiedervorlage/historie-item-wiedervorlage.component.ts @@ -25,34 +25,36 @@ import { Component, Input } from '@angular/core'; import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; @Component({ - selector: 'alfa-historie-item-wiedervorlage', - templateUrl: './historie-item-wiedervorlage.component.html', - styleUrls: ['./historie-item-wiedervorlage.component.scss'], + selector: 'alfa-historie-item-wiedervorlage', + templateUrl: './historie-item-wiedervorlage.component.html', + styleUrls: ['./historie-item-wiedervorlage.component.scss'], }) export class HistorieItemWiedervorlageComponent { + @Input() command: CommandResource; - @Input() command: CommandResource; + headline: string; + hasBody: boolean = true; - headline: string; - hasBody: boolean = true; + get wiedervorlage(): any { + return this.command.body.item; + } - get wiedervorlage(): any { - return this.command.body.item; - } + ngOnInit(): void { + this.headline = HISTORIE_TEXT_BY_WIEDERVORLAGE_ORDER[this.command.order]; + this.hasBody = this.hasItemBody(); + } - ngOnInit(): void { - this.headline = HISTORIE_TEXT_BY_WIEDERVORLAGE_ORDER[this.command.order]; - this.hasBody = this.hasItemBody(); - } - - hasItemBody(): boolean { - return this.command.order == CommandOrder.CREATE_WIEDERVORLAGE || this.command.order == CommandOrder.EDIT_WIEDERVORLAGE; - } + hasItemBody(): boolean { + return ( + this.command.order == CommandOrder.CREATE_WIEDERVORLAGE || + this.command.order == CommandOrder.EDIT_WIEDERVORLAGE + ); + } } const HISTORIE_TEXT_BY_WIEDERVORLAGE_ORDER: { [order: string]: string } = { - [CommandOrder.CREATE_WIEDERVORLAGE]: 'eine Wiedervorlage hinzugefügt.', - [CommandOrder.EDIT_WIEDERVORLAGE]: 'eine Wiedervorlage bearbeitet.', - [CommandOrder.WIEDERVORLAGE_ERLEDIGEN]: 'eine Wiedervorlage als erledigt markiert.', - [CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN]: 'eine Wiedervorlage als offen markiert.' -} \ No newline at end of file + [CommandOrder.CREATE_WIEDERVORLAGE]: 'eine Wiedervorlage hinzugefügt.', + [CommandOrder.EDIT_WIEDERVORLAGE]: 'eine Wiedervorlage bearbeitet.', + [CommandOrder.WIEDERVORLAGE_ERLEDIGEN]: 'eine Wiedervorlage als erledigt markiert.', + [CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN]: 'eine Wiedervorlage als offen markiert.', +}; diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.html index 859ae3c272dd5ab5cd8a956367c1dbbd1199f50f..c6abeda290e8b828b080d8154582ec5fe0d145e3 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.html @@ -24,31 +24,59 @@ --> <ng-container [ngSwitch]="orderTypeByCommandOrder[historieCommand.order]"> - <ng-container *ngSwitchCase="commandOrderType.USER"> - <alfa-historie-item-assign-user-container [command]="historieCommand" data-test-id="historie-item-assign-user"></alfa-historie-item-assign-user-container> - </ng-container> - <ng-container *ngSwitchCase="commandOrderType.KOMMENTAR"> - <alfa-historie-item-kommentar [command]="historieCommand" data-test-id="historie-item-kommentar"></alfa-historie-item-kommentar> - </ng-container> - <ng-container *ngSwitchCase="commandOrderType.FORWARDING"> - <alfa-historie-item-forwarding [command]="historieCommand" data-test-id="historie-item-forwarding"></alfa-historie-item-forwarding> - </ng-container> - <ng-container *ngSwitchCase="commandOrderType.POSTFACH_NACHRICHT"> - <alfa-historie-item-postfach-nachricht [command]="historieCommand" data-test-id="historie-item-postfach-nachricht"></alfa-historie-item-postfach-nachricht> - </ng-container> - <ng-container *ngSwitchCase="commandOrderType.VORGANG"> - <alfa-historie-item-vorgang-status [command]="historieCommand" data-test-id="historie-item-vorgang"></alfa-historie-item-vorgang-status> - </ng-container> - <ng-container *ngSwitchCase="commandOrderType.WIEDERVORLAGE"> - <alfa-historie-item-wiedervorlage [command]="historieCommand" data-test-id="historie-item-wiedervorlage"></alfa-historie-item-wiedervorlage> - </ng-container> - <ng-container *ngSwitchCase="commandOrderType.LOESCH_ANFORDERUNG"> - <alfa-historie-item-loesch-anforderung [command]="historieCommand" data-test-id="historie-item-loesch-anforderung"></alfa-historie-item-loesch-anforderung> - </ng-container> - <ng-container *ngSwitchCase="commandOrderType.SET_AKTENZEICHEN"> - <alfa-historie-item-aktenzeichen [command]="historieCommand" data-test-id="historie-item-aktenzeichen"></alfa-historie-item-aktenzeichen> - </ng-container> - <ng-container *ngSwitchDefault> - <alfa-historie-item-unknown [headline]="historieCommand.order" [resource]="historieCommand" data-test-id="historie-item-unknown"></alfa-historie-item-unknown> - </ng-container> -</ng-container> \ No newline at end of file + <ng-container *ngSwitchCase="commandOrderType.USER"> + <alfa-historie-item-assign-user-container + [command]="historieCommand" + data-test-id="historie-item-assign-user" + ></alfa-historie-item-assign-user-container> + </ng-container> + <ng-container *ngSwitchCase="commandOrderType.KOMMENTAR"> + <alfa-historie-item-kommentar + [command]="historieCommand" + data-test-id="historie-item-kommentar" + ></alfa-historie-item-kommentar> + </ng-container> + <ng-container *ngSwitchCase="commandOrderType.FORWARDING"> + <alfa-historie-item-forwarding + [command]="historieCommand" + data-test-id="historie-item-forwarding" + ></alfa-historie-item-forwarding> + </ng-container> + <ng-container *ngSwitchCase="commandOrderType.POSTFACH_NACHRICHT"> + <alfa-historie-item-postfach-nachricht + [command]="historieCommand" + data-test-id="historie-item-postfach-nachricht" + ></alfa-historie-item-postfach-nachricht> + </ng-container> + <ng-container *ngSwitchCase="commandOrderType.VORGANG"> + <alfa-historie-item-vorgang-status + [command]="historieCommand" + data-test-id="historie-item-vorgang" + ></alfa-historie-item-vorgang-status> + </ng-container> + <ng-container *ngSwitchCase="commandOrderType.WIEDERVORLAGE"> + <alfa-historie-item-wiedervorlage + [command]="historieCommand" + data-test-id="historie-item-wiedervorlage" + ></alfa-historie-item-wiedervorlage> + </ng-container> + <ng-container *ngSwitchCase="commandOrderType.LOESCH_ANFORDERUNG"> + <alfa-historie-item-loesch-anforderung + [command]="historieCommand" + data-test-id="historie-item-loesch-anforderung" + ></alfa-historie-item-loesch-anforderung> + </ng-container> + <ng-container *ngSwitchCase="commandOrderType.SET_AKTENZEICHEN"> + <alfa-historie-item-aktenzeichen + [command]="historieCommand" + data-test-id="historie-item-aktenzeichen" + ></alfa-historie-item-aktenzeichen> + </ng-container> + <ng-container *ngSwitchDefault> + <alfa-historie-item-unknown + [headline]="historieCommand.order" + [resource]="historieCommand" + data-test-id="historie-item-unknown" + ></alfa-historie-item-unknown> + </ng-container> +</ng-container> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.scss index 4ad74587729bb4e23c2ac29aeb7b70fee5d3828f..d601869c1d09f4bca303cc79aa5f104aee2bf7ff 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.scss @@ -24,6 +24,6 @@ @import 'variables'; :host { - display: block; - border-bottom: 1px solid $greyLight; -} \ No newline at end of file + display: block; + border-bottom: 1px solid $greyLight; +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.spec.ts index d1f80d1bf9acfb560f79d6ad2bdca47cfd521874..84b42604f41f48a1f5b0b5742551313778688dda 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.spec.ts @@ -38,128 +38,141 @@ import { HistorieItemWiedervorlageComponent } from '../historie-item-wiedervorla import { HistorieListItemComponent } from './historie-list-item.component'; describe('HistorieListItemComponent', () => { - let component: HistorieListItemComponent; - let fixture: ComponentFixture<HistorieListItemComponent>; - - const assignUserItem: string = getDataTestIdOf('historie-item-assign-user'); - const kommentarItem: string = getDataTestIdOf('historie-item-kommentar'); - const forwardingItem: string = getDataTestIdOf('historie-item-forwarding'); - const postfachNachrichtItem: string = getDataTestIdOf('historie-item-postfach-nachricht'); - const vorgangItem: string = getDataTestIdOf('historie-item-vorgang'); - const wiedervorlageItem: string = getDataTestIdOf('historie-item-wiedervorlage'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HistorieListItemComponent, - MockComponent(HistorieItemHeaderComponent), - MockComponent(HistorieItemWiedervorlageComponent), - MockComponent(HistorieItemKommentarComponent), - MockComponent(HistorieItemVorgangStatusComponent), - MockComponent(HistorieItemUnknownComponent), - MockComponent(HistorieItemPostfachNachrichtComponent), - MockComponent(HistorieItemForwardingComponent), - MockComponent(HistorieItemAssignUserContainerComponent) - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(HistorieListItemComponent); - component = fixture.componentInstance; - component.historieCommand = createCommandResource(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('decision of item component', () => { - - describe('on ' + CommandOrderType.USER + ' type ', () => { - - const order: CommandOrder[] = [CommandOrder.ASSIGN_USER]; - - it.each(order)('should show item on order s%', (order: CommandOrder) => { - component.historieCommand = { ...createCommandResource(), order }; - fixture.detectChanges(); - - const itemComponent = getElementFromFixture(fixture, assignUserItem); - - expect(itemComponent).toBeInstanceOf(HTMLElement); - }) - }) - - describe('on ' + CommandOrderType.KOMMENTAR + ' type ', () => { - - const order: CommandOrder[] = [CommandOrder.CREATE_KOMMENTAR, CommandOrder.EDIT_KOMMENTAR]; - - it.each(order)('should show item on order %s', (order: CommandOrder) => { - component.historieCommand = { ...createCommandResource(), order }; - fixture.detectChanges(); - - const itemComponent = getElementFromFixture(fixture, kommentarItem); - - expect(itemComponent).toBeInstanceOf(HTMLElement); - }) - }) - - describe('on ' + CommandOrderType.FORWARDING + ' type ', () => { - - const order: CommandOrder[] = [CommandOrder.REDIRECT_VORGANG, CommandOrder.FORWARD_SUCCESSFULL, CommandOrder.FORWARD_FAILED]; - - it.each(order)('should show item on order %s', (order: CommandOrder) => { - component.historieCommand = { ...createCommandResource(), order }; - fixture.detectChanges(); - - const itemComponent = getElementFromFixture(fixture, forwardingItem); - - expect(itemComponent).toBeInstanceOf(HTMLElement); - }) - }) - - describe('on ' + CommandOrderType.POSTFACH_NACHRICHT + ' type ', () => { - - const order: CommandOrder[] = [CommandOrder.SEND_POSTFACH_NACHRICHT, CommandOrder.RECEIVE_POSTFACH_NACHRICHT]; - - it.each(order)('should show item on order %s', (order: CommandOrder) => { - component.historieCommand = { ...createCommandResource(), order }; - fixture.detectChanges(); - - const itemComponent = getElementFromFixture(fixture, postfachNachrichtItem); - - expect(itemComponent).toBeInstanceOf(HTMLElement); - }) - }) - - describe('on ' + CommandOrderType.VORGANG + ' type ', () => { - - const order: CommandOrder[] = [CommandOrder.VORGANG_ANNEHMEN, CommandOrder.VORGANG_VERWERFEN, CommandOrder.VORGANG_ZURUECKHOLEN, CommandOrder.VORGANG_BEARBEITEN, - CommandOrder.VORGANG_BESCHEIDEN, CommandOrder.VORGANG_ZURUECKSTELLEN, CommandOrder.VORGANG_ABSCHLIESSEN, CommandOrder.VORGANG_WIEDEREROEFFNEN]; - - it.each(order)('should show item on order %s', (order: CommandOrder) => { - component.historieCommand = { ...createCommandResource(), order }; - fixture.detectChanges(); - - const itemComponent = getElementFromFixture(fixture, vorgangItem); - - expect(itemComponent).toBeInstanceOf(HTMLElement); - }) - }) - - describe('on ' + CommandOrderType.WIEDERVORLAGE + ' type ', () => { - - const order: CommandOrder[] = [CommandOrder.CREATE_WIEDERVORLAGE, CommandOrder.EDIT_WIEDERVORLAGE, CommandOrder.WIEDERVORLAGE_ERLEDIGEN, CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN]; - - it.each(order)('should show item on order %s', (order: CommandOrder) => { - component.historieCommand = { ...createCommandResource(), order }; - fixture.detectChanges(); - - const itemComponent = getElementFromFixture(fixture, wiedervorlageItem); - - expect(itemComponent).toBeInstanceOf(HTMLElement); - }) - }) - }) -}); \ No newline at end of file + let component: HistorieListItemComponent; + let fixture: ComponentFixture<HistorieListItemComponent>; + + const assignUserItem: string = getDataTestIdOf('historie-item-assign-user'); + const kommentarItem: string = getDataTestIdOf('historie-item-kommentar'); + const forwardingItem: string = getDataTestIdOf('historie-item-forwarding'); + const postfachNachrichtItem: string = getDataTestIdOf('historie-item-postfach-nachricht'); + const vorgangItem: string = getDataTestIdOf('historie-item-vorgang'); + const wiedervorlageItem: string = getDataTestIdOf('historie-item-wiedervorlage'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HistorieListItemComponent, + MockComponent(HistorieItemHeaderComponent), + MockComponent(HistorieItemWiedervorlageComponent), + MockComponent(HistorieItemKommentarComponent), + MockComponent(HistorieItemVorgangStatusComponent), + MockComponent(HistorieItemUnknownComponent), + MockComponent(HistorieItemPostfachNachrichtComponent), + MockComponent(HistorieItemForwardingComponent), + MockComponent(HistorieItemAssignUserContainerComponent), + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(HistorieListItemComponent); + component = fixture.componentInstance; + component.historieCommand = createCommandResource(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('decision of item component', () => { + describe('on ' + CommandOrderType.USER + ' type ', () => { + const order: CommandOrder[] = [CommandOrder.ASSIGN_USER]; + + it.each(order)('should show item on order s%', (order: CommandOrder) => { + component.historieCommand = { ...createCommandResource(), order }; + fixture.detectChanges(); + + const itemComponent = getElementFromFixture(fixture, assignUserItem); + + expect(itemComponent).toBeInstanceOf(HTMLElement); + }); + }); + + describe('on ' + CommandOrderType.KOMMENTAR + ' type ', () => { + const order: CommandOrder[] = [CommandOrder.CREATE_KOMMENTAR, CommandOrder.EDIT_KOMMENTAR]; + + it.each(order)('should show item on order %s', (order: CommandOrder) => { + component.historieCommand = { ...createCommandResource(), order }; + fixture.detectChanges(); + + const itemComponent = getElementFromFixture(fixture, kommentarItem); + + expect(itemComponent).toBeInstanceOf(HTMLElement); + }); + }); + + describe('on ' + CommandOrderType.FORWARDING + ' type ', () => { + const order: CommandOrder[] = [ + CommandOrder.REDIRECT_VORGANG, + CommandOrder.FORWARD_SUCCESSFULL, + CommandOrder.FORWARD_FAILED, + ]; + + it.each(order)('should show item on order %s', (order: CommandOrder) => { + component.historieCommand = { ...createCommandResource(), order }; + fixture.detectChanges(); + + const itemComponent = getElementFromFixture(fixture, forwardingItem); + + expect(itemComponent).toBeInstanceOf(HTMLElement); + }); + }); + + describe('on ' + CommandOrderType.POSTFACH_NACHRICHT + ' type ', () => { + const order: CommandOrder[] = [ + CommandOrder.SEND_POSTFACH_NACHRICHT, + CommandOrder.RECEIVE_POSTFACH_NACHRICHT, + ]; + + it.each(order)('should show item on order %s', (order: CommandOrder) => { + component.historieCommand = { ...createCommandResource(), order }; + fixture.detectChanges(); + + const itemComponent = getElementFromFixture(fixture, postfachNachrichtItem); + + expect(itemComponent).toBeInstanceOf(HTMLElement); + }); + }); + + describe('on ' + CommandOrderType.VORGANG + ' type ', () => { + const order: CommandOrder[] = [ + CommandOrder.VORGANG_ANNEHMEN, + CommandOrder.VORGANG_VERWERFEN, + CommandOrder.VORGANG_ZURUECKHOLEN, + CommandOrder.VORGANG_BEARBEITEN, + CommandOrder.VORGANG_BESCHEIDEN, + CommandOrder.VORGANG_ZURUECKSTELLEN, + CommandOrder.VORGANG_ABSCHLIESSEN, + CommandOrder.VORGANG_WIEDEREROEFFNEN, + ]; + + it.each(order)('should show item on order %s', (order: CommandOrder) => { + component.historieCommand = { ...createCommandResource(), order }; + fixture.detectChanges(); + + const itemComponent = getElementFromFixture(fixture, vorgangItem); + + expect(itemComponent).toBeInstanceOf(HTMLElement); + }); + }); + + describe('on ' + CommandOrderType.WIEDERVORLAGE + ' type ', () => { + const order: CommandOrder[] = [ + CommandOrder.CREATE_WIEDERVORLAGE, + CommandOrder.EDIT_WIEDERVORLAGE, + CommandOrder.WIEDERVORLAGE_ERLEDIGEN, + CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN, + ]; + + it.each(order)('should show item on order %s', (order: CommandOrder) => { + component.historieCommand = { ...createCommandResource(), order }; + fixture.detectChanges(); + + const itemComponent = getElementFromFixture(fixture, wiedervorlageItem); + + expect(itemComponent).toBeInstanceOf(HTMLElement); + }); + }); + }); +}); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.ts index 8b0accd9a6eb5304e22e8d91c28a8492cc81183e..df482203230ac168ac9bdb9e39fa7e249ed1763b 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list-item/historie-list-item.component.ts @@ -22,17 +22,20 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Component, Input } from '@angular/core'; -import { CommandOrderType, CommandResource, ORDER_TYPE_BY_COMMAND_ORDER } from '@alfa-client/command-shared'; +import { + CommandOrderType, + CommandResource, + ORDER_TYPE_BY_COMMAND_ORDER, +} from '@alfa-client/command-shared'; @Component({ - selector: 'alfa-historie-list-item', - templateUrl: './historie-list-item.component.html', - styleUrls: ['./historie-list-item.component.scss'], + selector: 'alfa-historie-list-item', + templateUrl: './historie-list-item.component.html', + styleUrls: ['./historie-list-item.component.scss'], }) export class HistorieListItemComponent { + @Input() historieCommand: CommandResource; - @Input() historieCommand: CommandResource - - readonly orderTypeByCommandOrder = ORDER_TYPE_BY_COMMAND_ORDER; - readonly commandOrderType = CommandOrderType; -} \ No newline at end of file + readonly orderTypeByCommandOrder = ORDER_TYPE_BY_COMMAND_ORDER; + readonly commandOrderType = CommandOrderType; +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.html b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.html index 28545e12c5891bee39a27b0be7563aab3cc2a36d..11b0fa82852ec13ff75b9ce53b86e92bb1c17920 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.html +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.html @@ -23,16 +23,25 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-historie-item-vorgang-created [vorgangWithEingang]="vorgangWithEingang"></alfa-historie-item-vorgang-created> +<alfa-historie-item-vorgang-created + [vorgangWithEingang]="vorgangWithEingang" +></alfa-historie-item-vorgang-created> <ozgcloud-spinner [stateResource]="commandStateListResource"> - - <ng-container *ngIf="commandStateListResource.resource"> - <ozgcloud-accordion [multi]="true"> - <ng-container *ngFor="let historieCommand of (commandStateListResource.resource | toEmbeddedResources: commandListLinkRel.COMMAND_LIST); index as i"> - <alfa-historie-list-item [historieCommand]="historieCommand" [attr.data-test-id]="'historie-list-item-' + i"></alfa-historie-list-item> - </ng-container> - </ozgcloud-accordion> - </ng-container> - -</ozgcloud-spinner> \ No newline at end of file + <ng-container *ngIf="commandStateListResource.resource"> + <ozgcloud-accordion [multi]="true"> + <ng-container + *ngFor=" + let historieCommand of commandStateListResource.resource + | toEmbeddedResources: commandListLinkRel.COMMAND_LIST; + index as i + " + > + <alfa-historie-list-item + [historieCommand]="historieCommand" + [attr.data-test-id]="'historie-list-item-' + i" + ></alfa-historie-list-item> + </ng-container> + </ozgcloud-accordion> + </ng-container> +</ozgcloud-spinner> diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.scss b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.scss index 86e14516c34fa09bee546a46b3e3c69dd2ec0dbe..b2549633b88686c4759c7de5637702275ecff6e0 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.scss +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.scss @@ -24,12 +24,12 @@ @import 'variables'; ul { - margin-top: 0; - padding-left: 0; - width: 100%; + margin-top: 0; + padding-left: 0; + width: 100%; - li { - border-bottom: 1px solid $greyLight; - padding: 0.75rem 0; - } -} \ No newline at end of file + li { + border-bottom: 1px solid $greyLight; + padding: 0.75rem 0; + } +} diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.spec.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.spec.ts index eecf453372a57805e50cf8c624232db7c9d5dd3b..bf5608d30ca82872a4c05a5652ba62e8cdea4312 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.spec.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.spec.ts @@ -26,7 +26,12 @@ import localeDe from '@angular/common/locales/de'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatExpansionModule } from '@angular/material/expansion'; import { CommandListResource } from '@alfa-client/command-shared'; -import { createEmptyStateResource, createStateResource, FormatDateWithTimePipe, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + FormatDateWithTimePipe, + ToEmbeddedResourcesPipe, +} from '@alfa-client/tech-shared'; import { getElementFromFixture } from '@alfa-client/test-utils'; import { AccordionComponent, SpinnerComponent } from '@alfa-client/ui'; import { createCommandListResource } from 'libs/command-shared/test/command'; @@ -39,59 +44,56 @@ import { HistorieListComponent } from './historie-list.component'; registerLocaleData(localeDe); describe('HistorieListComponent', () => { - let component: HistorieListComponent; - let fixture: ComponentFixture<HistorieListComponent>; + let component: HistorieListComponent; + let fixture: ComponentFixture<HistorieListComponent>; - const historieItem: string = getDataTestIdOf('historie-list-item-0'); + const historieItem: string = getDataTestIdOf('historie-list-item-0'); - const commandListResource: CommandListResource = createCommandListResource(); + const commandListResource: CommandListResource = createCommandListResource(); - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - MatExpansionModule, - ], - declarations: [ - ToEmbeddedResourcesPipe, - FormatDateWithTimePipe, - HistorieListComponent, - MockComponent(HistorieListItemComponent), - MockComponent(SpinnerComponent), - MockComponent(HistorieItemVorgangCreatedComponent), - MockComponent(AccordionComponent) - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MatExpansionModule], + declarations: [ + ToEmbeddedResourcesPipe, + FormatDateWithTimePipe, + HistorieListComponent, + MockComponent(HistorieListItemComponent), + MockComponent(SpinnerComponent), + MockComponent(HistorieItemVorgangCreatedComponent), + MockComponent(AccordionComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HistorieListComponent); - component = fixture.componentInstance; - component.commandStateListResource = createStateResource(commandListResource); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HistorieListComponent); + component = fixture.componentInstance; + component.commandStateListResource = createStateResource(commandListResource); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('list item', () => { + describe('list item', () => { + it('should show items on filled content', () => { + component.commandStateListResource = createStateResource(commandListResource); + fixture.detectChanges(); - it('should show items on filled content', () => { - component.commandStateListResource = createStateResource(commandListResource); - fixture.detectChanges(); + const element = getElementFromFixture(fixture, historieItem); - const element = getElementFromFixture(fixture, historieItem); + expect(element).toBeInstanceOf(HTMLElement); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) + it('should NOT show items without content', () => { + component.commandStateListResource = createEmptyStateResource(); + fixture.detectChanges(); - it('should NOT show items without content', () => { - component.commandStateListResource = createEmptyStateResource(); - fixture.detectChanges(); + const element = getElementFromFixture(fixture, historieItem); - const element = getElementFromFixture(fixture, historieItem); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) -}) + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); +}); diff --git a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.ts b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.ts index 4f1d0c11eccd8b30fd87a59b81d2ca3bd22e2a06..af288bca3e774ada2dad2c41caa0c776b985f6a3 100644 --- a/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.ts +++ b/alfa-client/libs/historie/src/lib/historie-container/historie-list/historie-list.component.ts @@ -28,15 +28,13 @@ import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { CommandListLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; @Component({ - selector: 'alfa-historie-list', - templateUrl: './historie-list.component.html', - styleUrls: ['./historie-list.component.scss'], + selector: 'alfa-historie-list', + templateUrl: './historie-list.component.html', + styleUrls: ['./historie-list.component.scss'], }) export class HistorieListComponent { + @Input() commandStateListResource: StateResource<CommandListResource>; + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() commandStateListResource: StateResource<CommandListResource>; - @Input() vorgangWithEingang: VorgangWithEingangResource; - - readonly commandListLinkRel = CommandListLinkRel; - + readonly commandListLinkRel = CommandListLinkRel; } diff --git a/alfa-client/libs/historie/src/lib/historie.module.ts b/alfa-client/libs/historie/src/lib/historie.module.ts index 876c52d9f57b29f4d5b7874d2a61105ae7040a0a..1d3830b291eafe0762573e2c106fd8ed0bc05536 100644 --- a/alfa-client/libs/historie/src/lib/historie.module.ts +++ b/alfa-client/libs/historie/src/lib/historie.module.ts @@ -36,7 +36,7 @@ import { HistorieItemAttachmentComponent } from './historie-container/historie-l import { HistorieItemForwardingComponent } from './historie-container/historie-list/historie-item-forwarding/historie-item-forwarding.component'; import { HistorieItemHeaderComponent } from './historie-container/historie-list/historie-item-header/historie-item-header.component'; import { HistorieItemKommentarComponent } from './historie-container/historie-list/historie-item-kommentar/historie-item-kommentar.component'; -import { HistorieItemLoeschAnforderungComponent } from "./historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component"; +import { HistorieItemLoeschAnforderungComponent } from './historie-container/historie-list/historie-item-loesch-anforderung/historie-item-loesch-anforderung.component'; import { HistorieItemPostfachNachrichtComponent } from './historie-container/historie-list/historie-item-postfach-nachricht/historie-item-postfach-nachricht.component'; import { HistorieItemUnknownComponent } from './historie-container/historie-list/historie-item-unknown/historie-item-unknown.component'; import { HistorieItemVorgangCreatedComponent } from './historie-container/historie-list/historie-item-vorgang-created/historie-item-vorgang-created.component'; @@ -48,34 +48,34 @@ import { HistorieListComponent } from './historie-container/historie-list/histor import { HistorieItemAktenzeichenComponent } from './historie-container/historie-list/historie-item-aktenzeichen/historie-item-aktenzeichen.component'; @NgModule({ - imports: [ - CommonModule, - TechSharedModule, - HistorieSharedModule, - UserProfileModule, - UiModule, - CommandSharedModule, - ], - declarations: [ - HistorieContainerComponent, - HistorieListComponent, - HistorieListItemComponent, - HistorieItemVorgangCreatedComponent, - HistorieItemKommentarComponent, - ExpansionPanelWithUserComponent, - HistorieItemWiedervorlageComponent, - HistorieItemHeaderComponent, - HistorieItemVorgangStatusComponent, - HistorieItemUnknownComponent, - HistorieItemPostfachNachrichtComponent, - HistorieItemForwardingComponent, - HistorieItemAssignUserComponent, - HistorieItemAssignUserContainerComponent, - HistorieItemWiedervorlageStatusComponent, - HistorieItemAttachmentComponent, - HistorieItemLoeschAnforderungComponent, - HistorieItemAktenzeichenComponent, - ], - exports: [HistorieContainerComponent], + imports: [ + CommonModule, + TechSharedModule, + HistorieSharedModule, + UserProfileModule, + UiModule, + CommandSharedModule, + ], + declarations: [ + HistorieContainerComponent, + HistorieListComponent, + HistorieListItemComponent, + HistorieItemVorgangCreatedComponent, + HistorieItemKommentarComponent, + ExpansionPanelWithUserComponent, + HistorieItemWiedervorlageComponent, + HistorieItemHeaderComponent, + HistorieItemVorgangStatusComponent, + HistorieItemUnknownComponent, + HistorieItemPostfachNachrichtComponent, + HistorieItemForwardingComponent, + HistorieItemAssignUserComponent, + HistorieItemAssignUserContainerComponent, + HistorieItemWiedervorlageStatusComponent, + HistorieItemAttachmentComponent, + HistorieItemLoeschAnforderungComponent, + HistorieItemAktenzeichenComponent, + ], + exports: [HistorieContainerComponent], }) export class HistorieModule {} diff --git a/alfa-client/libs/historie/src/test-setup.ts b/alfa-client/libs/historie/src/test-setup.ts index a34d602adcc3acf9aca31a86021eff1f069e918d..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/historie/src/test-setup.ts +++ b/alfa-client/libs/historie/src/test-setup.ts @@ -25,15 +25,14 @@ import '@testing-library/jest-dom'; import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); \ No newline at end of file +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/historie/tsconfig.json b/alfa-client/libs/historie/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/historie/tsconfig.json +++ b/alfa-client/libs/historie/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/historie/tsconfig.lib.json b/alfa-client/libs/historie/tsconfig.lib.json index ead8f8bdba5aca4d713f65c9003b06695a69c2f4..2e762bd23944def694724f2ce7c0ea2d922ae1e5 100644 --- a/alfa-client/libs/historie/tsconfig.lib.json +++ b/alfa-client/libs/historie/tsconfig.lib.json @@ -1,17 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [] - }, - "exclude": [ - "src/test-setup.ts", - "**/*.spec.ts", - "**/*.test.ts", - "jest.config.ts" - ], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "**/*.test.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/historie/tsconfig.spec.json b/alfa-client/libs/historie/tsconfig.spec.json index 4950ae2f7859509b300543bff1c1e5ce4b1e2d5c..c3cb17f784fa2f7b9a4b0e7c9b03663500f4ee3d 100644 --- a/alfa-client/libs/historie/tsconfig.spec.json +++ b/alfa-client/libs/historie/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/kommentar-shared/.eslintrc.json b/alfa-client/libs/kommentar-shared/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/kommentar-shared/.eslintrc.json +++ b/alfa-client/libs/kommentar-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/kommentar-shared/jest.config.ts b/alfa-client/libs/kommentar-shared/jest.config.ts index cf650b04653b3239cde531526f6bcb8a09b433ba..8c10f12768e3c8378a6c82486b775a11882c09b9 100644 --- a/alfa-client/libs/kommentar-shared/jest.config.ts +++ b/alfa-client/libs/kommentar-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'kommentar-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/kommentar-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'kommentar-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/kommentar-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/kommentar-shared/project.json b/alfa-client/libs/kommentar-shared/project.json index 6585a6ef273f0e7ae1f42812beb264849ae80bea..365ba89ee0dc1eae8d5794983af95fd84d9e9916 100644 --- a/alfa-client/libs/kommentar-shared/project.json +++ b/alfa-client/libs/kommentar-shared/project.json @@ -1,29 +1,29 @@ { - "name": "kommentar-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/kommentar-shared/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/kommentar-shared"], - "options": { - "tsConfig": "libs/kommentar-shared/tsconfig.spec.json", - "jestConfig": "libs/kommentar-shared/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/kommentar-shared/src/**/*.ts", - "libs/kommentar-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [] + "name": "kommentar-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/kommentar-shared/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/kommentar-shared"], + "options": { + "tsConfig": "libs/kommentar-shared/tsconfig.spec.json", + "jestConfig": "libs/kommentar-shared/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/kommentar-shared/src/**/*.ts", + "libs/kommentar-shared/src/**/*.html" + ] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [] } diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.spec.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.spec.ts index fe1ea3c752e29e0bbfd70f7e0538f9eb8048674c..e073f7428d9bfead5e0d5034447583ebf628ef8c 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.spec.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { KommentarSharedModule } from './kommentar-shared.module'; describe('KommentarSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [KommentarSharedModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [KommentarSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(KommentarSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(KommentarSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.ts index 75e8d056ccd6ea85b4ba94d94f94f3a1be6edd3c..2ea9f70927131d8ec1331398c242b917b74f3897 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar-shared.module.ts @@ -27,10 +27,6 @@ import { TechSharedModule } from '@alfa-client/tech-shared'; import { VorgangSharedModule } from '@alfa-client/vorgang-shared'; @NgModule({ - imports: [ - CommonModule, - TechSharedModule, - VorgangSharedModule - ], + imports: [CommonModule, TechSharedModule, VorgangSharedModule], }) -export class KommentarSharedModule { } +export class KommentarSharedModule {} diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.linkrel.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.linkrel.ts index e45aaa43c025a462af927246e0779a72625faaff..6aba0a8790cb62f6f422ba8242b483e442097ac7 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.linkrel.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.linkrel.ts @@ -22,13 +22,13 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum KommentarListLinkRel { - KOMMENTAR_LIST = 'kommentarList', - CREATE_KOMMENTAR = 'create-kommentar', - UPLOAD_FILE = 'uploadFile', + KOMMENTAR_LIST = 'kommentarList', + CREATE_KOMMENTAR = 'create-kommentar', + UPLOAD_FILE = 'uploadFile', } export enum KommentarLinkRel { - EDIT = 'edit', - CREATED_BY = 'createdBy', - ATTACHMENTS = 'attachments', -} \ No newline at end of file + EDIT = 'edit', + CREATED_BY = 'createdBy', + ATTACHMENTS = 'attachments', +} diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.model.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.model.ts index 8cc2f3a8c1a813ba6a799f6f90beceba7143af28..3155c2596134d40deb75c95edad1f86b3a3b9816 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.model.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.model.ts @@ -26,16 +26,15 @@ import { ListResource } from '@alfa-client/tech-shared'; import { Resource, ResourceUri } from '@ngxp/rest'; export interface Kommentar { - createdBy: string; - createdAt: Date; - text: string; - attachments: ResourceUri[] | string + createdBy: string; + createdAt: Date; + text: string; + attachments: ResourceUri[] | string; } -export interface KommentarResource extends Kommentar, Resource { } -export interface KommentarListResource extends ListResource { } - +export interface KommentarResource extends Kommentar, Resource {} +export interface KommentarListResource extends ListResource {} export interface CreateKommentarCommand extends CreateCommand { - kommentar: Kommentar -} \ No newline at end of file + kommentar: Kommentar; +} diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.repository.spec.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.repository.spec.ts index 8cd6090e7d4f2b9526340171e7bf79dc40c052cd..d0399026409f4e677a5d64749ae8ac82eb681526 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.repository.spec.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.repository.spec.ts @@ -32,40 +32,42 @@ import { KommentarListResource } from './kommentar.model'; import { KommentarRepository } from './kommentar.repository'; describe('KommentarRepository', () => { - let repository: KommentarRepository; - let resourceFactory = mock(ResourceFactory); - let resourceWrapper = { get: jest.fn() }; + let repository: KommentarRepository; + let resourceFactory = mock(ResourceFactory); + let resourceWrapper = { get: jest.fn() }; - beforeEach(() => { - repository = new KommentarRepository(useFromMock(resourceFactory)); - }) + beforeEach(() => { + repository = new KommentarRepository(useFromMock(resourceFactory)); + }); - describe('findKommentare', () => { - const kommentarListResource: KommentarListResource = createKommentarListResource(); - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([KommentarListLinkRel.KOMMENTAR_LIST]); + describe('findKommentare', () => { + const kommentarListResource: KommentarListResource = createKommentarListResource(); + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([ + KommentarListLinkRel.KOMMENTAR_LIST, + ]); - beforeEach(() => { - resourceFactory.from.mockReturnValue(resourceWrapper); - resourceWrapper.get.mockReturnValue(cold('a', { a: kommentarListResource })); - }) + beforeEach(() => { + resourceFactory.from.mockReturnValue(resourceWrapper); + resourceWrapper.get.mockReturnValue(cold('a', { a: kommentarListResource })); + }); - it('should call resourceFactory with resource', () => { - repository.findKommentare(vorgang); + it('should call resourceFactory with resource', () => { + repository.findKommentare(vorgang); - expect(resourceFactory.from).toHaveBeenCalledWith(vorgang); - }) + expect(resourceFactory.from).toHaveBeenCalledWith(vorgang); + }); - it('should call resourceWrapper with link', () => { - repository.findKommentare(vorgang); + it('should call resourceWrapper with link', () => { + repository.findKommentare(vorgang); - expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangHeaderLinkRel.KOMMENTARE); - }) + expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangHeaderLinkRel.KOMMENTARE); + }); - it('should return result', () => { - let result = repository.findKommentare(vorgang); + it('should return result', () => { + let result = repository.findKommentare(vorgang); - expect(result).not.toBeNull(); - expect(result).toBeObservable(hot('a', { a: kommentarListResource })); - }) - }) -}) \ No newline at end of file + expect(result).not.toBeNull(); + expect(result).toBeObservable(hot('a', { a: kommentarListResource })); + }); + }); +}); diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.repository.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.repository.ts index 00a701d5745d86f69a2a43ed71f7022178cd5660..1b10d14cfbef71ab438ecc8f041059234769878f 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.repository.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.repository.ts @@ -29,10 +29,9 @@ import { KommentarListResource } from './kommentar.model'; @Injectable({ providedIn: 'root' }) export class KommentarRepository { + constructor(private resourceFactory: ResourceFactory) {} - constructor(private resourceFactory: ResourceFactory) { } - - public findKommentare(vorgang: VorgangResource): Observable<KommentarListResource> { - return this.resourceFactory.from(vorgang).get(VorgangHeaderLinkRel.KOMMENTARE); - } -} \ No newline at end of file + public findKommentare(vorgang: VorgangResource): Observable<KommentarListResource> { + return this.resourceFactory.from(vorgang).get(VorgangHeaderLinkRel.KOMMENTARE); + } +} diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts index a2893f61d1003f46410bca498e7f18a89d6674d1..0478aadb64501cee92b4900b6275eb8cd122a96d 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.spec.ts @@ -24,293 +24,322 @@ import { BinaryFileService } from '@alfa-client/binary-file-shared'; import { CommandOrder, CommandResource, CommandService } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { mock, Mock, useFromMock } from '@alfa-client/test-utils'; import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { cold, hot } from 'jest-marbles'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; import { createCommandResource } from 'libs/command-shared/test/command'; -import { createKommentar, createKommentarListResource, createKommentarResource } from 'libs/kommentar-shared/test/kommentar'; +import { + createKommentar, + createKommentarListResource, + createKommentarResource, +} from 'libs/kommentar-shared/test/kommentar'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { of } from 'rxjs'; import { KommentarLinkRel, KommentarListLinkRel } from './kommentar.linkrel'; -import { CreateKommentarCommand, Kommentar, KommentarListResource, KommentarResource } from './kommentar.model'; +import { + CreateKommentarCommand, + Kommentar, + KommentarListResource, + KommentarResource, +} from './kommentar.model'; import { KommentarRepository } from './kommentar.repository'; import { KommentarService } from './kommentar.service'; describe('KommentarService', () => { - let service: KommentarService; - let repository: Mock<KommentarRepository>; - let commandService: Mock<CommandService>; - let navigationService: Mock<NavigationService>; - let vorgangService: Mock<VorgangService>; - let binaryFileService: Mock<BinaryFileService>; + let service: KommentarService; + let repository: Mock<KommentarRepository>; + let commandService: Mock<CommandService>; + let navigationService: Mock<NavigationService>; + let vorgangService: Mock<VorgangService>; + let binaryFileService: Mock<BinaryFileService>; + + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const kommentarList: KommentarListResource = createKommentarListResource(); + const kommentar: Kommentar = createKommentar(); + const kommentarResource: KommentarResource = createKommentarResource(); + const command: CommandResource = createCommandResource(); + const commandStateResource: StateResource<CommandResource> = createStateResource(command); + + beforeEach(() => { + repository = mock(KommentarRepository); + commandService = mock(CommandService); + navigationService = mock(NavigationService); + vorgangService = mock(VorgangService); + binaryFileService = mock(BinaryFileService); + + navigationService.urlChanged.mockReturnValue(of({})); + + service = new KommentarService( + useFromMock(repository), + useFromMock(commandService), + useFromMock(navigationService), + useFromMock(vorgangService), + useFromMock(binaryFileService), + ); + }); + + describe('getKommentareByVorgang', () => { + beforeEach(() => { + repository.findKommentare.mockReturnValue(of(kommentarList)); + + service.setListLoadingTrue = jest.fn(); + service.setKommentarList = jest.fn(); + }); + + it('should set loading to true', () => { + service.getKommentareByVorgang(vorgang); + + expect(service.setListLoadingTrue).toHaveBeenCalled(); + }); + + it('should call repository', () => { + service.getKommentareByVorgang(vorgang).subscribe(); + + expect(repository.findKommentare).toHaveBeenCalledWith(vorgang); + }); + + it('should set loaded resource', () => { + service.getKommentareByVorgang(vorgang); + + expect(service.setKommentarList).toHaveBeenCalledWith(kommentarList); + }); + }); - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const kommentarList: KommentarListResource = createKommentarListResource(); - const kommentar: Kommentar = createKommentar(); - const kommentarResource: KommentarResource = createKommentarResource(); - const command: CommandResource = createCommandResource(); - const commandStateResource: StateResource<CommandResource> = createStateResource(command); + describe('createKommentar', () => { + describe('init and next value', () => { + beforeEach(() => { + commandService.createCommand.mockReturnValue(hot('-a', { a: commandStateResource })); + }); + + it('should be return', () => { + const result = service.createKommentar(kommentar); + + expect(result).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: commandStateResource }), + ); + }); + }); + + describe('further process', () => { + beforeEach(() => { + commandService.createCommand.mockReturnValue(of(commandStateResource)); + }); - beforeEach(() => { - repository = mock(KommentarRepository); - commandService = mock(CommandService); - navigationService = mock(NavigationService); - vorgangService = mock(VorgangService); - binaryFileService = mock(BinaryFileService); + it('should call command service', () => { + service.createKommentar(kommentar); + + expect(commandService.createCommand).toHaveBeenCalledWith( + service.kommentarList$.value.resource, + KommentarListLinkRel.CREATE_KOMMENTAR, + service.createCreateKommentarCommand(kommentar), + ); + }); + + it('should call getEffectedResource', () => { + service.afterCreateOrEditKommentar = jest.fn(); + + service.createKommentar(kommentar).subscribe(); + + expect(service.afterCreateOrEditKommentar).toHaveBeenCalledWith(commandStateResource); + }); + + it('should call createCreateKommentarCommand', () => { + service.createCreateKommentarCommand = jest.fn(); + + service.createKommentar(kommentar); + + expect(service.createCreateKommentarCommand).toHaveBeenCalledWith(kommentar); + }); - navigationService.urlChanged.mockReturnValue(of({})); + it('should create CreateKommentarCommand', () => { + var command: CreateKommentarCommand = service.createCreateKommentarCommand(kommentar); - service = new KommentarService( - useFromMock(repository), - useFromMock(commandService), - useFromMock(navigationService), - useFromMock(vorgangService), - useFromMock(binaryFileService)); - }) + expect(command).toEqual({ order: CommandOrder.CREATE_KOMMENTAR, kommentar, body: null }); + }); + }); + }); - describe('getKommentareByVorgang', () => { + describe('edit kommentar', () => { + describe('init and next value', () => { + beforeEach(() => { + commandService.createCommand.mockReturnValue(hot('-a', { a: commandStateResource })); + }); - beforeEach(() => { - repository.findKommentare.mockReturnValue(of(kommentarList)); + it('should be return', () => { + const result = service.editKommentar(kommentarResource, kommentar); - service.setListLoadingTrue = jest.fn(); - service.setKommentarList = jest.fn(); - }) + expect(result).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: commandStateResource }), + ); + }); + }); - it('should set loading to true', () => { - service.getKommentareByVorgang(vorgang); + describe('further process', () => { + beforeEach(() => { + commandService.createCommand.mockReturnValue(of(commandStateResource)); + }); - expect(service.setListLoadingTrue).toHaveBeenCalled(); - }) + it('should call command service', () => { + service.editKommentar(kommentarResource, kommentar); - it('should call repository', () => { - service.getKommentareByVorgang(vorgang).subscribe(); + expect(commandService.createCommand).toHaveBeenCalledWith( + kommentarResource, + KommentarLinkRel.EDIT, + service.createEditKommentarCommand(kommentar), + ); + }); - expect(repository.findKommentare).toHaveBeenCalledWith(vorgang); - }) + it('should call getEffectedResource', () => { + service.afterCreateOrEditKommentar = jest.fn(); - it('should set loaded resource', () => { - service.getKommentareByVorgang(vorgang); + service.editKommentar(kommentarResource, kommentar).subscribe(); - expect(service.setKommentarList).toHaveBeenCalledWith(kommentarList); - }) - }) + expect(service.afterCreateOrEditKommentar).toHaveBeenCalledWith(commandStateResource); + }); - describe('createKommentar', () => { + it('should call createEditKommentarCommand', () => { + service.createEditKommentarCommand = jest.fn(); - describe('init and next value', () => { + service.editKommentar(kommentarResource, kommentar); - beforeEach(() => { - commandService.createCommand.mockReturnValue(hot('-a', { a: commandStateResource })); - }) + expect(service.createEditKommentarCommand).toHaveBeenCalledWith(kommentar); + }); - it('should be return', () => { - const result = service.createKommentar(kommentar); + it('should create CreateKommentarCommand', () => { + var command: CreateKommentarCommand = service.createEditKommentarCommand(kommentar); - expect(result).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: commandStateResource })); - }) - }) + expect(command).toEqual({ order: CommandOrder.EDIT_KOMMENTAR, kommentar, body: null }); + }); + }); + }); - describe('further process', () => { + describe('afterCreateOrEditKommentar', () => { + describe('on command is done', () => { + const kommentarList: KommentarListResource = createKommentarListResource(); - beforeEach(() => { - commandService.createCommand.mockReturnValue(of(commandStateResource)); - }) + beforeEach(() => { + commandService.getEffectedResource.mockReturnValue(of(kommentarList)); + }); - it('should call command service', () => { - service.createKommentar(kommentar); + it('should hide formular', () => { + service.hideFormular = jest.fn(); - expect(commandService.createCommand).toHaveBeenCalledWith(service.kommentarList$.value.resource, KommentarListLinkRel.CREATE_KOMMENTAR, service.createCreateKommentarCommand(kommentar)); - }) + service.afterCreateOrEditKommentar({ + ...commandStateResource, + resource: createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), + }); - it('should call getEffectedResource', () => { - service.afterCreateOrEditKommentar = jest.fn(); + expect(service.hideFormular).toHaveBeenCalled(); + }); - service.createKommentar(kommentar).subscribe(); + it('should reload vorgang', () => { + service.afterCreateOrEditKommentar({ + ...commandStateResource, + resource: createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), + }); - expect(service.afterCreateOrEditKommentar).toHaveBeenCalledWith(commandStateResource); - }) + expect(vorgangService.reloadCurrentVorgang).toHaveBeenCalled(); + }); - it('should call createCreateKommentarCommand', () => { - service.createCreateKommentarCommand = jest.fn(); + it('should set kommentar list on reload', () => { + service.setKommentarListReload = jest.fn(); - service.createKommentar(kommentar); + service.afterCreateOrEditKommentar({ + ...commandStateResource, + resource: createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), + }); - expect(service.createCreateKommentarCommand).toHaveBeenCalledWith(kommentar); - }) + expect(service.setKommentarListReload).toHaveBeenCalled(); + }); + }); - it('should create CreateKommentarCommand', () => { - var command: CreateKommentarCommand = service.createCreateKommentarCommand(kommentar); + describe('on command is pending', () => { + it('should do nothing', () => { + service.afterCreateOrEditKommentar({ + ...commandStateResource, + resource: createCommandResource([CommandLinkRel.UPDATE]), + }); - expect(command).toEqual({ order: CommandOrder.CREATE_KOMMENTAR, kommentar, body: null }); - }) - }) - }) + expect(commandService.getEffectedResource).not.toHaveBeenCalled(); + }); + }); + }); - describe('edit kommentar', () => { + describe('onNavigation', () => { + describe('to vorgang list', () => { + it('should set reload flag of kommentar list', () => { + service.kommentarList$.next(createEmptyStateResource()); - describe('init and next value', () => { + service.onNavigation({}); - beforeEach(() => { - commandService.createCommand.mockReturnValue(hot('-a', { a: commandStateResource })); - }) + expect(service.kommentarList$.value.reload).toEqual(true); + }); + }); - it('should be return', () => { - const result = service.editKommentar(kommentarResource, kommentar); + describe('to vorgang detail page', () => { + it('should set kommentar list to reload', () => { + service.kommentarList$.next(createEmptyStateResource()); - expect(result).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: commandStateResource })); - }) - }) + service.onNavigation({ vorgangWithEingangUrl: 'X' }); - describe('further process', () => { + expect(service.kommentarList$.value.reload).toEqual(true); + }); + }); + }); - beforeEach(() => { - commandService.createCommand.mockReturnValue(of(commandStateResource)); - }) + describe('attachments', () => { + it('should be loaded if link avaible', () => { + const kommentarResource = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); + service.getAttachments(kommentarResource); - it('should call command service', () => { - service.editKommentar(kommentarResource, kommentar); + expect(binaryFileService.getFiles).toHaveBeenCalledWith( + kommentarResource, + KommentarLinkRel.ATTACHMENTS, + ); + }); - expect(commandService.createCommand).toHaveBeenCalledWith(kommentarResource, KommentarLinkRel.EDIT, service.createEditKommentarCommand(kommentar)); - }) + it('should not be loaded if no link available', () => { + service.getAttachments(kommentarResource); - it('should call getEffectedResource', () => { - service.afterCreateOrEditKommentar = jest.fn(); + expect(binaryFileService.getFiles).not.toHaveBeenCalled(); + }); + }); - service.editKommentar(kommentarResource, kommentar).subscribe(); + describe('canCreateNewKommentar', () => { + it('should create new Kommentare', () => { + const canCreateNewKommentar$ = cold('a', { a: true }); + + const observable = service.canCreateNewKommentar( + createKommentarListResource([KommentarListLinkRel.CREATE_KOMMENTAR]), + ); - expect(service.afterCreateOrEditKommentar).toHaveBeenCalledWith(commandStateResource); - }) + expect(observable).toBeObservable(canCreateNewKommentar$); + }); - it('should call createEditKommentarCommand', () => { - service.createEditKommentarCommand = jest.fn(); + it('should not create new Kommentare if formular visible', () => { + const canCreateNewKommentar$ = cold('a', { a: false }); + service.formularVisibility$.next(true); - service.editKommentar(kommentarResource, kommentar); + const observable = service.canCreateNewKommentar( + createKommentarListResource([KommentarListLinkRel.CREATE_KOMMENTAR]), + ); - expect(service.createEditKommentarCommand).toHaveBeenCalledWith(kommentar); - }) + expect(observable).toBeObservable(canCreateNewKommentar$); + }); - it('should create CreateKommentarCommand', () => { - var command: CreateKommentarCommand = service.createEditKommentarCommand(kommentar); + it('should not create new Kommentare if link not exists', () => { + const canCreateNewKommentar$ = cold('a', { a: false }); + service.formularVisibility$.next(false); - expect(command).toEqual({ order: CommandOrder.EDIT_KOMMENTAR, kommentar, body: null }); - }) - }) - }) - - describe('afterCreateOrEditKommentar', () => { - - describe('on command is done', () => { - - const kommentarList: KommentarListResource = createKommentarListResource(); - - beforeEach(() => { - commandService.getEffectedResource.mockReturnValue(of(kommentarList)); - }) - - it('should hide formular', () => { - service.hideFormular = jest.fn(); - - service.afterCreateOrEditKommentar({ ...commandStateResource, resource: createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]) }); - - expect(service.hideFormular).toHaveBeenCalled(); - }) - - it('should reload vorgang', () => { - service.afterCreateOrEditKommentar({ ...commandStateResource, resource: createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]) }); - - expect(vorgangService.reloadCurrentVorgang).toHaveBeenCalled(); - }) - - it('should set kommentar list on reload', () => { - service.setKommentarListReload = jest.fn(); - - service.afterCreateOrEditKommentar({ ...commandStateResource, resource: createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]) }); - - expect(service.setKommentarListReload).toHaveBeenCalled(); - }) - }) - - describe('on command is pending', () => { - - it('should do nothing', () => { - service.afterCreateOrEditKommentar({ ...commandStateResource, resource: createCommandResource([CommandLinkRel.UPDATE]) }); - - expect(commandService.getEffectedResource).not.toHaveBeenCalled(); - }) - }) - }) - - describe('onNavigation', () => { - - describe('to vorgang list', () => { - - it('should set reload flag of kommentar list', () => { - service.kommentarList$.next(createEmptyStateResource()); - - service.onNavigation({}); - - expect(service.kommentarList$.value.reload).toEqual(true); - }) - }) - - describe('to vorgang detail page', () => { - - it('should set kommentar list to reload', () => { - service.kommentarList$.next(createEmptyStateResource()); - - service.onNavigation({ 'vorgangWithEingangUrl': 'X' }); - - expect(service.kommentarList$.value.reload).toEqual(true); - }) - }); - }) - - describe('attachments', () => { - it('should be loaded if link avaible', () => { - const kommentarResource = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); - service.getAttachments(kommentarResource); - - expect(binaryFileService.getFiles).toHaveBeenCalledWith( - kommentarResource, - KommentarLinkRel.ATTACHMENTS - ); - }); - - it('should not be loaded if no link available', () => { - service.getAttachments(kommentarResource); - - expect(binaryFileService.getFiles).not.toHaveBeenCalled(); - }) - }); - - describe('canCreateNewKommentar', () => { - it('should create new Kommentare', () => { - const canCreateNewKommentar$ = cold('a', {a: true}); - - const observable = service.canCreateNewKommentar(createKommentarListResource([KommentarListLinkRel.CREATE_KOMMENTAR])); - - expect(observable).toBeObservable(canCreateNewKommentar$); - }); - - it('should not create new Kommentare if formular visible', () => { - const canCreateNewKommentar$ = cold('a', {a: false}); - service.formularVisibility$.next(true); - - const observable = service.canCreateNewKommentar(createKommentarListResource([KommentarListLinkRel.CREATE_KOMMENTAR])); - - expect(observable).toBeObservable(canCreateNewKommentar$); - }); - - it('should not create new Kommentare if link not exists', () => { - const canCreateNewKommentar$ = cold('a', {a: false}); - service.formularVisibility$.next(false); - - const observable = service.canCreateNewKommentar(createKommentarListResource()); - - expect(observable).toBeObservable(canCreateNewKommentar$); - }); - }); -}) \ No newline at end of file + const observable = service.canCreateNewKommentar(createKommentarListResource()); + + expect(observable).toBeObservable(canCreateNewKommentar$); + }); + }); +}); diff --git a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts index 8f03c34a30d27f94ed20dd433f538c4510d2281f..b1be2ecc5b41cd6504ea878f9297ea4ecc1a7099 100644 --- a/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts +++ b/alfa-client/libs/kommentar-shared/src/lib/kommentar.service.ts @@ -24,135 +24,180 @@ import { Injectable } from '@angular/core'; import { Params } from '@angular/router'; import { BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared'; -import { CommandOrder, CommandResource, CommandService, CreateCommand, isDone } from '@alfa-client/command-shared'; +import { + CommandOrder, + CommandResource, + CommandService, + CreateCommand, + isDone, +} from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { createEmptyStateResource, createStateResource, doIfLoadingRequired, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + doIfLoadingRequired, + StateResource, +} from '@alfa-client/tech-shared'; import { VorgangResource, VorgangService } from '@alfa-client/vorgang-shared'; import { hasLink, Resource } from '@ngxp/rest'; import { isNil } from 'lodash-es'; import { BehaviorSubject, Observable, of, Subscription } from 'rxjs'; import { map, startWith, tap } from 'rxjs/operators'; import { KommentarLinkRel, KommentarListLinkRel } from './kommentar.linkrel'; -import { CreateKommentarCommand, Kommentar, KommentarListResource, KommentarResource } from './kommentar.model'; +import { + CreateKommentarCommand, + Kommentar, + KommentarListResource, + KommentarResource, +} from './kommentar.model'; import { KommentarRepository } from './kommentar.repository'; @Injectable({ providedIn: 'root' }) export class KommentarService { - - readonly kommentarList$: BehaviorSubject<StateResource<KommentarListResource>> = new BehaviorSubject(createEmptyStateResource<KommentarListResource>()); - readonly formularVisibility$: BehaviorSubject<boolean> = new BehaviorSubject(false); - - private navigationSub: Subscription; - - constructor( - private repository: KommentarRepository, - private commandService: CommandService, - private navigationService: NavigationService, - private vorgangService: VorgangService, - private binaryFileService: BinaryFileService, - ) { - this.listenToNavigation(); - } - - private listenToNavigation(): void { - this.unsubscribe(); - this.navigationSub = this.navigationService.urlChanged().subscribe((params: Params) => this.onNavigation(params)); - } - - private unsubscribe(): void { - if (!isNil(this.navigationSub)) this.navigationSub.unsubscribe(); - } - - onNavigation(params: Params): void { - if (NavigationService.isVorgangListPage(params)) { - this.setKommentarListOnReload(); - } - if (NavigationService.isVorgangDetailPage(params, VorgangService.VORGANG_WITH_EINGANG_URL)) { - this.setKommentarListOnReload(); - } - } - - private setKommentarListOnReload(): void { - this.kommentarList$.next({ ...this.kommentarList$.value, reload: true }); - } - - public getKommentareByVorgang(vorgang: VorgangResource): Observable<StateResource<KommentarListResource>> { - doIfLoadingRequired(this.kommentarList$.value, () => this.loadKommentare(vorgang)); - return this.kommentarList$.asObservable(); - } - - private loadKommentare(vorgang: VorgangResource): void { - this.setListLoadingTrue(); - - const sub: Subscription = this.repository.findKommentare(vorgang).subscribe((kommentarList: KommentarListResource) => { - this.setKommentarList(kommentarList); - sub.unsubscribe(); - }); - } - - setListLoadingTrue(): void { - this.kommentarList$.next({ ...this.kommentarList$.value, loading: true }); - } - - setKommentarListReload() { - this.kommentarList$.next({ ...this.kommentarList$.value, reload: true }); - } - - setKommentarList(kommentarList: KommentarListResource): void { - this.kommentarList$.next(createStateResource(kommentarList)); - } - - public isFormularVisible(): Observable<boolean> { - return this.formularVisibility$.asObservable(); - } - - public canCreateNewKommentar(kommentareListResource: KommentarListResource): Observable<boolean> { - return this.formularVisibility$.pipe( - map(formularVisibility => !formularVisibility && hasLink(kommentareListResource, KommentarListLinkRel.CREATE_KOMMENTAR))); - } - - public showFormular(): void { - this.formularVisibility$.next(true); - } - - public hideFormular(): void { - this.formularVisibility$.next(false); - } - - public createKommentar(kommentar: Kommentar): Observable<StateResource<CommandResource>> { - return this.createKommentarCommand(this.kommentarList$.value.resource, KommentarListLinkRel.CREATE_KOMMENTAR, this.createCreateKommentarCommand(kommentar)); - } - - createCreateKommentarCommand(kommentar: Kommentar): CreateKommentarCommand { - return { order: CommandOrder.CREATE_KOMMENTAR, kommentar, body: null }; - } - - public editKommentar(kommentar: KommentarResource, toPatch: Kommentar): Observable<StateResource<CommandResource>> { - return this.createKommentarCommand(kommentar, KommentarLinkRel.EDIT, this.createEditKommentarCommand(toPatch)); - } - - createEditKommentarCommand(kommentar: Kommentar): CreateKommentarCommand { - return { order: CommandOrder.EDIT_KOMMENTAR, kommentar, body: null }; - } - - createKommentarCommand(resource: Resource, linkRel: string, command: CreateCommand): Observable<StateResource<CommandResource>> { - return this.commandService.createCommand(resource, linkRel, command).pipe( - tap((createdCommand: StateResource<CommandResource>) => this.afterCreateOrEditKommentar(createdCommand)), - startWith(createEmptyStateResource<CommandResource>(true))); - } - - afterCreateOrEditKommentar(command: StateResource<CommandResource>): void { - if (isDone(command.resource)) { - this.hideFormular(); - this.setKommentarListReload(); - this.vorgangService.reloadCurrentVorgang(); - } - } - - getAttachments(kommentar: KommentarResource): Observable<StateResource<BinaryFileListResource>> { - if (hasLink(kommentar, KommentarLinkRel.ATTACHMENTS)) { - return this.binaryFileService.getFiles(kommentar, KommentarLinkRel.ATTACHMENTS); - } - return of(createEmptyStateResource<BinaryFileListResource>()); - } -} \ No newline at end of file + readonly kommentarList$: BehaviorSubject<StateResource<KommentarListResource>> = + new BehaviorSubject(createEmptyStateResource<KommentarListResource>()); + readonly formularVisibility$: BehaviorSubject<boolean> = new BehaviorSubject(false); + + private navigationSub: Subscription; + + constructor( + private repository: KommentarRepository, + private commandService: CommandService, + private navigationService: NavigationService, + private vorgangService: VorgangService, + private binaryFileService: BinaryFileService, + ) { + this.listenToNavigation(); + } + + private listenToNavigation(): void { + this.unsubscribe(); + this.navigationSub = this.navigationService + .urlChanged() + .subscribe((params: Params) => this.onNavigation(params)); + } + + private unsubscribe(): void { + if (!isNil(this.navigationSub)) this.navigationSub.unsubscribe(); + } + + onNavigation(params: Params): void { + if (NavigationService.isVorgangListPage(params)) { + this.setKommentarListOnReload(); + } + if (NavigationService.isVorgangDetailPage(params, VorgangService.VORGANG_WITH_EINGANG_URL)) { + this.setKommentarListOnReload(); + } + } + + private setKommentarListOnReload(): void { + this.kommentarList$.next({ ...this.kommentarList$.value, reload: true }); + } + + public getKommentareByVorgang( + vorgang: VorgangResource, + ): Observable<StateResource<KommentarListResource>> { + doIfLoadingRequired(this.kommentarList$.value, () => this.loadKommentare(vorgang)); + return this.kommentarList$.asObservable(); + } + + private loadKommentare(vorgang: VorgangResource): void { + this.setListLoadingTrue(); + + const sub: Subscription = this.repository + .findKommentare(vorgang) + .subscribe((kommentarList: KommentarListResource) => { + this.setKommentarList(kommentarList); + sub.unsubscribe(); + }); + } + + setListLoadingTrue(): void { + this.kommentarList$.next({ ...this.kommentarList$.value, loading: true }); + } + + setKommentarListReload() { + this.kommentarList$.next({ ...this.kommentarList$.value, reload: true }); + } + + setKommentarList(kommentarList: KommentarListResource): void { + this.kommentarList$.next(createStateResource(kommentarList)); + } + + public isFormularVisible(): Observable<boolean> { + return this.formularVisibility$.asObservable(); + } + + public canCreateNewKommentar(kommentareListResource: KommentarListResource): Observable<boolean> { + return this.formularVisibility$.pipe( + map( + (formularVisibility) => + !formularVisibility && + hasLink(kommentareListResource, KommentarListLinkRel.CREATE_KOMMENTAR), + ), + ); + } + + public showFormular(): void { + this.formularVisibility$.next(true); + } + + public hideFormular(): void { + this.formularVisibility$.next(false); + } + + public createKommentar(kommentar: Kommentar): Observable<StateResource<CommandResource>> { + return this.createKommentarCommand( + this.kommentarList$.value.resource, + KommentarListLinkRel.CREATE_KOMMENTAR, + this.createCreateKommentarCommand(kommentar), + ); + } + + createCreateKommentarCommand(kommentar: Kommentar): CreateKommentarCommand { + return { order: CommandOrder.CREATE_KOMMENTAR, kommentar, body: null }; + } + + public editKommentar( + kommentar: KommentarResource, + toPatch: Kommentar, + ): Observable<StateResource<CommandResource>> { + return this.createKommentarCommand( + kommentar, + KommentarLinkRel.EDIT, + this.createEditKommentarCommand(toPatch), + ); + } + + createEditKommentarCommand(kommentar: Kommentar): CreateKommentarCommand { + return { order: CommandOrder.EDIT_KOMMENTAR, kommentar, body: null }; + } + + createKommentarCommand( + resource: Resource, + linkRel: string, + command: CreateCommand, + ): Observable<StateResource<CommandResource>> { + return this.commandService.createCommand(resource, linkRel, command).pipe( + tap((createdCommand: StateResource<CommandResource>) => + this.afterCreateOrEditKommentar(createdCommand), + ), + startWith(createEmptyStateResource<CommandResource>(true)), + ); + } + + afterCreateOrEditKommentar(command: StateResource<CommandResource>): void { + if (isDone(command.resource)) { + this.hideFormular(); + this.setKommentarListReload(); + this.vorgangService.reloadCurrentVorgang(); + } + } + + getAttachments(kommentar: KommentarResource): Observable<StateResource<BinaryFileListResource>> { + if (hasLink(kommentar, KommentarLinkRel.ATTACHMENTS)) { + return this.binaryFileService.getFiles(kommentar, KommentarLinkRel.ATTACHMENTS); + } + return of(createEmptyStateResource<BinaryFileListResource>()); + } +} diff --git a/alfa-client/libs/kommentar-shared/src/test-setup.ts b/alfa-client/libs/kommentar-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/kommentar-shared/src/test-setup.ts +++ b/alfa-client/libs/kommentar-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/kommentar-shared/test/kommentar.ts b/alfa-client/libs/kommentar-shared/test/kommentar.ts index ec0af58009df594ffe8aa46a1ef4f1b5d9472ba7..ebe80dc1f95dd9f7c42edbbdff4097da867ea906 100644 --- a/alfa-client/libs/kommentar-shared/test/kommentar.ts +++ b/alfa-client/libs/kommentar-shared/test/kommentar.ts @@ -28,24 +28,24 @@ import { KommentarListLinkRel } from '../src/lib/kommentar.linkrel'; import { Kommentar, KommentarListResource, KommentarResource } from '../src/lib/kommentar.model'; export function createKommentar(): Kommentar { - return { - text: faker.random.words(10), - createdAt: faker.date.past(), - createdBy: faker.random.words(2), - attachments: [], - } + return { + text: faker.random.words(10), + createdAt: faker.date.past(), + createdBy: faker.random.words(2), + attachments: [], + }; } export function createKommentarResource(linkRel: string[] = []): KommentarResource { - return toResource(createKommentar(), linkRel); + return toResource(createKommentar(), linkRel); } export function createKommentarResources(linkRel: string[] = []): KommentarResource[] { - return times(10, () => createKommentarResource(linkRel)); + return times(10, () => createKommentarResource(linkRel)); } export function createKommentarListResource(linkRel: string[] = []): KommentarListResource { - return toResource({}, [...linkRel], { - [KommentarListLinkRel.KOMMENTAR_LIST]: createKommentarResources() - }); -} \ No newline at end of file + return toResource({}, [...linkRel], { + [KommentarListLinkRel.KOMMENTAR_LIST]: createKommentarResources(), + }); +} diff --git a/alfa-client/libs/kommentar-shared/tsconfig.json b/alfa-client/libs/kommentar-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/kommentar-shared/tsconfig.json +++ b/alfa-client/libs/kommentar-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/kommentar-shared/tsconfig.lib.json b/alfa-client/libs/kommentar-shared/tsconfig.lib.json index b061ae529ccfa78e6869bb8913f1eadc8b22cc25..1cc2d08ae0a5326f0b4f68921f77e265c7b9f2f4 100644 --- a/alfa-client/libs/kommentar-shared/tsconfig.lib.json +++ b/alfa-client/libs/kommentar-shared/tsconfig.lib.json @@ -1,14 +1,14 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/kommentar-shared/tsconfig.spec.json b/alfa-client/libs/kommentar-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/kommentar-shared/tsconfig.spec.json +++ b/alfa-client/libs/kommentar-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/kommentar/.eslintrc.json b/alfa-client/libs/kommentar/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/kommentar/.eslintrc.json +++ b/alfa-client/libs/kommentar/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/kommentar/jest.config.ts b/alfa-client/libs/kommentar/jest.config.ts index c6f13bcc465a9122f0ef26311b3fb716912bd0c4..543c1b0152b4221ce8b8359beeb1bc7e6af28eaf 100644 --- a/alfa-client/libs/kommentar/jest.config.ts +++ b/alfa-client/libs/kommentar/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'kommentar', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/kommentar', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'kommentar', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/kommentar', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/kommentar/project.json b/alfa-client/libs/kommentar/project.json index 1c0ddf32007fec4272a702ac1b3c0ebf2aba27e2..0e33c11c51ca9ec23c77fa5db763fd4c4d279b18 100644 --- a/alfa-client/libs/kommentar/project.json +++ b/alfa-client/libs/kommentar/project.json @@ -1,29 +1,26 @@ { - "name": "kommentar", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/kommentar/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/kommentar"], - "options": { - "tsConfig": "libs/kommentar/tsconfig.spec.json", - "jestConfig": "libs/kommentar/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/kommentar/src/**/*.ts", - "libs/kommentar/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [] + "name": "kommentar", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/kommentar/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/kommentar"], + "options": { + "tsConfig": "libs/kommentar/tsconfig.spec.json", + "jestConfig": "libs/kommentar/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/kommentar/src/**/*.ts", "libs/kommentar/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [] } diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.html b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.html index 1241941a8deb6493f0ec394f496c96bd1c54e583..da3b6072530f0402bea3dadf7dac41f97712d9ed 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.html +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.html @@ -24,37 +24,37 @@ --> <form class="form" [formGroup]="formService.form"> - - <ozgcloud-textarea-editor - [formControlName]="formServiceClass.TEXT" - label="Kommentar"> - </ozgcloud-textarea-editor> - - <alfa-binary-file-attachment-container - data-test-id="kommentar-attachment-list" - [existFiles]="attachments$ | async" - [formArrayName]="formServiceClass.FIELD_ATTACHMENTS" - [uploadStateResource]="kommentarListStateResource" - [linkRelUploadAttachment]="kommentarListLinkRel.UPLOAD_FILE"> - </alfa-binary-file-attachment-container> - - <div class="buttons"> - <ozgcloud-stroked-button-with-spinner - text="Speichern" - data-test-id="add-button" - icon="save_alt" - class="submit-button" - [stateResource]="submitInProgress$ | async" - (clickEmitter)="submit()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-stroked-button-with-spinner - text="Abbrechen" - data-test-id="cancel-button" - icon="clear" - color="" - class="cancel-button" - (clickEmitter)="cancel.emit()"> - </ozgcloud-stroked-button-with-spinner> - </div> + <ozgcloud-textarea-editor [formControlName]="formServiceClass.TEXT" label="Kommentar"> + </ozgcloud-textarea-editor> + + <alfa-binary-file-attachment-container + data-test-id="kommentar-attachment-list" + [existFiles]="attachments$ | async" + [formArrayName]="formServiceClass.FIELD_ATTACHMENTS" + [uploadStateResource]="kommentarListStateResource" + [linkRelUploadAttachment]="kommentarListLinkRel.UPLOAD_FILE" + > + </alfa-binary-file-attachment-container> + + <div class="buttons"> + <ozgcloud-stroked-button-with-spinner + text="Speichern" + data-test-id="add-button" + icon="save_alt" + class="submit-button" + [stateResource]="submitInProgress$ | async" + (clickEmitter)="submit()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-stroked-button-with-spinner + text="Abbrechen" + data-test-id="cancel-button" + icon="clear" + color="" + class="cancel-button" + (clickEmitter)="cancel.emit()" + > + </ozgcloud-stroked-button-with-spinner> + </div> </form> diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.scss b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.scss index cecafcec6a4bbf6944989258f69f58ceb276d812..b92a2604aee4d5ce6c838689a616295e4ba97518 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.scss +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.scss @@ -22,17 +22,17 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .form { - box-shadow: 0 0 4px rgba(#000, 0.32); - margin: -4px -8px 10px -8px; - padding: 8px; - border-radius: 8px; + box-shadow: 0 0 4px rgba(#000, 0.32); + margin: -4px -8px 10px -8px; + padding: 8px; + border-radius: 8px; } .buttons { - display: flex; - margin: 16px -8px; + display: flex; + margin: 16px -8px; - ozgcloud-stroked-button-with-spinner { - margin: 0 8px; - } + ozgcloud-stroked-button-with-spinner { + margin: 0 8px; + } } diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.spec.ts index f60faa541719aec6ee640b652a960b8a63d20ede..596291f3c6f4af5f8e159618671840cfe7b50fec 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.spec.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.spec.ts @@ -28,7 +28,10 @@ import { BinaryFileAttachmentContainerComponent } from '@alfa-client/binary-file import { KommentarLinkRel, KommentarService } from '@alfa-client/kommentar-shared'; import { createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { OzgcloudStrokedButtonWithSpinnerComponent, TextAreaEditorComponent } from '@alfa-client/ui'; +import { + OzgcloudStrokedButtonWithSpinnerComponent, + TextAreaEditorComponent, +} from '@alfa-client/ui'; import { MockComponent } from 'ng-mocks'; import { of } from 'rxjs'; import { createBinaryFileListResource } from '../../../../../binary-file-shared/test/binary-file'; @@ -37,80 +40,80 @@ import { KommentarFormComponent } from './kommentar-form.component'; import { KommentarFormService } from './kommentar.formservice'; describe('KommentarFormComponent', () => { - let component: KommentarFormComponent; - let fixture: ComponentFixture<KommentarFormComponent>; + let component: KommentarFormComponent; + let fixture: ComponentFixture<KommentarFormComponent>; - const formService = mock(KommentarFormService); - const kommentarService = mock(KommentarService); + const formService = mock(KommentarFormService); + const kommentarService = mock(KommentarService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - KommentarFormComponent, - MockComponent(TextAreaEditorComponent), - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(BinaryFileAttachmentContainerComponent), - ], - imports: [ - MatFormFieldModule, - ReactiveFormsModule, - ], - providers: [ - { - provide: KommentarFormService, - useValue: formService - }, - { - provide: KommentarService, - useValue: kommentarService - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + KommentarFormComponent, + MockComponent(TextAreaEditorComponent), + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(BinaryFileAttachmentContainerComponent), + ], + imports: [MatFormFieldModule, ReactiveFormsModule], + providers: [ + { + provide: KommentarFormService, + useValue: formService, + }, + { + provide: KommentarService, + useValue: kommentarService, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(KommentarFormComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(KommentarFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should call patch', () => { - const patchSpy = jest.spyOn(KommentarFormService.prototype, 'patch').mockImplementation(); - const kommentarResource = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); - component.kommentar = kommentarResource; - kommentarService.getAttachments.mockReturnValue( - of(createStateResource(createBinaryFileListResource()))); + it('should call patch', () => { + const patchSpy = jest.spyOn(KommentarFormService.prototype, 'patch').mockImplementation(); + const kommentarResource = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); + component.kommentar = kommentarResource; + kommentarService.getAttachments.mockReturnValue( + of(createStateResource(createBinaryFileListResource())), + ); - component.ngOnChanges(); + component.ngOnChanges(); - expect(patchSpy).toHaveBeenCalledWith(kommentarResource); - }) + expect(patchSpy).toHaveBeenCalledWith(kommentarResource); + }); - it('should load attachments', done => { - component.kommentar = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); - kommentarService.getAttachments.mockReturnValue( - of(createStateResource(createBinaryFileListResource()))); + it('should load attachments', (done) => { + component.kommentar = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); + kommentarService.getAttachments.mockReturnValue( + of(createStateResource(createBinaryFileListResource())), + ); - component.ngOnChanges(); + component.ngOnChanges(); - component.attachments$.subscribe(binaryFileResources => { - expect(binaryFileResources.length).toBe(10); - done(); - }); - }); + component.attachments$.subscribe((binaryFileResources) => { + expect(binaryFileResources.length).toBe(10); + done(); + }); + }); - it('should call kommentarService', () => { - const kommentarResource = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); - component.kommentar = kommentarResource; - kommentarService.getAttachments.mockReturnValue( - of(createStateResource(createBinaryFileListResource()))); + it('should call kommentarService', () => { + const kommentarResource = createKommentarResource([KommentarLinkRel.ATTACHMENTS]); + component.kommentar = kommentarResource; + kommentarService.getAttachments.mockReturnValue( + of(createStateResource(createBinaryFileListResource())), + ); - component.ngOnChanges(); + component.ngOnChanges(); - expect(kommentarService.getAttachments).toHaveBeenCalledWith(kommentarResource); - }); + expect(kommentarService.getAttachments).toHaveBeenCalledWith(kommentarResource); + }); }); diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.ts index 3eae567fee0ca1028ac5db1f478a75b6cd149d7f..bdeb563bf5b8088948be3518bb114f1c919aa90b 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar-form.component.ts @@ -23,8 +23,17 @@ */ import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; -import { KommentarListLinkRel, KommentarListResource, KommentarResource, KommentarService } from '@alfa-client/kommentar-shared'; -import { createEmptyStateResource, getEmbeddedResources, StateResource } from '@alfa-client/tech-shared'; +import { + KommentarListLinkRel, + KommentarListResource, + KommentarResource, + KommentarService, +} from '@alfa-client/kommentar-shared'; +import { + createEmptyStateResource, + getEmbeddedResources, + StateResource, +} from '@alfa-client/tech-shared'; import { isNil } from 'lodash-es'; import { Observable, of } from 'rxjs'; import { KommentarFormService } from './kommentar.formservice'; @@ -32,51 +41,53 @@ import { BinaryFileListLinkRel, BinaryFileResource } from '@alfa-client/binary-f import { map } from 'rxjs/operators'; @Component({ - selector: 'alfa-kommentar-form', - templateUrl: './kommentar-form.component.html', - styleUrls: ['./kommentar-form.component.scss'], - providers: [KommentarFormService] + selector: 'alfa-kommentar-form', + templateUrl: './kommentar-form.component.html', + styleUrls: ['./kommentar-form.component.scss'], + providers: [KommentarFormService], }) export class KommentarFormComponent implements OnChanges { + @Input() kommentar: KommentarResource; + @Input() kommentarListStateResource: StateResource<KommentarListResource>; - @Input() kommentar: KommentarResource; - @Input() kommentarListStateResource: StateResource<KommentarListResource>; + @Output() cancel: EventEmitter<void> = new EventEmitter(); - @Output() cancel: EventEmitter<void> = new EventEmitter(); + submitInProgress$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - submitInProgress$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly formServiceClass = KommentarFormService; + readonly kommentarListLinkRel = KommentarListLinkRel; - readonly formServiceClass = KommentarFormService; - readonly kommentarListLinkRel = KommentarListLinkRel; + attachments$: Observable<BinaryFileResource[]> = of([]); - attachments$: Observable<BinaryFileResource[]> = of([]); + constructor( + public formService: KommentarFormService, + public kommentarService: KommentarService, + ) {} - constructor( - public formService: KommentarFormService, - public kommentarService: KommentarService) { - } + ngOnChanges(): void { + if (!isNil(this.kommentar)) { + this.patch(); + this.updateAttachments(); + } + } - ngOnChanges(): void { - if (!isNil(this.kommentar)) { - this.patch(); - this.updateAttachments(); - } - } + private updateAttachments() { + this.attachments$ = this.kommentarService + .getAttachments(this.kommentar) + .pipe( + map((stateResource) => + getEmbeddedResources<BinaryFileResource>(stateResource, BinaryFileListLinkRel.FILE_LIST), + ), + ); + } - private updateAttachments() { - this.attachments$ = - this.kommentarService.getAttachments(this.kommentar) - .pipe(map(stateResource => - getEmbeddedResources<BinaryFileResource>( - stateResource, - BinaryFileListLinkRel.FILE_LIST))); - } + patch(): void { + this.formService.patch(this.kommentar); + } - patch(): void { - this.formService.patch(this.kommentar); - } - - submit(): void { - this.submitInProgress$ = <Observable<StateResource<CommandResource>>>this.formService.submit(); - } -} \ No newline at end of file + submit(): void { + this.submitInProgress$ = <Observable<StateResource<CommandResource>>>this.formService.submit(); + } +} diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.spec.ts index 20c913d4d65320ce6abd93fef8e9aa7eb75f31d8..b91a8edcc8adfbd8001420267d5cbc64504e6ef6 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.spec.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.spec.ts @@ -30,44 +30,43 @@ import { of } from 'rxjs'; import { KommentarFormService } from './kommentar.formservice'; describe('KommentarFormService', () => { - let formService: KommentarFormService; - let kommentarService: Mock<KommentarService>; + let formService: KommentarFormService; + let kommentarService: Mock<KommentarService>; - const formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + const formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); - beforeEach(() => { - kommentarService = mock(KommentarService); + beforeEach(() => { + kommentarService = mock(KommentarService); - formService = new KommentarFormService(formBuilder, useFromMock(kommentarService)); - }) + formService = new KommentarFormService(formBuilder, useFromMock(kommentarService)); + }); - it('should create', () => { - expect(formService).toBeTruthy(); - }); + it('should create', () => { + expect(formService).toBeTruthy(); + }); - describe('submit', () => { + describe('submit', () => { + const kommentarResource: KommentarResource = createKommentarResource(); - const kommentarResource: KommentarResource = createKommentarResource(); + beforeEach(() => { + kommentarService.createKommentar.mockReturnValue(of(createEmptyStateResource())); + kommentarService.editKommentar.mockReturnValue(of(createEmptyStateResource())); + }); - beforeEach(() => { - kommentarService.createKommentar.mockReturnValue(of(createEmptyStateResource())); - kommentarService.editKommentar.mockReturnValue(of(createEmptyStateResource())); - }) + it('should call createKommentar', () => { + formService.source = null; - it('should call createKommentar', () => { - formService.source = null; + formService.submit(); - formService.submit(); + expect(kommentarService.createKommentar).toHaveBeenCalled(); + }); - expect(kommentarService.createKommentar).toHaveBeenCalled(); - }) + it('should call editKommentar', () => { + formService.source = kommentarResource; - it('should call editKommentar', () => { - formService.source = kommentarResource; + formService.submit(); - formService.submit(); - - expect(kommentarService.editKommentar).toHaveBeenCalled(); - }) - }) -}) \ No newline at end of file + expect(kommentarService.editKommentar).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts index 3aa929471bee1a59451d3ab32d09e48d9defeed0..c7c3d53062cf74f0100f7a99a10cc06ee5f8b4fd 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-form/kommentar.formservice.ts @@ -21,45 +21,47 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Injectable } from "@angular/core"; +import { Injectable } from '@angular/core'; import { - UntypedFormArray, - UntypedFormBuilder, - UntypedFormControl, - UntypedFormGroup -} from "@angular/forms"; -import { KommentarService } from "@alfa-client/kommentar-shared"; -import { AbstractFormService, StateResource } from "@alfa-client/tech-shared"; -import { Observable } from "rxjs"; + UntypedFormArray, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, +} from '@angular/forms'; +import { KommentarService } from '@alfa-client/kommentar-shared'; +import { AbstractFormService, StateResource } from '@alfa-client/tech-shared'; +import { Observable } from 'rxjs'; @Injectable() export class KommentarFormService extends AbstractFormService { + static readonly TEXT = 'text'; - static readonly TEXT = 'text'; + static readonly FIELD_PATH_PREFIX = 'kommentar'; + static readonly FIELD_ATTACHMENTS = 'attachments'; - static readonly FIELD_PATH_PREFIX = 'kommentar'; - static readonly FIELD_ATTACHMENTS = 'attachments'; + constructor( + formBuilder: UntypedFormBuilder, + private kommentarService: KommentarService, + ) { + super(formBuilder); + } - constructor(formBuilder: UntypedFormBuilder, private kommentarService: KommentarService) { - super(formBuilder); - } + protected initForm(): UntypedFormGroup { + return this.formBuilder.group({ + [KommentarFormService.TEXT]: new UntypedFormControl(null), + [KommentarFormService.FIELD_ATTACHMENTS]: new UntypedFormArray([]), + }); + } - protected initForm(): UntypedFormGroup { - return this.formBuilder.group({ - [KommentarFormService.TEXT]: new UntypedFormControl(null), - [KommentarFormService.FIELD_ATTACHMENTS]: new UntypedFormArray([]), - }) - } + protected doSubmit(): Observable<StateResource<any>> { + if (this.isPatch()) { + return this.kommentarService.editKommentar(this.getSourceValue(), this.getFormValue()); + } else { + return this.kommentarService.createKommentar(this.getFormValue()); + } + } - protected doSubmit(): Observable<StateResource<any>> { - if (this.isPatch()) { - return this.kommentarService.editKommentar(this.getSourceValue(), this.getFormValue()); - } else { - return this.kommentarService.createKommentar(this.getFormValue()); - } - } - - protected getPathPrefix(): string { - return KommentarFormService.FIELD_PATH_PREFIX; - } -} \ No newline at end of file + protected getPathPrefix(): string { + return KommentarFormService.FIELD_PATH_PREFIX; + } +} diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.html b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.html index 5c5d9566c2ae3ab9835d9a0f12e135cf29644912..9ea845e79f37a5613ef41b8beb9754307af15a7f 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.html +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.html @@ -24,29 +24,30 @@ --> <ng-container *ngIf="kommentarListStateResource$ | async as kommentarListStateResource"> - - <ozgcloud-expansion-panel headline="Kommentare"> - <alfa-kommentar-list-in-vorgang - [kommentarListStateResource]="kommentarListStateResource" - data-test-id="kommentar-list-in-vorgang"> - </alfa-kommentar-list-in-vorgang> - </ozgcloud-expansion-panel> - - <alfa-kommentar-form - *ngIf="showFormular$ | async" - [kommentarListStateResource]="kommentarListStateResource$ | async" - (cancel)="hideFormular()" - class="kommentar-form" - data-test-id="kommentar-formular"> - </alfa-kommentar-form> - - <ozgcloud-stroked-button-with-spinner - *ngIf="canCreateNewKommentar$ | async" - (clickEmitter)="showFormular()" - class="create-button" - text="Kommentar" - icon="add" - dataTestId="create-kommentar"> - </ozgcloud-stroked-button-with-spinner> - + <ozgcloud-expansion-panel headline="Kommentare"> + <alfa-kommentar-list-in-vorgang + [kommentarListStateResource]="kommentarListStateResource" + data-test-id="kommentar-list-in-vorgang" + > + </alfa-kommentar-list-in-vorgang> + </ozgcloud-expansion-panel> + + <alfa-kommentar-form + *ngIf="showFormular$ | async" + [kommentarListStateResource]="kommentarListStateResource$ | async" + (cancel)="hideFormular()" + class="kommentar-form" + data-test-id="kommentar-formular" + > + </alfa-kommentar-form> + + <ozgcloud-stroked-button-with-spinner + *ngIf="canCreateNewKommentar$ | async" + (clickEmitter)="showFormular()" + class="create-button" + text="Kommentar" + icon="add" + dataTestId="create-kommentar" + > + </ozgcloud-stroked-button-with-spinner> </ng-container> diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.scss b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.scss index 34df99009d27d3f026108d3e1dfdd88e227f0324..c8a63472e7796cb91979dbc24ea800af419756f6 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.scss +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.scss @@ -23,6 +23,6 @@ */ .create-button, .kommentar-form { - display: block; - margin-left: 56px; + display: block; + margin-left: 56px; } diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts index 82ce366d4f5491d5f1c42afd816b967c627ce869..0a2f6753751869a4fe19341c0ce1f85c267ea0bd 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.spec.ts @@ -25,7 +25,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { KommentarListLinkRel, KommentarService } from '@alfa-client/kommentar-shared'; import { createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { ExpansionPanelComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + ExpansionPanelComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { cold } from 'jest-marbles'; import { MockComponent } from 'ng-mocks'; import { Observable } from 'rxjs'; @@ -36,132 +39,152 @@ import { KommentarListInVorgangContainerComponent } from './kommentar-list-in-vo import { KommentarListInVorgangComponent } from './kommentar-list-in-vorgang/kommentar-list-in-vorgang.component'; describe('KommentarListInVorgangContainerComponent', () => { - let component: KommentarListInVorgangContainerComponent; - let fixture: ComponentFixture<KommentarListInVorgangContainerComponent>; - - const kommentarService = mock(KommentarService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - KommentarListInVorgangContainerComponent, - MockComponent(ExpansionPanelComponent), - MockComponent(KommentarListInVorgangComponent), - MockComponent(KommentarFormComponent), - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent) - ], - providers: [ - { - provide: KommentarService, - useValue: kommentarService - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(KommentarListInVorgangContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - component.vorgangStateResource = createStateResource(createVorgangWithEingangResource()); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ng on changes', () => { - - beforeEach(() => { - kommentarService.isFormularVisible.mockReturnValue(new Observable(o => o.next(false))); - kommentarService.getKommentareByVorgang.mockReturnValue(new Observable(o => - o.next(createStateResource(createKommentarListResource([KommentarListLinkRel.CREATE_KOMMENTAR]))))); - }); - - it('should call kommentar service isFormularVisible', () => { - component.ngOnChanges(); - - expect(kommentarService.isFormularVisible).toHaveBeenCalled(); - }) - - it('should call kommentar service getKommentareByVorgang', () => { - component.ngOnChanges(); - - expect(kommentarService.getKommentareByVorgang).toHaveBeenCalledWith(component.vorgangStateResource.resource); - }) - - it('should create new Kommentare', () => { - const canCreateNewKommentar$ = cold('a', { a: true }); - const kommentarListStateResource = createStateResource(createKommentarListResource()); - const kommentarListStateResource$ = new Observable(observer => observer.next(kommentarListStateResource)); - kommentarService.getKommentareByVorgang.mockReturnValue(kommentarListStateResource$); - kommentarService.canCreateNewKommentar.mockReturnValue(new Observable(observer => observer.next(true))); - - component.ngOnChanges(); - - expect(component.canCreateNewKommentar$).toBeObservable(canCreateNewKommentar$); - }); - - it('should not create new Kommentare', () => { - const canCreateNewKommentar$ = cold('a', { a: false }); - const kommentarListStateResource = createStateResource(createKommentarListResource()); - const kommentarListStateResource$ = new Observable(observer => observer.next(kommentarListStateResource)); - kommentarService.getKommentareByVorgang.mockReturnValue(kommentarListStateResource$); - kommentarService.canCreateNewKommentar.mockReturnValue(new Observable(observer => observer.next(false))); - - component.ngOnChanges(); - - expect(component.canCreateNewKommentar$).toBeObservable(canCreateNewKommentar$) - }); - - it('should call reloadKommentarListOnVorgangReload', () => { - const reloadKommentarListOnVorgangReload = jest.spyOn(component, 'reloadKommentarListOnVorgangReload').mockReturnThis(); - - component.ngOnChanges(); - - expect(reloadKommentarListOnVorgangReload).toHaveBeenCalled(); - }); - }) - - describe('reloadKommentarListOnVorgangReload', () => { - - beforeEach(() => { - kommentarService.setKommentarListReload.mockClear(); - }); - - it('should call kommentarService', () => { - component.vorgangStateResource = { ...createStateResource(createVorgangWithEingangResource()), reload: true }; - - component.reloadKommentarListOnVorgangReload(); - - expect(kommentarService.setKommentarListReload).toBeCalled(); - }); - - it('should not call kommentarService', () => { - component.vorgangStateResource = { ...createStateResource(createVorgangWithEingangResource()), reload: false }; - - component.reloadKommentarListOnVorgangReload(); - - expect(kommentarService.setKommentarListReload).not.toBeCalled(); - }); - - }); - - describe('show formular', () => { - - it('should call kommentar service showFormular', () => { - component.showFormular(); - - expect(kommentarService.showFormular).toHaveBeenCalled(); - }) - }) - - describe('hide formular', () => { - - it('should call kommentar service hideFormular', () => { - component.hideFormular(); - - expect(kommentarService.hideFormular).toHaveBeenCalled(); - }) - }) + let component: KommentarListInVorgangContainerComponent; + let fixture: ComponentFixture<KommentarListInVorgangContainerComponent>; + + const kommentarService = mock(KommentarService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + KommentarListInVorgangContainerComponent, + MockComponent(ExpansionPanelComponent), + MockComponent(KommentarListInVorgangComponent), + MockComponent(KommentarFormComponent), + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + ], + providers: [ + { + provide: KommentarService, + useValue: kommentarService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(KommentarListInVorgangContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + component.vorgangStateResource = createStateResource(createVorgangWithEingangResource()); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ng on changes', () => { + beforeEach(() => { + kommentarService.isFormularVisible.mockReturnValue(new Observable((o) => o.next(false))); + kommentarService.getKommentareByVorgang.mockReturnValue( + new Observable((o) => + o.next( + createStateResource( + createKommentarListResource([KommentarListLinkRel.CREATE_KOMMENTAR]), + ), + ), + ), + ); + }); + + it('should call kommentar service isFormularVisible', () => { + component.ngOnChanges(); + + expect(kommentarService.isFormularVisible).toHaveBeenCalled(); + }); + + it('should call kommentar service getKommentareByVorgang', () => { + component.ngOnChanges(); + + expect(kommentarService.getKommentareByVorgang).toHaveBeenCalledWith( + component.vorgangStateResource.resource, + ); + }); + + it('should create new Kommentare', () => { + const canCreateNewKommentar$ = cold('a', { a: true }); + const kommentarListStateResource = createStateResource(createKommentarListResource()); + const kommentarListStateResource$ = new Observable((observer) => + observer.next(kommentarListStateResource), + ); + kommentarService.getKommentareByVorgang.mockReturnValue(kommentarListStateResource$); + kommentarService.canCreateNewKommentar.mockReturnValue( + new Observable((observer) => observer.next(true)), + ); + + component.ngOnChanges(); + + expect(component.canCreateNewKommentar$).toBeObservable(canCreateNewKommentar$); + }); + + it('should not create new Kommentare', () => { + const canCreateNewKommentar$ = cold('a', { a: false }); + const kommentarListStateResource = createStateResource(createKommentarListResource()); + const kommentarListStateResource$ = new Observable((observer) => + observer.next(kommentarListStateResource), + ); + kommentarService.getKommentareByVorgang.mockReturnValue(kommentarListStateResource$); + kommentarService.canCreateNewKommentar.mockReturnValue( + new Observable((observer) => observer.next(false)), + ); + + component.ngOnChanges(); + + expect(component.canCreateNewKommentar$).toBeObservable(canCreateNewKommentar$); + }); + + it('should call reloadKommentarListOnVorgangReload', () => { + const reloadKommentarListOnVorgangReload = jest + .spyOn(component, 'reloadKommentarListOnVorgangReload') + .mockReturnThis(); + + component.ngOnChanges(); + + expect(reloadKommentarListOnVorgangReload).toHaveBeenCalled(); + }); + }); + + describe('reloadKommentarListOnVorgangReload', () => { + beforeEach(() => { + kommentarService.setKommentarListReload.mockClear(); + }); + + it('should call kommentarService', () => { + component.vorgangStateResource = { + ...createStateResource(createVorgangWithEingangResource()), + reload: true, + }; + + component.reloadKommentarListOnVorgangReload(); + + expect(kommentarService.setKommentarListReload).toBeCalled(); + }); + + it('should not call kommentarService', () => { + component.vorgangStateResource = { + ...createStateResource(createVorgangWithEingangResource()), + reload: false, + }; + + component.reloadKommentarListOnVorgangReload(); + + expect(kommentarService.setKommentarListReload).not.toBeCalled(); + }); + }); + + describe('show formular', () => { + it('should call kommentar service showFormular', () => { + component.showFormular(); + + expect(kommentarService.showFormular).toHaveBeenCalled(); + }); + }); + + describe('hide formular', () => { + it('should call kommentar service hideFormular', () => { + component.hideFormular(); + + expect(kommentarService.hideFormular).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts index d76267edeb866e298405a3a2ea44c9e27a38597a..4cf48be4ea8611d3cdf38724a27ce13ff14b9b23 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang-container.component.ts @@ -28,40 +28,43 @@ import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { mergeMap, Observable } from 'rxjs'; @Component({ - selector: 'alfa-kommentar-list-in-vorgang-container', - templateUrl: './kommentar-list-in-vorgang-container.component.html', - styleUrls: ['./kommentar-list-in-vorgang-container.component.scss'] + selector: 'alfa-kommentar-list-in-vorgang-container', + templateUrl: './kommentar-list-in-vorgang-container.component.html', + styleUrls: ['./kommentar-list-in-vorgang-container.component.scss'], }) export class KommentarListInVorgangContainerComponent implements OnChanges { + @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; - @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; + showFormular$: Observable<boolean>; + kommentarListStateResource$: Observable<StateResource<KommentarListResource>>; + canCreateNewKommentar$: Observable<boolean>; - showFormular$: Observable<boolean>; - kommentarListStateResource$: Observable<StateResource<KommentarListResource>>; - canCreateNewKommentar$: Observable<boolean>; + constructor(private kommentarService: KommentarService) {} - constructor(private kommentarService: KommentarService) { - } + ngOnChanges(): void { + this.reloadKommentarListOnVorgangReload(); + this.showFormular$ = this.kommentarService.isFormularVisible(); + this.kommentarListStateResource$ = this.kommentarService.getKommentareByVorgang( + this.vorgangStateResource.resource, + ); + this.canCreateNewKommentar$ = this.kommentarListStateResource$.pipe( + mergeMap((stateResource) => + this.kommentarService.canCreateNewKommentar(stateResource.resource), + ), + ); + } - ngOnChanges(): void { - this.reloadKommentarListOnVorgangReload(); - this.showFormular$ = this.kommentarService.isFormularVisible(); - this.kommentarListStateResource$ = this.kommentarService.getKommentareByVorgang(this.vorgangStateResource.resource); - this.canCreateNewKommentar$ = this.kommentarListStateResource$.pipe( - mergeMap(stateResource => this.kommentarService.canCreateNewKommentar(stateResource.resource))); - } + reloadKommentarListOnVorgangReload(): void { + if (this.vorgangStateResource.reload) { + this.kommentarService.setKommentarListReload(); + } + } - reloadKommentarListOnVorgangReload(): void { - if (this.vorgangStateResource.reload) { - this.kommentarService.setKommentarListReload(); - } - } + showFormular(): void { + this.kommentarService.showFormular(); + } - showFormular(): void { - this.kommentarService.showFormular(); - } - - hideFormular(): void { - this.kommentarService.hideFormular(); - } -} \ No newline at end of file + hideFormular(): void { + this.kommentarService.hideFormular(); + } +} diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.html b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.html index 08b77849d4bcc954f1e256b58b8c36181ab50a67..bc9ba080b68be7dc82aebbf03b4c9631c0762bd2 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.html +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.html @@ -24,7 +24,8 @@ --> <alfa-kommentar-list-item-in-vorgang - *ngFor="let kommentar of kommentare" - [kommentar]="kommentar" - [kommentarListStateResource]="kommentarListStateResource"> + *ngFor="let kommentar of kommentare" + [kommentar]="kommentar" + [kommentarListStateResource]="kommentarListStateResource" +> </alfa-kommentar-list-item-in-vorgang> diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.scss b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.scss index 425cdee074d68fe2a6258f67faa1eee376980c50..2fcbb95dfebce69326d426229558079770e09125 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.scss +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.scss @@ -22,6 +22,6 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.spec.ts index b3f685ebb0ac25c4317ff573dfcaa6b517bd747a..5704671bafe64cf3f4baa826f3254b5daa4d153d 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.spec.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.spec.ts @@ -25,52 +25,57 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MockComponent } from 'ng-mocks'; import { KommentarListInVorgangComponent } from './kommentar-list-in-vorgang.component'; import { KommentarListItemInVorgangComponent } from './kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component'; -import { createEmptyStateResource, createStateResource, EMPTY_ARRAY } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + EMPTY_ARRAY, +} from '@alfa-client/tech-shared'; import { createKommentarListResource } from '../../../../../kommentar-shared/test/kommentar'; import { KommentarListLinkRel } from '@alfa-client/kommentar-shared'; describe('KommentarListInVorgangComponent', () => { - let component: KommentarListInVorgangComponent; - let fixture: ComponentFixture<KommentarListInVorgangComponent>; + let component: KommentarListInVorgangComponent; + let fixture: ComponentFixture<KommentarListInVorgangComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - KommentarListInVorgangComponent, - MockComponent(KommentarListItemInVorgangComponent)] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + KommentarListInVorgangComponent, + MockComponent(KommentarListItemInVorgangComponent), + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(KommentarListInVorgangComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(KommentarListInVorgangComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('getKommentare', () => { - it('should return empty array if state resource is null', () => { - component.kommentarListStateResource = null; + describe('getKommentare', () => { + it('should return empty array if state resource is null', () => { + component.kommentarListStateResource = null; - expect(component.getKommentare()).toEqual(EMPTY_ARRAY); - }); + expect(component.getKommentare()).toEqual(EMPTY_ARRAY); + }); - it('should return empty array if resource is null', () => { - component.kommentarListStateResource = createEmptyStateResource(); + it('should return empty array if resource is null', () => { + component.kommentarListStateResource = createEmptyStateResource(); - expect(component.getKommentare()).toEqual(EMPTY_ARRAY); - }); + expect(component.getKommentare()).toEqual(EMPTY_ARRAY); + }); - it('should return embedded resource', () => { - const kommentareListResource = createKommentarListResource(); - component.kommentarListStateResource = createStateResource(kommentareListResource); + it('should return embedded resource', () => { + const kommentareListResource = createKommentarListResource(); + component.kommentarListStateResource = createStateResource(kommentareListResource); - expect(component.getKommentare()).toEqual( - kommentareListResource._embedded[KommentarListLinkRel.KOMMENTAR_LIST]); - }) - - }); + expect(component.getKommentare()).toEqual( + kommentareListResource._embedded[KommentarListLinkRel.KOMMENTAR_LIST], + ); + }); + }); }); diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.ts index 06dfcbf9b30545ce69b6fbbcbe2e99a2ee512e89..6ba9ad4d61ddc064b50cfea69cb43cb8a19aa90e 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-in-vorgang.component.ts @@ -24,26 +24,26 @@ import { Component, Input, OnChanges } from '@angular/core'; import { KommentarListResource, KommentarResource } from '@alfa-client/kommentar-shared'; import { KommentarListLinkRel } from 'libs/kommentar-shared/src/lib/kommentar.linkrel'; -import { getEmbeddedResources, StateResource } from "@alfa-client/tech-shared"; +import { getEmbeddedResources, StateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-kommentar-list-in-vorgang', - templateUrl: './kommentar-list-in-vorgang.component.html', - styleUrls: ['./kommentar-list-in-vorgang.component.scss'] + selector: 'alfa-kommentar-list-in-vorgang', + templateUrl: './kommentar-list-in-vorgang.component.html', + styleUrls: ['./kommentar-list-in-vorgang.component.scss'], }) export class KommentarListInVorgangComponent implements OnChanges { + @Input() kommentarListStateResource: StateResource<KommentarListResource>; - @Input() kommentarListStateResource: StateResource<KommentarListResource>; + kommentare: KommentarResource[]; - kommentare: KommentarResource[]; + ngOnChanges(): void { + this.kommentare = this.getKommentare(); + } - ngOnChanges(): void { - this.kommentare = this.getKommentare(); - } - - getKommentare(): KommentarResource[] { - return getEmbeddedResources( - this.kommentarListStateResource, - KommentarListLinkRel.KOMMENTAR_LIST); - } -} \ No newline at end of file + getKommentare(): KommentarResource[] { + return getEmbeddedResources( + this.kommentarListStateResource, + KommentarListLinkRel.KOMMENTAR_LIST, + ); + } +} diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.html b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.html index 7410a769b37fcb0d2eb54265dcfafc7aae02a346..9a94d2795a84d8bad27b23be6e11bde8eec441c3 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.html +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.html @@ -25,29 +25,38 @@ --> <div *ngIf="!editMode" class="plain-text"> - <button [attr.data-test-id]="'kommentar-item-' + (kommentar.text | convertForDataTest)" - (click)="edit()"> - <div class="kommentar-head"> - <alfa-user-profile-in-kommentar-container class="username" - *ngIf="kommentar | hasLink: kommentarLinkRel.CREATED_BY" [kommentar]="kommentar" - data-test-class="kommentar-created-by"></alfa-user-profile-in-kommentar-container> - <span data-test-id="kommentar-created-at" - class="date">{{ kommentar.createdAt | formatDateWithTimePipe: false }}</span> - </div> - <p class="text">{{ kommentar.text }}</p> - </button> - - <alfa-horizontal-binary-file-list - *ngIf="kommentar | hasLink: kommentarLinkRel.ATTACHMENTS" - [deletable]="false" - [fileListResource]="attachments$ | async"> - </alfa-horizontal-binary-file-list> + <button + [attr.data-test-id]="'kommentar-item-' + (kommentar.text | convertForDataTest)" + (click)="edit()" + > + <div class="kommentar-head"> + <alfa-user-profile-in-kommentar-container + class="username" + *ngIf="kommentar | hasLink: kommentarLinkRel.CREATED_BY" + [kommentar]="kommentar" + data-test-class="kommentar-created-by" + ></alfa-user-profile-in-kommentar-container> + <span data-test-id="kommentar-created-at" class="date">{{ + kommentar.createdAt | formatDateWithTimePipe: false + }}</span> + </div> + <p class="text">{{ kommentar.text }}</p> + </button> + + <alfa-horizontal-binary-file-list + *ngIf="kommentar | hasLink: kommentarLinkRel.ATTACHMENTS" + [deletable]="false" + [fileListResource]="attachments$ | async" + > + </alfa-horizontal-binary-file-list> </div> <alfa-kommentar-form - *ngIf="editMode" data-test-id="kommentar-list-item-form" - [kommentar]="kommentar" - [kommentarListStateResource]="kommentarListStateResource" - (cancel)="editMode = false" - class="edit-text"> -</alfa-kommentar-form> \ No newline at end of file + *ngIf="editMode" + data-test-id="kommentar-list-item-form" + [kommentar]="kommentar" + [kommentarListStateResource]="kommentarListStateResource" + (cancel)="editMode = false" + class="edit-text" +> +</alfa-kommentar-form> diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.scss b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.scss index 995cd8b0e8c71faf6f76adb0ddcf4ab8d8275e5e..bf52bd6b8383f611228097a4f129859c93fbdf78 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.scss +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.scss @@ -22,63 +22,63 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - margin-right: 8px; + margin-right: 8px; } button { - display: block; - border: 0; - background-color: transparent; - text-align: left; - width: 100%; - color: inherit; + display: block; + border: 0; + background-color: transparent; + text-align: left; + width: 100%; + color: inherit; } .kommentar-head { - display: flex; - align-items: center; - opacity: 0.8; - cursor: pointer; + display: flex; + align-items: center; + opacity: 0.8; + cursor: pointer; - ::ng-deep { - alfa-user-icon { - transform: scale(0.7); - margin-left: -4px; - } - } + ::ng-deep { + alfa-user-icon { + transform: scale(0.7); + margin-left: -4px; + } + } - .username { - flex-shrink: 2; - min-width: 0; - } - - .date { - flex-shrink: 0; - font-size: 13px; - } + .username { + flex-shrink: 2; + min-width: 0; + } + + .date { + flex-shrink: 0; + font-size: 13px; + } } .text { - &:hover, - &:focus-within { - cursor: pointer; - } + &:hover, + &:focus-within { + cursor: pointer; + } } .plain-text { - margin: -4px -8px 8px -8px; - padding: 4px 8px; - outline: 0; + margin: -4px -8px 8px -8px; + padding: 4px 8px; + outline: 0; - p { - margin-bottom: 2px; - } + p { + margin-bottom: 2px; + } - &:hover, - &:focus-within { - box-shadow: 0 0 4px rgba(#000, 0.24); - border-radius: 8px; - transition: all 3s ease-in-out; - transition-property: margin, padding; - } + &:hover, + &:focus-within { + box-shadow: 0 0 4px rgba(#000, 0.24); + border-radius: 8px; + transition: all 3s ease-in-out; + transition-property: margin, padding; + } } diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.spec.ts index 8ca44648b9adbdad19c01ca7822022422c411cc0..5fb8038d00b8e733a4cc6c0b3a6663f5678344c5 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.spec.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.spec.ts @@ -24,11 +24,23 @@ import { registerLocaleData } from '@angular/common'; import localeDe from '@angular/common/locales/de'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { KommentarLinkRel, KommentarListLinkRel, KommentarService } from '@alfa-client/kommentar-shared'; -import { ConvertForDataTestPipe, createStateResource, FormatDateWithTimePipe, HasLinkPipe } from '@alfa-client/tech-shared'; +import { + KommentarLinkRel, + KommentarListLinkRel, + KommentarService, +} from '@alfa-client/kommentar-shared'; +import { + ConvertForDataTestPipe, + createStateResource, + FormatDateWithTimePipe, + HasLinkPipe, +} from '@alfa-client/tech-shared'; import { getElementFromFixture, mock } from '@alfa-client/test-utils'; import { UserProfileInKommentarContainerComponent } from '@alfa-client/user-profile'; -import { createKommentarListResource, createKommentarResource } from 'libs/kommentar-shared/test/kommentar'; +import { + createKommentarListResource, + createKommentarResource, +} from 'libs/kommentar-shared/test/kommentar'; import { getDataTestClassOf } from 'libs/tech-shared/test/data-test'; import { MockComponent } from 'ng-mocks'; import { KommentarFormComponent } from '../../kommentar-form/kommentar-form.component'; @@ -37,91 +49,88 @@ import { KommentarListItemInVorgangComponent } from './kommentar-list-item-in-vo registerLocaleData(localeDe); describe('KommentarListItemInVorgangComponent', () => { - let component: KommentarListItemInVorgangComponent; - let fixture: ComponentFixture<KommentarListItemInVorgangComponent>; - - const userProfile: string = getDataTestClassOf('kommentar-created-by'); - const kommentarService = mock(KommentarService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HasLinkPipe, - KommentarListItemInVorgangComponent, - ConvertForDataTestPipe, - FormatDateWithTimePipe, - MockComponent(KommentarFormComponent), - MockComponent(UserProfileInKommentarContainerComponent) - ], - providers: [ - { - provide: KommentarService, - useValue: kommentarService - } - ] - - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(KommentarListItemInVorgangComponent); - component = fixture.componentInstance; - component.kommentar = createKommentarResource(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }) - - describe('user profile', () => { - - it('should be visible on existing link', () => { - component.kommentar = createKommentarResource([KommentarLinkRel.CREATED_BY]); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, userProfile); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should be hidden if link is missing', () => { - component.kommentar = createKommentarResource(); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, userProfile); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('kommentare attachments', () => { - it('should be loaded', () => { - const kommentarResource = createKommentarResource(); - component.kommentar = kommentarResource; - - component.ngOnInit(); - - expect(kommentarService.getAttachments).toHaveBeenCalledWith(kommentarResource); - }); - }) - - describe('edit', () => { - - it('should change editMode', () => { - component.kommentar = createKommentarResource([KommentarLinkRel.EDIT]); - - component.edit(); - - expect(component.editMode).toBeTruthy(); - }); - - it('should not change editMode', () => { - component.kommentar = createKommentarResource(); - - component.edit(); - - expect(component.editMode).toBeFalsy(); - }); - }); + let component: KommentarListItemInVorgangComponent; + let fixture: ComponentFixture<KommentarListItemInVorgangComponent>; + + const userProfile: string = getDataTestClassOf('kommentar-created-by'); + const kommentarService = mock(KommentarService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HasLinkPipe, + KommentarListItemInVorgangComponent, + ConvertForDataTestPipe, + FormatDateWithTimePipe, + MockComponent(KommentarFormComponent), + MockComponent(UserProfileInKommentarContainerComponent), + ], + providers: [ + { + provide: KommentarService, + useValue: kommentarService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(KommentarListItemInVorgangComponent); + component = fixture.componentInstance; + component.kommentar = createKommentarResource(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('user profile', () => { + it('should be visible on existing link', () => { + component.kommentar = createKommentarResource([KommentarLinkRel.CREATED_BY]); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, userProfile); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should be hidden if link is missing', () => { + component.kommentar = createKommentarResource(); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, userProfile); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('kommentare attachments', () => { + it('should be loaded', () => { + const kommentarResource = createKommentarResource(); + component.kommentar = kommentarResource; + + component.ngOnInit(); + + expect(kommentarService.getAttachments).toHaveBeenCalledWith(kommentarResource); + }); + }); + + describe('edit', () => { + it('should change editMode', () => { + component.kommentar = createKommentarResource([KommentarLinkRel.EDIT]); + + component.edit(); + + expect(component.editMode).toBeTruthy(); + }); + + it('should not change editMode', () => { + component.kommentar = createKommentarResource(); + + component.edit(); + + expect(component.editMode).toBeFalsy(); + }); + }); }); diff --git a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.ts b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.ts index 419e259b2c5256c14a6f4be4f90bb69f0698b7e3..cef05d891f9c234628f469ab09273aea77624ee5 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component.ts @@ -23,34 +23,40 @@ */ import { Component, Input, OnInit } from '@angular/core'; import { BinaryFileListResource } from '@alfa-client/binary-file-shared'; -import { KommentarLinkRel, KommentarListResource, KommentarResource, KommentarService } from '@alfa-client/kommentar-shared'; -import { StateResource, createEmptyStateResource } from "@alfa-client/tech-shared"; +import { + KommentarLinkRel, + KommentarListResource, + KommentarResource, + KommentarService, +} from '@alfa-client/kommentar-shared'; +import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; import { hasLink } from '@ngxp/rest'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-kommentar-list-item-in-vorgang', - templateUrl: './kommentar-list-item-in-vorgang.component.html', - styleUrls: ['./kommentar-list-item-in-vorgang.component.scss'] + selector: 'alfa-kommentar-list-item-in-vorgang', + templateUrl: './kommentar-list-item-in-vorgang.component.html', + styleUrls: ['./kommentar-list-item-in-vorgang.component.scss'], }) export class KommentarListItemInVorgangComponent implements OnInit { - @Input() kommentar: KommentarResource; + @Input() kommentar: KommentarResource; - @Input() kommentarListStateResource: StateResource<KommentarListResource>; - attachments$: Observable<StateResource<BinaryFileListResource>> = of(createEmptyStateResource<BinaryFileListResource>()); + @Input() kommentarListStateResource: StateResource<KommentarListResource>; + attachments$: Observable<StateResource<BinaryFileListResource>> = of( + createEmptyStateResource<BinaryFileListResource>(), + ); - editMode: boolean = false; + editMode: boolean = false; - readonly kommentarLinkRel = KommentarLinkRel; + readonly kommentarLinkRel = KommentarLinkRel; - constructor(public kommentarService: KommentarService) { - } + constructor(public kommentarService: KommentarService) {} - ngOnInit(): void { - this.attachments$ = this.kommentarService.getAttachments(this.kommentar); - } + ngOnInit(): void { + this.attachments$ = this.kommentarService.getAttachments(this.kommentar); + } - edit(): void { - this.editMode = hasLink(this.kommentar, KommentarLinkRel.EDIT); - } -} \ No newline at end of file + edit(): void { + this.editMode = hasLink(this.kommentar, KommentarLinkRel.EDIT); + } +} diff --git a/alfa-client/libs/kommentar/src/lib/kommentar.module.spec.ts b/alfa-client/libs/kommentar/src/lib/kommentar.module.spec.ts index 7cc6173851039fbb978cd42279d58dca8c5f558a..8352fb0073070bfefe625d603bd1f9d5ddd5ff62 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar.module.spec.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { KommentarModule } from './kommentar.module'; describe('KommentarModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [KommentarModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [KommentarModule], + }).compileComponents(); + }); - it('should create', () => { - expect(KommentarModule).toBeDefined(); - }); + it('should create', () => { + expect(KommentarModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/kommentar/src/lib/kommentar.module.ts b/alfa-client/libs/kommentar/src/lib/kommentar.module.ts index 04a6c821be85f95cc3282be4998aac445b372f6f..4043430c112718e7ee98cb7c4063413b618a9f85 100644 --- a/alfa-client/libs/kommentar/src/lib/kommentar.module.ts +++ b/alfa-client/libs/kommentar/src/lib/kommentar.module.ts @@ -35,23 +35,21 @@ import { KommentarListInVorgangComponent } from './kommentar-list-in-vorgang-con import { KommentarListItemInVorgangComponent } from './kommentar-list-in-vorgang-container/kommentar-list-in-vorgang/kommentar-list-item-in-vorgang/kommentar-list-item-in-vorgang.component'; @NgModule({ - imports: [ - CommonModule, - VorgangSharedModule, - UiModule, - KommentarSharedModule, - TechSharedModule, - UserProfileModule, - BinaryFileModule, - ], - declarations: [ - KommentarListInVorgangContainerComponent, - KommentarFormComponent, - KommentarListInVorgangComponent, - KommentarListItemInVorgangComponent, - ], - exports: [ - KommentarListInVorgangContainerComponent - ] + imports: [ + CommonModule, + VorgangSharedModule, + UiModule, + KommentarSharedModule, + TechSharedModule, + UserProfileModule, + BinaryFileModule, + ], + declarations: [ + KommentarListInVorgangContainerComponent, + KommentarFormComponent, + KommentarListInVorgangComponent, + KommentarListItemInVorgangComponent, + ], + exports: [KommentarListInVorgangContainerComponent], }) -export class KommentarModule { } \ No newline at end of file +export class KommentarModule {} diff --git a/alfa-client/libs/kommentar/src/test-setup.ts b/alfa-client/libs/kommentar/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/kommentar/src/test-setup.ts +++ b/alfa-client/libs/kommentar/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/kommentar/tsconfig.json b/alfa-client/libs/kommentar/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/kommentar/tsconfig.json +++ b/alfa-client/libs/kommentar/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/kommentar/tsconfig.lib.json b/alfa-client/libs/kommentar/tsconfig.lib.json index b061ae529ccfa78e6869bb8913f1eadc8b22cc25..1cc2d08ae0a5326f0b4f68921f77e265c7b9f2f4 100644 --- a/alfa-client/libs/kommentar/tsconfig.lib.json +++ b/alfa-client/libs/kommentar/tsconfig.lib.json @@ -1,14 +1,14 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/kommentar/tsconfig.spec.json b/alfa-client/libs/kommentar/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/kommentar/tsconfig.spec.json +++ b/alfa-client/libs/kommentar/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/loesch-anforderung-shared/.eslintrc.json b/alfa-client/libs/loesch-anforderung-shared/.eslintrc.json index 7b7b6231394b8c5674ce1b007077d4327aea7fda..9416ef7fe3c2643718ea92627388bf35847fc788 100644 --- a/alfa-client/libs/loesch-anforderung-shared/.eslintrc.json +++ b/alfa-client/libs/loesch-anforderung-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - }, - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ] - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + }, + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"] + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/loesch-anforderung-shared/jest.config.ts b/alfa-client/libs/loesch-anforderung-shared/jest.config.ts index 931f64023f1225fab28046af577396dadc735eb0..ee079e21fbd87d916eeeda95efd017f12aee2fa2 100644 --- a/alfa-client/libs/loesch-anforderung-shared/jest.config.ts +++ b/alfa-client/libs/loesch-anforderung-shared/jest.config.ts @@ -1,23 +1,23 @@ /* eslint-disable */ export default { - displayName: 'loeschanforderung-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/loeschanforderung-shared', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'loeschanforderung-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/loeschanforderung-shared', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/loesch-anforderung-shared/project.json b/alfa-client/libs/loesch-anforderung-shared/project.json index ba6e021524d7a517b4ecd2062a0d1b383a06d6cb..63d38d0f7fb7933bf4129427ed075951a5d57d62 100644 --- a/alfa-client/libs/loesch-anforderung-shared/project.json +++ b/alfa-client/libs/loesch-anforderung-shared/project.json @@ -1,31 +1,29 @@ { - "name": "loesch-anforderung-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/loesch-anforderung-shared/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": [ - "{workspaceRoot}/coverage/libs/loesch-anforderung-shared" - ], - "options": { - "tsConfig": "libs/loesch-anforderung-shared/tsconfig.spec.json", - "jestConfig": "libs/loesch-anforderung-shared/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "libs/loesch-anforderung-shared/**/*.ts", - "libs/loesch-anforderung-shared/**/*.html" - ] - } - } - }, - "tags": [] + "name": "loesch-anforderung-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/loesch-anforderung-shared/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/loesch-anforderung-shared"], + "options": { + "tsConfig": "libs/loesch-anforderung-shared/tsconfig.spec.json", + "jestConfig": "libs/loesch-anforderung-shared/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": [ + "libs/loesch-anforderung-shared/**/*.ts", + "libs/loesch-anforderung-shared/**/*.html" + ] + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.actions.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.actions.ts index d5f9cf974a9fd6df506495b3a29db997a1234120..59b5d6f757ebe77eba790a274d9898d72e439fb6 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.actions.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.actions.ts @@ -1,21 +1,36 @@ import { HttpErrorResponse } from '@angular/common/http'; -import { ApiErrorAction, TypedActionCreator, TypedActionCreatorWithProps } from '@alfa-client/tech-shared'; +import { + ApiErrorAction, + TypedActionCreator, + TypedActionCreatorWithProps, +} from '@alfa-client/tech-shared'; import { VorgangWithEingangAction } from '@alfa-client/vorgang-shared'; import { createAction, props } from '@ngrx/store'; import { LoeschAnforderungResource } from '../loesch-anforderung.model'; export interface LoeschAnforderungProps { - loeschAnforderung: LoeschAnforderungResource + loeschAnforderung: LoeschAnforderungResource; } -export const loadLoeschAnforderung: TypedActionCreatorWithProps<VorgangWithEingangAction> = createAction('[LoeschAnforderung] Load LoeschAnforderung', props<VorgangWithEingangAction>()); -export const loadLoeschAnforderungSuccess: TypedActionCreatorWithProps<LoeschAnforderungProps> = createAction('[LoeschAnforderung] Load LoeschAnforderung Success', props<LoeschAnforderungProps>()); -export const loadLoeschAnforderungFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[LoeschAnforderung] Load LoeschAnforderung Failure', props<ApiErrorAction>()); +export const loadLoeschAnforderung: TypedActionCreatorWithProps<VorgangWithEingangAction> = + createAction('[LoeschAnforderung] Load LoeschAnforderung', props<VorgangWithEingangAction>()); +export const loadLoeschAnforderungSuccess: TypedActionCreatorWithProps<LoeschAnforderungProps> = + createAction( + '[LoeschAnforderung] Load LoeschAnforderung Success', + props<LoeschAnforderungProps>(), + ); +export const loadLoeschAnforderungFailure: TypedActionCreatorWithProps<ApiErrorAction> = + createAction('[LoeschAnforderung] Load LoeschAnforderung Failure', props<ApiErrorAction>()); export interface LoeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps { - error: HttpErrorResponse, - overviewUrl: string + error: HttpErrorResponse; + overviewUrl: string; } -export const loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess: TypedActionCreator = createAction('[LoeschAnforderung] LoeschAnforderung zurücknehmen reload vorgang success'); -export const loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure: TypedActionCreatorWithProps<LoeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps> = createAction('[LoeschAnforderung] LoeschAnforderung zurücknehmen reload vorgang failure', props<LoeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps>()); \ No newline at end of file +export const loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess: TypedActionCreator = + createAction('[LoeschAnforderung] LoeschAnforderung zurücknehmen reload vorgang success'); +export const loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure: TypedActionCreatorWithProps<LoeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps> = + createAction( + '[LoeschAnforderung] LoeschAnforderung zurücknehmen reload vorgang failure', + props<LoeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps>(), + ); diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.spec.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.spec.ts index 63c5e7b06f013b8ad4e1616b5feabca086d8b9af..bd4000d3c06e395b24cf02f835d7c45b7a8589bc 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.spec.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.spec.ts @@ -1,6 +1,11 @@ import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; -import { COMMAND_ERROR_MESSAGES, CommandErrorMessage, CommandOrder, CommandResource } from '@alfa-client/command-shared'; +import { + COMMAND_ERROR_MESSAGES, + CommandErrorMessage, + CommandOrder, + CommandResource, +} from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; import { ApiError } from '@alfa-client/tech-shared'; import { Mock, mock } from '@alfa-client/test-utils'; @@ -26,121 +31,138 @@ import * as VorgangActions from '../../../../vorgang-shared/src/lib/+state/vorga import * as LoeschAnforderungActions from './loesch-anforderung.actions'; describe('LoeschAnforderungEffects', () => { - let actions: Observable<Action>; - let effects: LoeschAnforderungEffects; - - const repository: Mock<LoeschAnforderungRepository> = mock(LoeschAnforderungRepository); - const snackbarService: Mock<SnackBarService> = mock(SnackBarService); - const navigationService: Mock<NavigationService> = mock(NavigationService); - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - LoeschAnforderungEffects, - provideMockActions(() => actions), - provideMockStore(), - { - provide: LoeschAnforderungRepository, - useValue: repository - }, - { - provide: SnackBarService, - useValue: snackbarService - }, - { - provide: NavigationService, - useValue: navigationService - } - ] - }); - - effects = TestBed.inject(LoeschAnforderungEffects); - }); - - describe('loadLoeschAnforderung', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.LOESCH_ANFORDERUNG]); - const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); - - it('should call repository', () => { - actions = of(action); - - effects.loadLoeschAnforderung$.subscribe(); - - expect(repository.getLoeschAnforderung).toHaveBeenCalledWith(vorgangWithEingang); - }) - - it('should dispatch loadLoeschAnforderungSuccess action', () => { - const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); - repository.getLoeschAnforderung.mockReturnValue(of(loeschAnforderung)); - - actions = hot('-a-|', { a: action }); - - const expected = hot('-a-|', { a: LoeschAnforderungActions.loadLoeschAnforderungSuccess({ loeschAnforderung }) }); - expect(effects.loadLoeschAnforderung$).toBeObservable(expected); - }) - - it('should dispatch loadLoeschAnforderungFailure action', () => { - const apiError: ApiError = createApiError() - const error = { error: { error: apiError } }; - const errorResponse = cold('-#', {}, error); - repository.getLoeschAnforderung = jest.fn(() => errorResponse); - - const expected = cold('--b', { b: LoeschAnforderungActions.loadLoeschAnforderungFailure({ apiError }) }); - actions = hot('-a', { a: action }); - - expect(effects.loadLoeschAnforderung$).toBeObservable(expected); - }) - }) - - describe('showVorgangLoeschenSuccessSnackbar', () => { - - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.VORGANG_LOESCHEN }; - const action = CommandActions.createCommandSuccess({ command }); - - it('should call sncakbarService on vorgangLoeschen command', () => { - actions = of(action) - - effects.showVorgangLoeschenSuccessSnackbar$.subscribe(); - - expect(snackbarService.show).toHaveBeenCalled(); - }) - }) - - describe('loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess', () => { - - const action = LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess(); - - it('should show snackbar', () => { - actions = of(action) - - effects.loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess$.subscribe(); - - expect(snackbarService.showError).toHaveBeenCalledWith(COMMAND_ERROR_MESSAGES[CommandErrorMessage.CONCURRENT_MODIFICATION]); - }) - }) - - describe('loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure', () => { - - const error: HttpErrorResponse = { ...createHttpErrorResponse(), status: HttpStatusCode.NotFound}; - const actionError = <HttpErrorResponse>{ error }; - const overviewUrl: string = faker.internet.url(); - const action = LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure({ error: actionError, overviewUrl }); - - it('should show snackbar', () => { - actions = of(action) - - effects.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure$.subscribe(); - - expect(snackbarService.showInfo).toHaveBeenCalledWith('Der Vorgang wurde zwischenzeitlich gelöscht.'); - }) - - it('should navigate to overview', () => { - actions = of(action) - - effects.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure$.subscribe(); - - expect(navigationService.navigate).toHaveBeenCalledWith(overviewUrl); - }) - }) -}); \ No newline at end of file + let actions: Observable<Action>; + let effects: LoeschAnforderungEffects; + + const repository: Mock<LoeschAnforderungRepository> = mock(LoeschAnforderungRepository); + const snackbarService: Mock<SnackBarService> = mock(SnackBarService); + const navigationService: Mock<NavigationService> = mock(NavigationService); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + LoeschAnforderungEffects, + provideMockActions(() => actions), + provideMockStore(), + { + provide: LoeschAnforderungRepository, + useValue: repository, + }, + { + provide: SnackBarService, + useValue: snackbarService, + }, + { + provide: NavigationService, + useValue: navigationService, + }, + ], + }); + + effects = TestBed.inject(LoeschAnforderungEffects); + }); + + describe('loadLoeschAnforderung', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.LOESCH_ANFORDERUNG, + ]); + const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); + + it('should call repository', () => { + actions = of(action); + + effects.loadLoeschAnforderung$.subscribe(); + + expect(repository.getLoeschAnforderung).toHaveBeenCalledWith(vorgangWithEingang); + }); + + it('should dispatch loadLoeschAnforderungSuccess action', () => { + const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); + repository.getLoeschAnforderung.mockReturnValue(of(loeschAnforderung)); + + actions = hot('-a-|', { a: action }); + + const expected = hot('-a-|', { + a: LoeschAnforderungActions.loadLoeschAnforderungSuccess({ loeschAnforderung }), + }); + expect(effects.loadLoeschAnforderung$).toBeObservable(expected); + }); + + it('should dispatch loadLoeschAnforderungFailure action', () => { + const apiError: ApiError = createApiError(); + const error = { error: { error: apiError } }; + const errorResponse = cold('-#', {}, error); + repository.getLoeschAnforderung = jest.fn(() => errorResponse); + + const expected = cold('--b', { + b: LoeschAnforderungActions.loadLoeschAnforderungFailure({ apiError }), + }); + actions = hot('-a', { a: action }); + + expect(effects.loadLoeschAnforderung$).toBeObservable(expected); + }); + }); + + describe('showVorgangLoeschenSuccessSnackbar', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.VORGANG_LOESCHEN, + }; + const action = CommandActions.createCommandSuccess({ command }); + + it('should call sncakbarService on vorgangLoeschen command', () => { + actions = of(action); + + effects.showVorgangLoeschenSuccessSnackbar$.subscribe(); + + expect(snackbarService.show).toHaveBeenCalled(); + }); + }); + + describe('loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess', () => { + const action = + LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess(); + + it('should show snackbar', () => { + actions = of(action); + + effects.loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess$.subscribe(); + + expect(snackbarService.showError).toHaveBeenCalledWith( + COMMAND_ERROR_MESSAGES[CommandErrorMessage.CONCURRENT_MODIFICATION], + ); + }); + }); + + describe('loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure', () => { + const error: HttpErrorResponse = { + ...createHttpErrorResponse(), + status: HttpStatusCode.NotFound, + }; + const actionError = <HttpErrorResponse>{ error }; + const overviewUrl: string = faker.internet.url(); + const action = + LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure({ + error: actionError, + overviewUrl, + }); + + it('should show snackbar', () => { + actions = of(action); + + effects.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure$.subscribe(); + + expect(snackbarService.showInfo).toHaveBeenCalledWith( + 'Der Vorgang wurde zwischenzeitlich gelöscht.', + ); + }); + + it('should navigate to overview', () => { + actions = of(action); + + effects.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure$.subscribe(); + + expect(navigationService.navigate).toHaveBeenCalledWith(overviewUrl); + }); + }); +}); diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.ts index ae0e6199e23c01b4928ccd1518110f6848a0d996..96026b85333813532b18255cfaf54d796b1369be 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.ts @@ -1,5 +1,11 @@ import { Injectable } from '@angular/core'; -import { COMMAND_ERROR_MESSAGES, CREATE_COMMAND_MESSAGE_BY_ORDER, CommandErrorMessage, CommandProps, LOESCH_ANFORDERUNG_ZURUECKNEHMEN_CONCURRENT_TO_DELETE_VORGANG_MESSAGE } from '@alfa-client/command-shared'; +import { + COMMAND_ERROR_MESSAGES, + CREATE_COMMAND_MESSAGE_BY_ORDER, + CommandErrorMessage, + CommandProps, + LOESCH_ANFORDERUNG_ZURUECKNEHMEN_CONCURRENT_TO_DELETE_VORGANG_MESSAGE, +} from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; import { getApiErrorFromHttpErrorResponse, isNotFound } from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; @@ -18,32 +24,82 @@ import * as LoeschAnforderungActions from './loesch-anforderung.actions'; @Injectable() export class LoeschAnforderungEffects { + constructor( + private readonly actions$: Actions, + private repository: LoeschAnforderungRepository, + private snackBarService: SnackBarService, + private navigationService: NavigationService, + ) {} - constructor(private readonly actions$: Actions, private repository: LoeschAnforderungRepository, private snackBarService: SnackBarService, private navigationService: NavigationService) { } + loadLoeschAnforderung$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.loadVorgangWithEingangSuccess), + filter((props: VorgangWithEingangAction) => + hasLink(props.vorgangWithEingang, VorgangWithEingangLinkRel.LOESCH_ANFORDERUNG), + ), + switchMap((props: VorgangWithEingangAction) => + this.repository.getLoeschAnforderung(props.vorgangWithEingang).pipe( + map((loeschAnforderung) => + LoeschAnforderungActions.loadLoeschAnforderungSuccess({ loeschAnforderung }), + ), + catchError((error) => + of( + LoeschAnforderungActions.loadLoeschAnforderungFailure({ + apiError: getApiErrorFromHttpErrorResponse(error), + }), + ), + ), + ), + ), + ), + ); - loadLoeschAnforderung$ = createEffect(() => this.actions$.pipe(ofType(VorgangActions.loadVorgangWithEingangSuccess), - filter((props: VorgangWithEingangAction) => hasLink(props.vorgangWithEingang, VorgangWithEingangLinkRel.LOESCH_ANFORDERUNG)), - switchMap((props: VorgangWithEingangAction) => this.repository.getLoeschAnforderung(props.vorgangWithEingang).pipe( - map(loeschAnforderung => LoeschAnforderungActions.loadLoeschAnforderungSuccess({ loeschAnforderung })), - catchError(error => of(LoeschAnforderungActions.loadLoeschAnforderungFailure({ apiError: getApiErrorFromHttpErrorResponse(error) })))) - ) - )) + showVorgangLoeschenSuccessSnackbar$ = createEffect( + () => + this.actions$.pipe( + ofType(CommandActions.createCommandSuccess), + filter((props: CommandProps) => isVorgangLoeschenCommand(props.command.order)), + tap((props: CommandProps) => + this.snackBarService.show( + props.command, + CREATE_COMMAND_MESSAGE_BY_ORDER[props.command.order], + ), + ), + ), + { dispatch: false }, + ); - showVorgangLoeschenSuccessSnackbar$ = createEffect(() => this.actions$.pipe(ofType(CommandActions.createCommandSuccess), - filter((props: CommandProps) => isVorgangLoeschenCommand(props.command.order)), - tap((props: CommandProps) => this.snackBarService.show(props.command, CREATE_COMMAND_MESSAGE_BY_ORDER[props.command.order])) - ), { dispatch: false }); + loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess$ = createEffect( + () => + this.actions$.pipe( + ofType( + LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess, + ), + tap(() => + this.snackBarService.showError( + COMMAND_ERROR_MESSAGES[CommandErrorMessage.CONCURRENT_MODIFICATION], + ), + ), + ), + { dispatch: false }, + ); - - loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess$ = createEffect(() => this.actions$.pipe(ofType(LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess), - tap(() => this.snackBarService.showError(COMMAND_ERROR_MESSAGES[CommandErrorMessage.CONCURRENT_MODIFICATION])) - ), { dispatch: false }); - - loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure$ = createEffect(() => this.actions$.pipe(ofType(LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure), - filter((props: LoeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps) => isNotFound(props.error.error.status)), - tap((props: LoeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps) => { - this.snackBarService.showInfo(LOESCH_ANFORDERUNG_ZURUECKNEHMEN_CONCURRENT_TO_DELETE_VORGANG_MESSAGE); - this.navigationService.navigate(props.overviewUrl); - }) - ), { dispatch: false }); -} \ No newline at end of file + loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure$ = createEffect( + () => + this.actions$.pipe( + ofType( + LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure, + ), + filter((props: LoeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps) => + isNotFound(props.error.error.status), + ), + tap((props: LoeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps) => { + this.snackBarService.showInfo( + LOESCH_ANFORDERUNG_ZURUECKNEHMEN_CONCURRENT_TO_DELETE_VORGANG_MESSAGE, + ); + this.navigationService.navigate(props.overviewUrl); + }), + ), + { dispatch: false }, + ); +} diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.facade.spec.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.facade.spec.ts index cf32ecd73156a27b2dea89592439040614200055..7605ec6aa2eb5f224a2ed1053bf5d575d18fd73e 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.facade.spec.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.facade.spec.ts @@ -15,119 +15,121 @@ import * as LoeschAnforderungActions from './loesch-anforderung.actions'; import * as LoeschAnforderungSelectors from './loesch-anforderung.selectors'; describe('LoeschAnforderungFacade', () => { - let facade: LoeschAnforderungFacade; - let store: Mock<Store>; - - let selectionSubject: Subject<any>; - - beforeEach(() => { - store = mock(Store); - - selectionSubject = new Subject(); - - store.select.mockReturnValue(selectionSubject); - store.dispatch = jest.fn(); - - facade = new LoeschAnforderungFacade(useFromMock(<any>store)); - }) - - it('is initialized', () => { - expect(facade).toBeTruthy(); - }) - - describe('LoeschAnfordernCommand', () => { - - it('should select from store', () => { - facade.getLoeschenAnfordernCommand(); - - expect(store.select).toHaveBeenCalledWith(LoeschAnforderungSelectors.loeschenAnfordernCommand); - }) - }) - - describe('getLoeschAnforderung', () => { - - it('should select from store', () => { - facade.getLoeschAnforderung(); - - expect(store.select).toHaveBeenCalledWith(LoeschAnforderungSelectors.loeschAnforderung); - }) - }) - - describe('loadLoeschAnforderung', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - it('should dispatch loadLoeschAnforderung', () => { - facade.loadLoeschAnforderung(vorgangWithEingang); - - expect(store.dispatch).toHaveBeenCalledWith(LoeschAnforderungActions.loadLoeschAnforderung({ vorgangWithEingang })); - }) - }) - - describe('loeschenAnfordern', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const command: CreateCommand = createCreateCommand(); - - it('should dispatch createCommand action', () => { - facade.loeschenAnfordern(vorgangWithEingang, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ - resource: vorgangWithEingang, - linkRel: VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN, - command - })); - }) - }) - - describe('getEndgueltigLoeschenCommand', () => { - - it('should select from store', () => { - facade.getEndgueltigLoeschenCommand(); - - expect(store.select).toHaveBeenCalledWith(LoeschAnforderungSelectors.vorgangLoeschenCommand); - }) - }) - - describe('endgueltigLoeschen', () => { - - const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); - const command: Command = createCommand(); - - it('should dispatch action', () => { - facade.endgueltigLoeschen(loeschAnforderung, command); - - const createCommandAction = CommandActions.createCommand({ - resource: loeschAnforderung, - linkRel: LoeschAnforderungLinkRel.EXECUTE_LOESCHEN, - command - }) - expect(store.dispatch).toHaveBeenCalledWith(createCommandAction); - }) - }) - - describe('getLoeschAnforderungZuruecknehmenCommand', () => { - - it('should select from store', () => { - facade.getLoeschAnforderungZuruecknehmenCommand(); - - expect(store.select).toHaveBeenCalledWith(LoeschAnforderungSelectors.loeschAnforderungZuruecknehmenCommand); - }) - }) - - describe('loeschAnforderungZuruecknehmen', () => { - - it('should dispatch action', () => { - const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); - const command: Command = createCommand(); - - facade.loeschAnforderungZuruecknehmen(loeschAnforderung, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ - resource: loeschAnforderung, - linkRel: LoeschAnforderungLinkRel.ZURUECKNEHMEN, - command - })); - }) - }) -}) \ No newline at end of file + let facade: LoeschAnforderungFacade; + let store: Mock<Store>; + + let selectionSubject: Subject<any>; + + beforeEach(() => { + store = mock(Store); + + selectionSubject = new Subject(); + + store.select.mockReturnValue(selectionSubject); + store.dispatch = jest.fn(); + + facade = new LoeschAnforderungFacade(useFromMock(<any>store)); + }); + + it('is initialized', () => { + expect(facade).toBeTruthy(); + }); + + describe('LoeschAnfordernCommand', () => { + it('should select from store', () => { + facade.getLoeschenAnfordernCommand(); + + expect(store.select).toHaveBeenCalledWith( + LoeschAnforderungSelectors.loeschenAnfordernCommand, + ); + }); + }); + + describe('getLoeschAnforderung', () => { + it('should select from store', () => { + facade.getLoeschAnforderung(); + + expect(store.select).toHaveBeenCalledWith(LoeschAnforderungSelectors.loeschAnforderung); + }); + }); + + describe('loadLoeschAnforderung', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + it('should dispatch loadLoeschAnforderung', () => { + facade.loadLoeschAnforderung(vorgangWithEingang); + + expect(store.dispatch).toHaveBeenCalledWith( + LoeschAnforderungActions.loadLoeschAnforderung({ vorgangWithEingang }), + ); + }); + }); + + describe('loeschenAnfordern', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const command: CreateCommand = createCreateCommand(); + + it('should dispatch createCommand action', () => { + facade.loeschenAnfordern(vorgangWithEingang, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN, + command, + }), + ); + }); + }); + + describe('getEndgueltigLoeschenCommand', () => { + it('should select from store', () => { + facade.getEndgueltigLoeschenCommand(); + + expect(store.select).toHaveBeenCalledWith(LoeschAnforderungSelectors.vorgangLoeschenCommand); + }); + }); + + describe('endgueltigLoeschen', () => { + const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); + const command: Command = createCommand(); + + it('should dispatch action', () => { + facade.endgueltigLoeschen(loeschAnforderung, command); + + const createCommandAction = CommandActions.createCommand({ + resource: loeschAnforderung, + linkRel: LoeschAnforderungLinkRel.EXECUTE_LOESCHEN, + command, + }); + expect(store.dispatch).toHaveBeenCalledWith(createCommandAction); + }); + }); + + describe('getLoeschAnforderungZuruecknehmenCommand', () => { + it('should select from store', () => { + facade.getLoeschAnforderungZuruecknehmenCommand(); + + expect(store.select).toHaveBeenCalledWith( + LoeschAnforderungSelectors.loeschAnforderungZuruecknehmenCommand, + ); + }); + }); + + describe('loeschAnforderungZuruecknehmen', () => { + it('should dispatch action', () => { + const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); + const command: Command = createCommand(); + + facade.loeschAnforderungZuruecknehmen(loeschAnforderung, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: loeschAnforderung, + linkRel: LoeschAnforderungLinkRel.ZURUECKNEHMEN, + command, + }), + ); + }); + }); +}); diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.facade.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.facade.ts index cb8cad98be6cc70bd97227018b47aea992a6f5e8..f8c60008d4184056126e7e104a89da9d7236cb96 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.facade.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.facade.ts @@ -13,38 +13,64 @@ import * as LoeschAnforderungSelectors from './loesch-anforderung.selectors'; @Injectable() export class LoeschAnforderungFacade { + constructor(private readonly store: Store) {} - constructor(private readonly store: Store) { } + public getLoeschenAnfordernCommand(): Observable<StateResource<CommandResource>> { + return this.store.select(LoeschAnforderungSelectors.loeschenAnfordernCommand); + } - public getLoeschenAnfordernCommand(): Observable<StateResource<CommandResource>> { - return this.store.select(LoeschAnforderungSelectors.loeschenAnfordernCommand); - } + public getLoeschAnforderung(): Observable<StateResource<LoeschAnforderungResource>> { + return this.store.select(LoeschAnforderungSelectors.loeschAnforderung); + } - public getLoeschAnforderung(): Observable<StateResource<LoeschAnforderungResource>> { - return this.store.select(LoeschAnforderungSelectors.loeschAnforderung); - } + public loadLoeschAnforderung(vorgangWithEingang: VorgangWithEingangResource): void { + this.store.dispatch(LoeschAnforderungActions.loadLoeschAnforderung({ vorgangWithEingang })); + } - public loadLoeschAnforderung(vorgangWithEingang: VorgangWithEingangResource): void { - this.store.dispatch(LoeschAnforderungActions.loadLoeschAnforderung({ vorgangWithEingang })); - } + public loeschenAnfordern( + vorgangWithEingang: VorgangWithEingangResource, + command: CreateCommand, + ): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN, + command, + }), + ); + } - public loeschenAnfordern(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN, command })); - } + public getEndgueltigLoeschenCommand(): Observable<StateResource<CommandResource>> { + return this.store.select(LoeschAnforderungSelectors.vorgangLoeschenCommand); + } - public getEndgueltigLoeschenCommand(): Observable<StateResource<CommandResource>> { - return this.store.select(LoeschAnforderungSelectors.vorgangLoeschenCommand); - } + public endgueltigLoeschen( + loeschAnforderung: LoeschAnforderungResource, + command: CreateCommand, + ): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: loeschAnforderung, + linkRel: LoeschAnforderungLinkRel.EXECUTE_LOESCHEN, + command, + }), + ); + } - public endgueltigLoeschen(loeschAnforderung: LoeschAnforderungResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: loeschAnforderung, linkRel: LoeschAnforderungLinkRel.EXECUTE_LOESCHEN, command })); - } + public getLoeschAnforderungZuruecknehmenCommand(): Observable<StateResource<CommandResource>> { + return this.store.select(LoeschAnforderungSelectors.loeschAnforderungZuruecknehmenCommand); + } - public getLoeschAnforderungZuruecknehmenCommand(): Observable<StateResource<CommandResource>> { - return this.store.select(LoeschAnforderungSelectors.loeschAnforderungZuruecknehmenCommand); - } - - public loeschAnforderungZuruecknehmen(loeschAnforderung: LoeschAnforderungResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: loeschAnforderung, linkRel: LoeschAnforderungLinkRel.ZURUECKNEHMEN, command })); - } -} \ No newline at end of file + public loeschAnforderungZuruecknehmen( + loeschAnforderung: LoeschAnforderungResource, + command: CreateCommand, + ): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: loeschAnforderung, + linkRel: LoeschAnforderungLinkRel.ZURUECKNEHMEN, + command, + }), + ); + } +} diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.spec.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.spec.ts index e18cb942d4bb3be9bc0d61b8719163676a03f061..518f2d056a131f9430f4369037a736548183a35c 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.spec.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.spec.ts @@ -1,5 +1,10 @@ import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; -import { ApiError, createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + ApiError, + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { Action } from '@ngrx/store'; import { TypedAction } from '@ngrx/store/src/models'; @@ -18,257 +23,309 @@ import * as VorgangActions from '../../../../vorgang-shared/src/lib/+state/vorga import * as LoeschAnforderungActions from './loesch-anforderung.actions'; describe('LoeschAnforderung Reducer', () => { - - describe('unknown action', () => { - - it('should return current state', () => { - const action = {} as Action; - - const result = reducer(initialState, action); - - expect(result).toBe(initialState); - }) - }) - - describe('LoeschAnforderung', () => { - - describe('on "loadLoeschAnforderungSuccess" action', () => { - - it('should set loeschenAnfordernResource', () => { - const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); - const action = LoeschAnforderungActions.loadLoeschAnforderungSuccess({ loeschAnforderung }); - - const state: LoeschAnforderungState = reducer(initialState, action); - - expect(state.loeschAnforderung).toEqual(createStateResource(loeschAnforderung)); - }) - }) - - describe('on "loadLoeschAnforderungFailure" action', () => { - - it('should set loeschenAnfordernResource as errorStateResource', () => { - const apiError: ApiError = createApiError(); - const action = LoeschAnforderungActions.loadLoeschAnforderungFailure({ apiError }); - - const state: LoeschAnforderungState = reducer(initialState, action); - - expect(state.loeschAnforderung).toEqual(createErrorStateResource(apiError)); - }) - }) - }) - - describe('VorgangZumLoeschenMarkieren', () => { - - describe('on "createCommand" action', () => { - - it('should set vorgangLoeschenCommand loading', () => { - const action = CommandActions.createCommand({ - command: { ...createCommand(), order: CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN }, - resource: createVorgangWithEingangResource(), - linkRel: LoeschAnforderungLinkRel.EXECUTE_LOESCHEN - }); - - const state: LoeschAnforderungState = reducer(initialState, action); - - expect(state.loeschenAnfordernCommand.loading).toBeTruthy(); - }) - }) - - describe('on "createCommandSuccess" action', () => { - - it('should set vorgangLoeschenCommand as StateResource', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN }; - const action = CommandActions.createCommandSuccess({ command }); - - const state: LoeschAnforderungState = reducer(initialState, action); - - expect(state.loeschenAnfordernCommand).toEqual(createStateResource(command)); - }) - }) - - describe('on "revokeCommandSuccess" action', () => { - - it('should clear loeschAnforderung', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN }; - const action = CommandActions.revokeCommandSuccess({ command }); - - const state: LoeschAnforderungState = reducer({ ...initialState, loeschAnforderung: createStateResource(createLoeschAnforderungResource()) }, action); - - expect(state.loeschAnforderung).toEqual(createEmptyStateResource()); - }) - }) - }) - - describe('VorgangLoeschen', () => { - - describe('on "createCommand" action', () => { - - it('should set vorgangLoeschenCommand loading', () => { - const action = CommandActions.createCommand({ - command: { ...createCommand(), order: CommandOrder.VORGANG_LOESCHEN }, - resource: createVorgangWithEingangResource(), - linkRel: LoeschAnforderungLinkRel.EXECUTE_LOESCHEN - }); - - const state: LoeschAnforderungState = reducer(initialState, action); - - expect(state.vorgangLoeschenCommand.loading).toBeTruthy(); - }) - }) - - describe('on "createCommandSuccess" action', () => { - - it('should set vorgangLoeschenCommand as StateResource', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.VORGANG_LOESCHEN }; - const action = CommandActions.createCommandSuccess({ command }); - - const state: LoeschAnforderungState = reducer(initialState, action); - - expect(state.vorgangLoeschenCommand).toEqual(createStateResource(command)); - }) - }) - }) - - describe('LoeschAnforderungZuruecknehmen', () => { - - describe('on "createCommand" action', () => { - - it('should set loeschAnforderungZuruecknehmenCommand loading', () => { - const action = CommandActions.createCommand({ - command: { ...createCommand(), order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN }, - resource: createVorgangWithEingangResource(), - linkRel: LoeschAnforderungLinkRel.ZURUECKNEHMEN - }); - - const state: LoeschAnforderungState = reducer(initialState, action); - - expect(state.loeschAnforderungZuruecknehmenCommand.loading).toBeTruthy(); - }) - }) - - describe('on "createCommandSuccess" action', () => { - - it('should set loeschAnforderungZuruecknehmenCommand as StateResource', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN }; - const action = CommandActions.createCommandSuccess({ command }); - - const state: LoeschAnforderungState = reducer(initialState, action); - - expect(state.loeschAnforderungZuruecknehmenCommand).toEqual(createStateResource(command)); - }) - - it('should clear LoeschAnforderung state', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN }; - const action = CommandActions.createCommandSuccess({ command }); - - const state: LoeschAnforderungState = reducer({ - ...initialState, - loeschAnforderung: createStateResource(createLoeschAnforderungResource()) - }, action); - - expect(state.loeschAnforderung).toEqual(createEmptyStateResource()); - }) - }) - - describe('on "createCommandFailure" action', () => { - - it('should set loeschAnforderungZuruecknehmenCommand as StateResource', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN }; - const error: ApiError = createApiError(); - const action = CommandActions.createCommandFailure({ command, error }); - - const state: LoeschAnforderungState = reducer(initialState, action); - - expect(state.loeschAnforderungZuruecknehmenCommand).toEqual(createErrorStateResource(error)); - }) - }) - - describe('on "revokeCommandSuccess" action', () => { - - it('should reload loeschAnforderung', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN }; - const action = CommandActions.revokeCommandSuccess({ command }); - - const state: LoeschAnforderungState = reducer({ ...initialState, loeschAnforderung: createStateResource(createLoeschAnforderungResource()) }, action); - - expect(state.loeschAnforderung.reload).toBeTruthy(); - }) - }) - }) - - describe('Vorgang', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const action: TypedAction<string> = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); - - describe('loadVorgangWithEingangSuccess', () => { - - it('should clear loeschenAnfordernCommand', () => { - const filledState: LoeschAnforderungState = { ...initialState, loeschenAnfordernCommand: createStateResource(createCommandResource()) }; - const state: LoeschAnforderungState = reducer(filledState, action); - - expect(state.loeschenAnfordernCommand).toEqual(createEmptyStateResource()); - }) - - it('should clear loeschAnforderung', () => { - const filledState: LoeschAnforderungState = { ...initialState, loeschAnforderung: createStateResource(createLoeschAnforderungResource()) }; - const state: LoeschAnforderungState = reducer(filledState, action); - - expect(state.loeschAnforderung).toEqual(createEmptyStateResource()); - }) - - it('should clear vorgangLoeschenCommand', () => { - const filledState: LoeschAnforderungState = { ...initialState, vorgangLoeschenCommand: createStateResource(createCommandResource()) }; - const state: LoeschAnforderungState = reducer(filledState, action); - - expect(state.vorgangLoeschenCommand).toEqual(createEmptyStateResource()); - }) - - it('should clear loeschAnforderungZuruecknehmenCommand', () => { - const filledState: LoeschAnforderungState = { ...initialState, loeschAnforderungZuruecknehmenCommand: createStateResource(createCommandResource()) }; - const state: LoeschAnforderungState = reducer(filledState, action); - - expect(state.loeschAnforderungZuruecknehmenCommand).toEqual(createEmptyStateResource()); - }) - }) - }) - - describe('Navigation', () => { - - it('should clear loeschenAnfordernCommand', () => { - const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); - - const filledState: LoeschAnforderungState = { ...initialState, loeschenAnfordernCommand: createStateResource(createCommandResource()) }; - const state: LoeschAnforderungState = reducer(filledState, action); - - expect(state.loeschenAnfordernCommand).toEqual(createEmptyStateResource()); - }) - - it('should clear loeschAnforderung', () => { - const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); - - const filledState: LoeschAnforderungState = { ...initialState, loeschAnforderung: createStateResource(createLoeschAnforderungResource()) }; - const state: LoeschAnforderungState = reducer(filledState, action); - - expect(state.loeschAnforderung).toEqual(createEmptyStateResource()); - }) - - it('should clear vorgangLoeschenCommand', () => { - const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); - - const filledState: LoeschAnforderungState = { ...initialState, vorgangLoeschenCommand: createStateResource(createCommandResource()) }; - const state: LoeschAnforderungState = reducer(filledState, action); - - expect(state.vorgangLoeschenCommand).toEqual(createEmptyStateResource()); - }) - - it('should clear loeschAnforderungZuruecknehmenCommand', () => { - const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); - - const filledState: LoeschAnforderungState = { ...initialState, loeschAnforderungZuruecknehmenCommand: createStateResource(createCommandResource()) }; - const state: LoeschAnforderungState = reducer(filledState, action); - - expect(state.loeschAnforderungZuruecknehmenCommand).toEqual(createEmptyStateResource()); - }) - }) -}) \ No newline at end of file + describe('unknown action', () => { + it('should return current state', () => { + const action = {} as Action; + + const result = reducer(initialState, action); + + expect(result).toBe(initialState); + }); + }); + + describe('LoeschAnforderung', () => { + describe('on "loadLoeschAnforderungSuccess" action', () => { + it('should set loeschenAnfordernResource', () => { + const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); + const action = LoeschAnforderungActions.loadLoeschAnforderungSuccess({ loeschAnforderung }); + + const state: LoeschAnforderungState = reducer(initialState, action); + + expect(state.loeschAnforderung).toEqual(createStateResource(loeschAnforderung)); + }); + }); + + describe('on "loadLoeschAnforderungFailure" action', () => { + it('should set loeschenAnfordernResource as errorStateResource', () => { + const apiError: ApiError = createApiError(); + const action = LoeschAnforderungActions.loadLoeschAnforderungFailure({ apiError }); + + const state: LoeschAnforderungState = reducer(initialState, action); + + expect(state.loeschAnforderung).toEqual(createErrorStateResource(apiError)); + }); + }); + }); + + describe('VorgangZumLoeschenMarkieren', () => { + describe('on "createCommand" action', () => { + it('should set vorgangLoeschenCommand loading', () => { + const action = CommandActions.createCommand({ + command: { ...createCommand(), order: CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN }, + resource: createVorgangWithEingangResource(), + linkRel: LoeschAnforderungLinkRel.EXECUTE_LOESCHEN, + }); + + const state: LoeschAnforderungState = reducer(initialState, action); + + expect(state.loeschenAnfordernCommand.loading).toBeTruthy(); + }); + }); + + describe('on "createCommandSuccess" action', () => { + it('should set vorgangLoeschenCommand as StateResource', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN, + }; + const action = CommandActions.createCommandSuccess({ command }); + + const state: LoeschAnforderungState = reducer(initialState, action); + + expect(state.loeschenAnfordernCommand).toEqual(createStateResource(command)); + }); + }); + + describe('on "revokeCommandSuccess" action', () => { + it('should clear loeschAnforderung', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN, + }; + const action = CommandActions.revokeCommandSuccess({ command }); + + const state: LoeschAnforderungState = reducer( + { + ...initialState, + loeschAnforderung: createStateResource(createLoeschAnforderungResource()), + }, + action, + ); + + expect(state.loeschAnforderung).toEqual(createEmptyStateResource()); + }); + }); + }); + + describe('VorgangLoeschen', () => { + describe('on "createCommand" action', () => { + it('should set vorgangLoeschenCommand loading', () => { + const action = CommandActions.createCommand({ + command: { ...createCommand(), order: CommandOrder.VORGANG_LOESCHEN }, + resource: createVorgangWithEingangResource(), + linkRel: LoeschAnforderungLinkRel.EXECUTE_LOESCHEN, + }); + + const state: LoeschAnforderungState = reducer(initialState, action); + + expect(state.vorgangLoeschenCommand.loading).toBeTruthy(); + }); + }); + + describe('on "createCommandSuccess" action', () => { + it('should set vorgangLoeschenCommand as StateResource', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.VORGANG_LOESCHEN, + }; + const action = CommandActions.createCommandSuccess({ command }); + + const state: LoeschAnforderungState = reducer(initialState, action); + + expect(state.vorgangLoeschenCommand).toEqual(createStateResource(command)); + }); + }); + }); + + describe('LoeschAnforderungZuruecknehmen', () => { + describe('on "createCommand" action', () => { + it('should set loeschAnforderungZuruecknehmenCommand loading', () => { + const action = CommandActions.createCommand({ + command: { ...createCommand(), order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN }, + resource: createVorgangWithEingangResource(), + linkRel: LoeschAnforderungLinkRel.ZURUECKNEHMEN, + }); + + const state: LoeschAnforderungState = reducer(initialState, action); + + expect(state.loeschAnforderungZuruecknehmenCommand.loading).toBeTruthy(); + }); + }); + + describe('on "createCommandSuccess" action', () => { + it('should set loeschAnforderungZuruecknehmenCommand as StateResource', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN, + }; + const action = CommandActions.createCommandSuccess({ command }); + + const state: LoeschAnforderungState = reducer(initialState, action); + + expect(state.loeschAnforderungZuruecknehmenCommand).toEqual(createStateResource(command)); + }); + + it('should clear LoeschAnforderung state', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN, + }; + const action = CommandActions.createCommandSuccess({ command }); + + const state: LoeschAnforderungState = reducer( + { + ...initialState, + loeschAnforderung: createStateResource(createLoeschAnforderungResource()), + }, + action, + ); + + expect(state.loeschAnforderung).toEqual(createEmptyStateResource()); + }); + }); + + describe('on "createCommandFailure" action', () => { + it('should set loeschAnforderungZuruecknehmenCommand as StateResource', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN, + }; + const error: ApiError = createApiError(); + const action = CommandActions.createCommandFailure({ command, error }); + + const state: LoeschAnforderungState = reducer(initialState, action); + + expect(state.loeschAnforderungZuruecknehmenCommand).toEqual( + createErrorStateResource(error), + ); + }); + }); + + describe('on "revokeCommandSuccess" action', () => { + it('should reload loeschAnforderung', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN, + }; + const action = CommandActions.revokeCommandSuccess({ command }); + + const state: LoeschAnforderungState = reducer( + { + ...initialState, + loeschAnforderung: createStateResource(createLoeschAnforderungResource()), + }, + action, + ); + + expect(state.loeschAnforderung.reload).toBeTruthy(); + }); + }); + }); + + describe('Vorgang', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const action: TypedAction<string> = VorgangActions.loadVorgangWithEingangSuccess({ + vorgangWithEingang, + }); + + describe('loadVorgangWithEingangSuccess', () => { + it('should clear loeschenAnfordernCommand', () => { + const filledState: LoeschAnforderungState = { + ...initialState, + loeschenAnfordernCommand: createStateResource(createCommandResource()), + }; + const state: LoeschAnforderungState = reducer(filledState, action); + + expect(state.loeschenAnfordernCommand).toEqual(createEmptyStateResource()); + }); + + it('should clear loeschAnforderung', () => { + const filledState: LoeschAnforderungState = { + ...initialState, + loeschAnforderung: createStateResource(createLoeschAnforderungResource()), + }; + const state: LoeschAnforderungState = reducer(filledState, action); + + expect(state.loeschAnforderung).toEqual(createEmptyStateResource()); + }); + + it('should clear vorgangLoeschenCommand', () => { + const filledState: LoeschAnforderungState = { + ...initialState, + vorgangLoeschenCommand: createStateResource(createCommandResource()), + }; + const state: LoeschAnforderungState = reducer(filledState, action); + + expect(state.vorgangLoeschenCommand).toEqual(createEmptyStateResource()); + }); + + it('should clear loeschAnforderungZuruecknehmenCommand', () => { + const filledState: LoeschAnforderungState = { + ...initialState, + loeschAnforderungZuruecknehmenCommand: createStateResource(createCommandResource()), + }; + const state: LoeschAnforderungState = reducer(filledState, action); + + expect(state.loeschAnforderungZuruecknehmenCommand).toEqual(createEmptyStateResource()); + }); + }); + }); + + describe('Navigation', () => { + it('should clear loeschenAnfordernCommand', () => { + const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ + routeData: createRouteData(), + }); + + const filledState: LoeschAnforderungState = { + ...initialState, + loeschenAnfordernCommand: createStateResource(createCommandResource()), + }; + const state: LoeschAnforderungState = reducer(filledState, action); + + expect(state.loeschenAnfordernCommand).toEqual(createEmptyStateResource()); + }); + + it('should clear loeschAnforderung', () => { + const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ + routeData: createRouteData(), + }); + + const filledState: LoeschAnforderungState = { + ...initialState, + loeschAnforderung: createStateResource(createLoeschAnforderungResource()), + }; + const state: LoeschAnforderungState = reducer(filledState, action); + + expect(state.loeschAnforderung).toEqual(createEmptyStateResource()); + }); + + it('should clear vorgangLoeschenCommand', () => { + const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ + routeData: createRouteData(), + }); + + const filledState: LoeschAnforderungState = { + ...initialState, + vorgangLoeschenCommand: createStateResource(createCommandResource()), + }; + const state: LoeschAnforderungState = reducer(filledState, action); + + expect(state.vorgangLoeschenCommand).toEqual(createEmptyStateResource()); + }); + + it('should clear loeschAnforderungZuruecknehmenCommand', () => { + const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ + routeData: createRouteData(), + }); + + const filledState: LoeschAnforderungState = { + ...initialState, + loeschAnforderungZuruecknehmenCommand: createStateResource(createCommandResource()), + }; + const state: LoeschAnforderungState = reducer(filledState, action); + + expect(state.loeschAnforderungZuruecknehmenCommand).toEqual(createEmptyStateResource()); + }); + }); +}); diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.ts index 1d0236ebbf6e99ccc4e366469e5571f7fb9f8627..ccb9ede989db5e7e1402f1d5080dcc3f12856937 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.ts @@ -1,8 +1,24 @@ -import { CommandProps, CommandResource, CreateCommandFailureProps, CreateCommandProps } from '@alfa-client/command-shared'; -import { ApiError, ApiErrorAction, StateResource, createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + CommandProps, + CommandResource, + CreateCommandFailureProps, + CreateCommandProps, +} from '@alfa-client/command-shared'; +import { + ApiError, + ApiErrorAction, + StateResource, + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Action, ActionReducer, createReducer, on } from '@ngrx/store'; import { LoeschAnforderungResource } from '../loesch-anforderung.model'; -import { isLoeschAnforderungZuruecknehmen, isVorgangLoeschenCommand, isVorgangZumLoeschenMarkierenCommand } from '../loesch-anforderung.util'; +import { + isLoeschAnforderungZuruecknehmen, + isVorgangLoeschenCommand, + isVorgangZumLoeschenMarkierenCommand, +} from '../loesch-anforderung.util'; import { LoeschAnforderungProps } from './loesch-anforderung.actions'; import * as CommandActions from '../../../../command-shared/src/lib/+state/command.actions'; @@ -13,113 +29,170 @@ import * as LoeschAnforderungActions from './loesch-anforderung.actions'; export const LOESCH_ANFORDERUNG_FEATURE_KEY = 'LoeschAnforderungState'; export interface LoeschAnforderungPartialState { - readonly [LOESCH_ANFORDERUNG_FEATURE_KEY]: LoeschAnforderungState; + readonly [LOESCH_ANFORDERUNG_FEATURE_KEY]: LoeschAnforderungState; } export interface LoeschAnforderungState { - loeschenAnfordernCommand: StateResource<CommandResource>; - loeschAnforderung: StateResource<LoeschAnforderungResource>; - vorgangLoeschenCommand: StateResource<CommandResource>; - loeschAnforderungZuruecknehmenCommand: StateResource<CommandResource>; + loeschenAnfordernCommand: StateResource<CommandResource>; + loeschAnforderung: StateResource<LoeschAnforderungResource>; + vorgangLoeschenCommand: StateResource<CommandResource>; + loeschAnforderungZuruecknehmenCommand: StateResource<CommandResource>; } export const initialState: LoeschAnforderungState = { - loeschenAnfordernCommand: createEmptyStateResource(), - loeschAnforderung: createEmptyStateResource(), - vorgangLoeschenCommand: createEmptyStateResource(), - loeschAnforderungZuruecknehmenCommand: createEmptyStateResource() + loeschenAnfordernCommand: createEmptyStateResource(), + loeschAnforderung: createEmptyStateResource(), + vorgangLoeschenCommand: createEmptyStateResource(), + loeschAnforderungZuruecknehmenCommand: createEmptyStateResource(), }; const loeschAnforderungReducer: ActionReducer<LoeschAnforderungState, Action> = createReducer( - initialState, + initialState, - on(LoeschAnforderungActions.loadLoeschAnforderungSuccess, (state: LoeschAnforderungState, props: LoeschAnforderungProps): LoeschAnforderungState => ({ - ...state, - loeschAnforderung: createStateResource(props.loeschAnforderung), - })), - on(LoeschAnforderungActions.loadLoeschAnforderungFailure, (state: LoeschAnforderungState, props: ApiErrorAction): LoeschAnforderungState => ({ - ...state, - loeschAnforderung: createErrorStateResource(props.apiError) - })), + on( + LoeschAnforderungActions.loadLoeschAnforderungSuccess, + (state: LoeschAnforderungState, props: LoeschAnforderungProps): LoeschAnforderungState => ({ + ...state, + loeschAnforderung: createStateResource(props.loeschAnforderung), + }), + ), + on( + LoeschAnforderungActions.loadLoeschAnforderungFailure, + (state: LoeschAnforderungState, props: ApiErrorAction): LoeschAnforderungState => ({ + ...state, + loeschAnforderung: createErrorStateResource(props.apiError), + }), + ), - //LoeschenAnfordernCommand - on(CommandActions.createCommand, (state: LoeschAnforderungState, props: CreateCommandProps): LoeschAnforderungState => { - return isVorgangZumLoeschenMarkierenCommand(props.command.order) ? { - ...state, - loeschenAnfordernCommand: createEmptyStateResource(true) - } : state; - }), - on(CommandActions.createCommandSuccess, (state: LoeschAnforderungState, props: CommandProps): LoeschAnforderungState => { - return isVorgangZumLoeschenMarkierenCommand(props.command.order) ? { - ...state, - loeschenAnfordernCommand: createStateResource(props.command) - } : state; - }), - on(CommandActions.revokeCommandSuccess, (state: LoeschAnforderungState, props: CommandProps): LoeschAnforderungState => { - return isVorgangZumLoeschenMarkierenCommand(props.command.order) ? { - ...state, - loeschAnforderung: createEmptyStateResource() - } : state; - }), + //LoeschenAnfordernCommand + on( + CommandActions.createCommand, + (state: LoeschAnforderungState, props: CreateCommandProps): LoeschAnforderungState => { + return isVorgangZumLoeschenMarkierenCommand(props.command.order) ? + { + ...state, + loeschenAnfordernCommand: createEmptyStateResource(true), + } + : state; + }, + ), + on( + CommandActions.createCommandSuccess, + (state: LoeschAnforderungState, props: CommandProps): LoeschAnforderungState => { + return isVorgangZumLoeschenMarkierenCommand(props.command.order) ? + { + ...state, + loeschenAnfordernCommand: createStateResource(props.command), + } + : state; + }, + ), + on( + CommandActions.revokeCommandSuccess, + (state: LoeschAnforderungState, props: CommandProps): LoeschAnforderungState => { + return isVorgangZumLoeschenMarkierenCommand(props.command.order) ? + { + ...state, + loeschAnforderung: createEmptyStateResource(), + } + : state; + }, + ), - //VorgangLoeschenCommand - on(CommandActions.createCommand, (state: LoeschAnforderungState, props: CreateCommandProps): LoeschAnforderungState => { - return isVorgangLoeschenCommand(props.command.order) ? { ...state, vorgangLoeschenCommand: createEmptyStateResource(true) } : state; - }), - on(CommandActions.createCommandSuccess, (state: LoeschAnforderungState, props: CommandProps): LoeschAnforderungState => { - return isVorgangLoeschenCommand(props.command.order) ? { ...state, vorgangLoeschenCommand: createStateResource(props.command) } : state; - }), + //VorgangLoeschenCommand + on( + CommandActions.createCommand, + (state: LoeschAnforderungState, props: CreateCommandProps): LoeschAnforderungState => { + return isVorgangLoeschenCommand(props.command.order) ? + { ...state, vorgangLoeschenCommand: createEmptyStateResource(true) } + : state; + }, + ), + on( + CommandActions.createCommandSuccess, + (state: LoeschAnforderungState, props: CommandProps): LoeschAnforderungState => { + return isVorgangLoeschenCommand(props.command.order) ? + { ...state, vorgangLoeschenCommand: createStateResource(props.command) } + : state; + }, + ), - //loeschAnforderungZuruecknehmenCommand - on(CommandActions.createCommand, (state: LoeschAnforderungState, props: CreateCommandProps): LoeschAnforderungState => { - return isLoeschAnforderungZuruecknehmen(props.command.order) ? { - ...state, - loeschAnforderungZuruecknehmenCommand: createEmptyStateResource(true) - } : state; - }), - on(CommandActions.createCommandSuccess, (state: LoeschAnforderungState, props: CommandProps): LoeschAnforderungState => { - return isLoeschAnforderungZuruecknehmen(props.command.order) ? { - ...state, - loeschAnforderungZuruecknehmenCommand: createStateResource(props.command), - loeschAnforderung: createEmptyStateResource() - } : state; - }), - on(CommandActions.createCommandFailure, (state: LoeschAnforderungState, props: CreateCommandFailureProps): LoeschAnforderungState => { - return isLoeschAnforderungZuruecknehmen(props.command.order) ? { - ...state, - loeschAnforderungZuruecknehmenCommand: createErrorStateResource(<ApiError>props.error) - } : state; - }), - on(CommandActions.revokeCommandSuccess, (state: LoeschAnforderungState, props: CommandProps): LoeschAnforderungState => { - return isLoeschAnforderungZuruecknehmen(props.command.order) ? { - ...state, - loeschAnforderung: { ...createEmptyStateResource(), reload: true } - } : state; - }), + //loeschAnforderungZuruecknehmenCommand + on( + CommandActions.createCommand, + (state: LoeschAnforderungState, props: CreateCommandProps): LoeschAnforderungState => { + return isLoeschAnforderungZuruecknehmen(props.command.order) ? + { + ...state, + loeschAnforderungZuruecknehmenCommand: createEmptyStateResource(true), + } + : state; + }, + ), + on( + CommandActions.createCommandSuccess, + (state: LoeschAnforderungState, props: CommandProps): LoeschAnforderungState => { + return isLoeschAnforderungZuruecknehmen(props.command.order) ? + { + ...state, + loeschAnforderungZuruecknehmenCommand: createStateResource(props.command), + loeschAnforderung: createEmptyStateResource(), + } + : state; + }, + ), + on( + CommandActions.createCommandFailure, + (state: LoeschAnforderungState, props: CreateCommandFailureProps): LoeschAnforderungState => { + return isLoeschAnforderungZuruecknehmen(props.command.order) ? + { + ...state, + loeschAnforderungZuruecknehmenCommand: createErrorStateResource(<ApiError>props.error), + } + : state; + }, + ), + on( + CommandActions.revokeCommandSuccess, + (state: LoeschAnforderungState, props: CommandProps): LoeschAnforderungState => { + return isLoeschAnforderungZuruecknehmen(props.command.order) ? + { + ...state, + loeschAnforderung: { ...createEmptyStateResource(), reload: true }, + } + : state; + }, + ), - //VorgangActions - on(VorgangActions.loadVorgangWithEingangSuccess, (state: LoeschAnforderungState): LoeschAnforderungState => { - return { - ...state, - loeschenAnfordernCommand: createEmptyStateResource(), - vorgangLoeschenCommand: createEmptyStateResource(), - loeschAnforderung: createEmptyStateResource(), - loeschAnforderungZuruecknehmenCommand: createEmptyStateResource() - }; - }), + //VorgangActions + on( + VorgangActions.loadVorgangWithEingangSuccess, + (state: LoeschAnforderungState): LoeschAnforderungState => { + return { + ...state, + loeschenAnfordernCommand: createEmptyStateResource(), + vorgangLoeschenCommand: createEmptyStateResource(), + loeschAnforderung: createEmptyStateResource(), + loeschAnforderungZuruecknehmenCommand: createEmptyStateResource(), + }; + }, + ), - //Navigation - on(NavigationActions.updateCurrentRouteData, (state: LoeschAnforderungState): LoeschAnforderungState => { - return { - ...state, - loeschenAnfordernCommand: createEmptyStateResource(), - loeschAnforderung: createEmptyStateResource(), - vorgangLoeschenCommand: createEmptyStateResource(), - loeschAnforderungZuruecknehmenCommand: createEmptyStateResource() - } - }) + //Navigation + on( + NavigationActions.updateCurrentRouteData, + (state: LoeschAnforderungState): LoeschAnforderungState => { + return { + ...state, + loeschenAnfordernCommand: createEmptyStateResource(), + loeschAnforderung: createEmptyStateResource(), + vorgangLoeschenCommand: createEmptyStateResource(), + loeschAnforderungZuruecknehmenCommand: createEmptyStateResource(), + }; + }, + ), ); export function reducer(state: LoeschAnforderungState, action: Action): LoeschAnforderungState { - return loeschAnforderungReducer(state, action); -} \ No newline at end of file + return loeschAnforderungReducer(state, action); +} diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.repository.spec.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.repository.spec.ts index 633ec6721ece79b1e6196c73bf7215220b171e15..b46c5261f063bbe231024f8bc026669333d58eb5 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.repository.spec.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.repository.spec.ts @@ -8,43 +8,45 @@ import { LoeschAnforderungResource } from '../loesch-anforderung.model'; import { LoeschAnforderungRepository } from './loesch-anforderung.repository'; describe('LoeschAnforderungRepository', () => { - let repository: LoeschAnforderungRepository; - let resourceFactory = mock(ResourceFactory); - let resourceWrapper = { get: jest.fn() }; + let repository: LoeschAnforderungRepository; + let resourceFactory = mock(ResourceFactory); + let resourceWrapper = { get: jest.fn() }; - beforeEach(() => { - repository = new LoeschAnforderungRepository(useFromMock(resourceFactory)); + beforeEach(() => { + repository = new LoeschAnforderungRepository(useFromMock(resourceFactory)); - resourceFactory.fromId.mockReturnValue(resourceWrapper); - resourceFactory.from.mockReturnValue(resourceWrapper); - }) + resourceFactory.fromId.mockReturnValue(resourceWrapper); + resourceFactory.from.mockReturnValue(resourceWrapper); + }); - describe('getLoeschAnforderung', () => { + describe('getLoeschAnforderung', () => { + const vorgangWithEingangResource: VorgangWithEingangResource = + createVorgangWithEingangResource(); + const loeschAnforderungResource: LoeschAnforderungResource = createLoeschAnforderungResource(); - const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource(); - const loeschAnforderungResource: LoeschAnforderungResource = createLoeschAnforderungResource() + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: loeschAnforderungResource })); + }); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: loeschAnforderungResource })); - }) + it('should call resourceFactory with resource', () => { + repository.getLoeschAnforderung(vorgangWithEingangResource); - it('should call resourceFactory with resource', () => { - repository.getLoeschAnforderung(vorgangWithEingangResource); + expect(resourceFactory.from).toHaveBeenCalledWith(vorgangWithEingangResource); + }); - expect(resourceFactory.from).toHaveBeenCalledWith(vorgangWithEingangResource); - }) + it('should call resourceWrapper with link', () => { + repository.getLoeschAnforderung(vorgangWithEingangResource); - it('should call resourceWrapper with link', () => { - repository.getLoeschAnforderung(vorgangWithEingangResource); + expect(resourceWrapper.get).toHaveBeenCalledWith( + VorgangWithEingangLinkRel.LOESCH_ANFORDERUNG, + ); + }); - expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangWithEingangLinkRel.LOESCH_ANFORDERUNG) - }) + it('should return result', () => { + let result = repository.getLoeschAnforderung(vorgangWithEingangResource); - it('should return result', () => { - let result = repository.getLoeschAnforderung(vorgangWithEingangResource); - - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: loeschAnforderungResource })); - }) - }) -}) \ No newline at end of file + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: loeschAnforderungResource })); + }); + }); +}); diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.repository.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.repository.ts index 77bfc4a8941f14a0b1013ecaa1bc9ac08aa3227a..8ff7288eefb930fdf06201de9ea2203581345447 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.repository.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.repository.ts @@ -6,10 +6,11 @@ import { LoeschAnforderungResource } from '../loesch-anforderung.model'; @Injectable() export class LoeschAnforderungRepository { + constructor(private resourceFactory: ResourceFactory) {} - constructor(private resourceFactory: ResourceFactory) { } - - public getLoeschAnforderung(vorgang: VorgangWithEingangResource): Observable<LoeschAnforderungResource> { - return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.LOESCH_ANFORDERUNG); - } -} \ No newline at end of file + public getLoeschAnforderung( + vorgang: VorgangWithEingangResource, + ): Observable<LoeschAnforderungResource> { + return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.LOESCH_ANFORDERUNG); + } +} diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.selectors.spec.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.selectors.spec.ts index bc6cf6c68f1ae6800b62c50f3768816653ab2d3c..2c7c20a79855c445e667d9297dadedac94ca1d15 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.selectors.spec.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.selectors.spec.ts @@ -8,48 +8,58 @@ import { initialState, LoeschAnforderungPartialState } from './loesch-anforderun import * as LoeschAnforderungSelectors from './loesch-anforderung.selectors'; describe('LoeschAnforderung Selectors', () => { + let state: LoeschAnforderungPartialState; - let state: LoeschAnforderungPartialState; + const loeschenAnfordernCommand: StateResource<CommandResource> = + createStateResource(createCommandResource()); + const loeschAnforderung: StateResource<LoeschAnforderungResource> = createStateResource( + createLoeschAnforderungResource(), + ); + const vorgangLoeschenCommand: StateResource<CommandResource> = + createStateResource(createCommandResource()); + const loeschAnforderungZuruecknehmenCommand: StateResource<CommandResource> = + createStateResource(createCommandResource()); - const loeschenAnfordernCommand: StateResource<CommandResource> = createStateResource(createCommandResource()); - const loeschAnforderung: StateResource<LoeschAnforderungResource> = createStateResource(createLoeschAnforderungResource()); - const vorgangLoeschenCommand: StateResource<CommandResource> = createStateResource(createCommandResource()); - const loeschAnforderungZuruecknehmenCommand: StateResource<CommandResource> = createStateResource(createCommandResource()); + beforeEach(() => { + state = { + LoeschAnforderungState: { + ...initialState, - beforeEach(() => { - state = { - LoeschAnforderungState: { - ...initialState, + loeschenAnfordernCommand, + loeschAnforderung, + vorgangLoeschenCommand, + loeschAnforderungZuruecknehmenCommand, + }, + }; + }); - loeschenAnfordernCommand, - loeschAnforderung, - vorgangLoeschenCommand, - loeschAnforderungZuruecknehmenCommand - } - }; - }); + it('should return loeschenAnfordernCommand', () => { + const result: StateResource<CommandResource> = + LoeschAnforderungSelectors.loeschenAnfordernCommand.projector(state.LoeschAnforderungState); - it('should return loeschenAnfordernCommand', () => { - const result: StateResource<CommandResource> = LoeschAnforderungSelectors.loeschenAnfordernCommand.projector(state.LoeschAnforderungState); + expect(result).toBe(loeschenAnfordernCommand); + }); - expect(result).toBe(loeschenAnfordernCommand); - }) + it('should return loeschAnforderung from state', () => { + const result: StateResource<LoeschAnforderungResource> = + LoeschAnforderungSelectors.loeschAnforderung.projector(state.LoeschAnforderungState); - it('should return loeschAnforderung from state', () => { - const result: StateResource<LoeschAnforderungResource> = LoeschAnforderungSelectors.loeschAnforderung.projector(state.LoeschAnforderungState); + expect(result).toBe(loeschAnforderung); + }); - expect(result).toBe(loeschAnforderung); - }) + it('should return vorgangLoeschenCommand from state', () => { + const result: StateResource<CommandResource> = + LoeschAnforderungSelectors.vorgangLoeschenCommand.projector(state.LoeschAnforderungState); - it('should return vorgangLoeschenCommand from state', () => { - const result: StateResource<CommandResource> = LoeschAnforderungSelectors.vorgangLoeschenCommand.projector(state.LoeschAnforderungState); + expect(result).toBe(vorgangLoeschenCommand); + }); - expect(result).toBe(vorgangLoeschenCommand); - }) + it('should return loeschAnforderungZuruecknehmenCommand', () => { + const result: StateResource<CommandResource> = + LoeschAnforderungSelectors.loeschAnforderungZuruecknehmenCommand.projector( + state.LoeschAnforderungState, + ); - it('should return loeschAnforderungZuruecknehmenCommand', () => { - const result: StateResource<CommandResource> = LoeschAnforderungSelectors.loeschAnforderungZuruecknehmenCommand.projector(state.LoeschAnforderungState); - - expect(result).toBe(loeschAnforderungZuruecknehmenCommand); - }) -}); \ No newline at end of file + expect(result).toBe(loeschAnforderungZuruecknehmenCommand); + }); +}); diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.selectors.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.selectors.ts index 7273c8ada192ae641148da961fcd3f5cf1561881..ebdea868134f1cb8863ae6de67546f409f8efe3e 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.selectors.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.selectors.ts @@ -2,11 +2,39 @@ import { CommandResource } from '@alfa-client/command-shared'; import { StateResource } from '@alfa-client/tech-shared'; import { createFeatureSelector, createSelector, MemoizedSelector } from '@ngrx/store'; import { LoeschAnforderungResource } from '../loesch-anforderung.model'; -import { LOESCH_ANFORDERUNG_FEATURE_KEY, LoeschAnforderungState } from './loesch-anforderung.reducer'; +import { + LOESCH_ANFORDERUNG_FEATURE_KEY, + LoeschAnforderungState, +} from './loesch-anforderung.reducer'; -export const getLoeschAnforderungState: MemoizedSelector<object, LoeschAnforderungState> = createFeatureSelector<LoeschAnforderungState>(LOESCH_ANFORDERUNG_FEATURE_KEY); +export const getLoeschAnforderungState: MemoizedSelector<object, LoeschAnforderungState> = + createFeatureSelector<LoeschAnforderungState>(LOESCH_ANFORDERUNG_FEATURE_KEY); -export const loeschenAnfordernCommand: MemoizedSelector<LoeschAnforderungState, StateResource<CommandResource>> = createSelector(getLoeschAnforderungState, (state: LoeschAnforderungState) => state.loeschenAnfordernCommand); -export const loeschAnforderung: MemoizedSelector<LoeschAnforderungState, StateResource<LoeschAnforderungResource>> = createSelector(getLoeschAnforderungState, (state: LoeschAnforderungState) => state.loeschAnforderung); -export const vorgangLoeschenCommand: MemoizedSelector<LoeschAnforderungState, StateResource<CommandResource>> = createSelector(getLoeschAnforderungState, (state: LoeschAnforderungState) => state.vorgangLoeschenCommand); -export const loeschAnforderungZuruecknehmenCommand: MemoizedSelector<LoeschAnforderungState, StateResource<CommandResource>> = createSelector(getLoeschAnforderungState, (state: LoeschAnforderungState) => state.loeschAnforderungZuruecknehmenCommand); \ No newline at end of file +export const loeschenAnfordernCommand: MemoizedSelector< + LoeschAnforderungState, + StateResource<CommandResource> +> = createSelector( + getLoeschAnforderungState, + (state: LoeschAnforderungState) => state.loeschenAnfordernCommand, +); +export const loeschAnforderung: MemoizedSelector< + LoeschAnforderungState, + StateResource<LoeschAnforderungResource> +> = createSelector( + getLoeschAnforderungState, + (state: LoeschAnforderungState) => state.loeschAnforderung, +); +export const vorgangLoeschenCommand: MemoizedSelector< + LoeschAnforderungState, + StateResource<CommandResource> +> = createSelector( + getLoeschAnforderungState, + (state: LoeschAnforderungState) => state.vorgangLoeschenCommand, +); +export const loeschAnforderungZuruecknehmenCommand: MemoizedSelector< + LoeschAnforderungState, + StateResource<CommandResource> +> = createSelector( + getLoeschAnforderungState, + (state: LoeschAnforderungState) => state.loeschAnforderungZuruecknehmenCommand, +); diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung-shared.module.spec.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung-shared.module.spec.ts index 948bea7fe0ef0ac1fdb37e36baba7475a3c2fc26..8b436483cbb78c05d784049920567052edc70812 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung-shared.module.spec.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung-shared.module.spec.ts @@ -2,14 +2,13 @@ import { TestBed } from '@angular/core/testing'; import { LoeschAnforderungSharedModule } from './loesch-anforderung-shared.module'; describe('LoeschAnforderungSharedModule', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [LoeschAnforderungSharedModule], + }).compileComponents(); + }); - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [LoeschAnforderungSharedModule], - }).compileComponents(); - }); - - it('should create', () => { - expect(LoeschAnforderungSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(LoeschAnforderungSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung-shared.module.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung-shared.module.ts index a338abb822dcd6a19495e062ab9a98d8cb47373e..cb99656bb8f03df3449ff9f0d8500391dba40ffd 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung-shared.module.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung-shared.module.ts @@ -10,12 +10,12 @@ import { LoeschAnforderungRepository } from './+state/loesch-anforderung.reposit import { LoeschAnforderungService } from './loesch-anforderung.service'; @NgModule({ - imports: [ - CommonModule, - StoreModule.forFeature(LOESCH_ANFORDERUNG_FEATURE_KEY, reducer), - EffectsModule.forFeature([LoeschAnforderungEffects]), - VorgangSharedModule - ], - providers: [LoeschAnforderungFacade, LoeschAnforderungService, LoeschAnforderungRepository], + imports: [ + CommonModule, + StoreModule.forFeature(LOESCH_ANFORDERUNG_FEATURE_KEY, reducer), + EffectsModule.forFeature([LoeschAnforderungEffects]), + VorgangSharedModule, + ], + providers: [LoeschAnforderungFacade, LoeschAnforderungService, LoeschAnforderungRepository], }) -export class LoeschAnforderungSharedModule { } \ No newline at end of file +export class LoeschAnforderungSharedModule {} diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.linkrel.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.linkrel.ts index e1bd307b1686bf5656485c59d6a3c885f2441cf4..9a5ec780d19b3b3c8cb272378e2542dc65ca0d56 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.linkrel.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.linkrel.ts @@ -1,4 +1,4 @@ export enum LoeschAnforderungLinkRel { - EXECUTE_LOESCHEN = 'execute_loeschen', - ZURUECKNEHMEN = 'zuruecknehmen' -} \ No newline at end of file + EXECUTE_LOESCHEN = 'execute_loeschen', + ZURUECKNEHMEN = 'zuruecknehmen', +} diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.model.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.model.ts index 31cee5ea3a8b160f0662d115d7438026aede0a1e..d772c616a8634d13f0a14bfd7228445988469764 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.model.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.model.ts @@ -2,8 +2,8 @@ import { VorgangStatus } from '@alfa-client/vorgang-shared'; import { Resource, ResourceUri } from '@ngxp/rest'; export interface LoeschAnforderung { - requestedBy: ResourceUri - prevStatus: VorgangStatus, + requestedBy: ResourceUri; + prevStatus: VorgangStatus; } -export interface LoeschAnforderungResource extends LoeschAnforderung, Resource { } \ No newline at end of file +export interface LoeschAnforderungResource extends LoeschAnforderung, Resource {} diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.spec.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.spec.ts index d286651200270f1e8a9dd7ac54768fdd050b7242..d446062a056c0d70f31a24934102afc4aeeafdc9 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.spec.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.spec.ts @@ -3,7 +3,11 @@ import faker from '@faker-js/faker'; import { CommandResource } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; import { StateResource, createStateResource } from '@alfa-client/tech-shared'; -import { AdditionalActions, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + AdditionalActions, + VorgangService, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { createCommandResource } from 'libs/command-shared/test/command'; import { createLoeschAnforderungResource } from 'libs/loesch-anforderung-shared/test/loesch-anforderung'; import { createHttpErrorResponse } from 'libs/tech-shared/test/http'; @@ -13,214 +17,233 @@ import { of } from 'rxjs'; import { LoeschAnforderungFacade } from './+state/loesch-anforderung.facade'; import { LoeschAnforderungResource } from './loesch-anforderung.model'; import { LoeschAnforderungService } from './loesch-anforderung.service'; -import { createLoeschAnforderungZuruecknehmenCommand, createVorgangLoeschenCommand, createVorgangZumLoeschenMarkierenCommand } from './loesch-anforderung.util'; +import { + createLoeschAnforderungZuruecknehmenCommand, + createVorgangLoeschenCommand, + createVorgangZumLoeschenMarkierenCommand, +} from './loesch-anforderung.util'; import * as CommandUtil from '../../../command-shared/src/lib/command.util'; describe('LoeschAnforderungService', () => { - let service: LoeschAnforderungService; + let service: LoeschAnforderungService; - let facade: Mock<LoeschAnforderungFacade>; - let vorgangService: Mock<VorgangService>; - let navigationService: Mock<NavigationService>; + let facade: Mock<LoeschAnforderungFacade>; + let vorgangService: Mock<VorgangService>; + let navigationService: Mock<NavigationService>; - beforeEach(() => { - facade = mock(LoeschAnforderungFacade); - vorgangService = mock(VorgangService); - navigationService = mock(NavigationService); + beforeEach(() => { + facade = mock(LoeschAnforderungFacade); + vorgangService = mock(VorgangService); + navigationService = mock(NavigationService); - service = new LoeschAnforderungService(useFromMock(facade), useFromMock(vorgangService), useFromMock(navigationService)); - }) + service = new LoeschAnforderungService( + useFromMock(facade), + useFromMock(vorgangService), + useFromMock(navigationService), + ); + }); - describe('getLoeschenAnfordernCommand', () => { + describe('getLoeschenAnfordernCommand', () => { + it('should call facade', () => { + service.getLoeschenAnfordernCommand(); - it('should call facade', () => { - service.getLoeschenAnfordernCommand(); + expect(facade.getLoeschenAnfordernCommand).toHaveBeenCalled(); + }); + }); - expect(facade.getLoeschenAnfordernCommand).toHaveBeenCalled(); - }) - }) + describe('loeschenAnfordern', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - describe('loeschenAnfordern', () => { + it('should call facade', () => { + service.loeschenAnfordern(vorgangWithEingang); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + expect(facade.loeschenAnfordern).toHaveBeenCalledWith( + vorgangWithEingang, + createVorgangZumLoeschenMarkierenCommand(), + ); + }); + }); - it('should call facade', () => { - service.loeschenAnfordern(vorgangWithEingang); + describe('getLoeschAnforderung', () => { + it('should call facade', () => { + service.getLoeschAnforderung(); - expect(facade.loeschenAnfordern).toHaveBeenCalledWith(vorgangWithEingang, createVorgangZumLoeschenMarkierenCommand()); - }) - }) + expect(facade.getLoeschAnforderung).toHaveBeenCalled(); + }); + }); - describe('getLoeschAnforderung', () => { + describe('getEndgueltigLoeschenCommand', () => { + const command: CommandResource = createCommandResource(); - it('should call facade', () => { - service.getLoeschAnforderung(); + beforeEach(() => { + facade.getEndgueltigLoeschenCommand.mockReturnValue(of(createStateResource(command))); + }); - expect(facade.getLoeschAnforderung).toHaveBeenCalled(); - }) - }) + it('should call facade', () => { + service.getEndgueltigLoeschenCommand().subscribe(); - describe('getEndgueltigLoeschenCommand', () => { + expect(facade.getEndgueltigLoeschenCommand).toHaveBeenCalled(); + }); - const command: CommandResource = createCommandResource(); + it('should call vorgangService to get backButtonUrl', () => { + service.getEndgueltigLoeschenCommand().subscribe(); - beforeEach(() => { - facade.getEndgueltigLoeschenCommand.mockReturnValue(of(createStateResource(command))); - }) + expect(vorgangService.getBackButtonUrl).toHaveBeenCalled(); + }); - it('should call facade', () => { - service.getEndgueltigLoeschenCommand().subscribe(); + it('should handleEndgueltigLoeschenCommandChanges', () => { + const backButtonUrl: string = faker.internet.url(); + service.handleEndgueltigLoeschenCommandChanges = jest.fn(); + vorgangService.getBackButtonUrl.mockReturnValue(of(backButtonUrl)); - expect(facade.getEndgueltigLoeschenCommand).toHaveBeenCalled(); - }) + service.getEndgueltigLoeschenCommand().subscribe(); - it('should call vorgangService to get backButtonUrl', () => { - service.getEndgueltigLoeschenCommand().subscribe(); + expect(service.handleEndgueltigLoeschenCommandChanges).toHaveBeenCalledWith( + command, + backButtonUrl, + ); + }); + }); - expect(vorgangService.getBackButtonUrl).toHaveBeenCalled(); - }) + describe('handleEndgueltigLoeschenCommandChanges', () => { + const backButtonUrl: string = faker.internet.url(); + const command: CommandResource = createCommandResource(); + const spyOnCommandUtil = jest.spyOn(CommandUtil, 'isSuccessfulDone'); - it('should handleEndgueltigLoeschenCommandChanges', () => { - const backButtonUrl: string = faker.internet.url(); - service.handleEndgueltigLoeschenCommandChanges = jest.fn(); - vorgangService.getBackButtonUrl.mockReturnValue(of(backButtonUrl)); + it('should call isDoneWithoutError', () => { + service.handleEndgueltigLoeschenCommandChanges(command, backButtonUrl); - service.getEndgueltigLoeschenCommand().subscribe(); + expect(spyOnCommandUtil).toHaveBeenCalledWith(command); + }); - expect(service.handleEndgueltigLoeschenCommandChanges).toHaveBeenCalledWith(command, backButtonUrl); - }) - }) + it('should call navigationService if command is done without error', () => { + spyOnCommandUtil.mockReturnValue(true); - describe('handleEndgueltigLoeschenCommandChanges', () => { + service.handleEndgueltigLoeschenCommandChanges(command, backButtonUrl); - const backButtonUrl: string = faker.internet.url(); - const command: CommandResource = createCommandResource(); - const spyOnCommandUtil = jest.spyOn(CommandUtil, 'isSuccessfulDone') + expect(navigationService.navigate).toHaveBeenCalledWith(backButtonUrl); + }); - it('should call isDoneWithoutError', () => { - service.handleEndgueltigLoeschenCommandChanges(command, backButtonUrl); + it('should not navigate on error command', () => { + spyOnCommandUtil.mockReturnValue(false); - expect(spyOnCommandUtil).toHaveBeenCalledWith(command); - }) + expect(navigationService.navigate).not.toHaveBeenCalled(); + }); + }); - it('should call navigationService if command is done without error', () => { - spyOnCommandUtil.mockReturnValue(true); + describe('endgueltigLoeschen', () => { + const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); - service.handleEndgueltigLoeschenCommandChanges(command, backButtonUrl); + it('should call facade', () => { + service.endgueltigLoeschen(loeschAnforderung); - expect(navigationService.navigate).toHaveBeenCalledWith(backButtonUrl); - }) + expect(facade.endgueltigLoeschen).toHaveBeenCalledWith( + loeschAnforderung, + createVorgangLoeschenCommand(), + ); + }); + }); - it('should not navigate on error command', () => { - spyOnCommandUtil.mockReturnValue(false); + describe('getLoschAnforderungZuruecknehmenCommand', () => { + const backButtonUrl: string = faker.internet.url(); + const command: CommandResource = createCommandResource(); + const commandStateResource: StateResource<CommandResource> = createStateResource(command); - expect(navigationService.navigate).not.toHaveBeenCalled(); - }) - }) + beforeEach(() => { + facade.getLoeschAnforderungZuruecknehmenCommand.mockReturnValue(of(commandStateResource)); + vorgangService.getBackButtonUrl.mockReturnValue(of(backButtonUrl)); + }); - describe('endgueltigLoeschen', () => { - const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); + it('should call facade', () => { + service.getLoschAnforderungZuruecknehmenCommand(); - it('should call facade', () => { - service.endgueltigLoeschen(loeschAnforderung); + expect(facade.getLoeschAnforderungZuruecknehmenCommand).toHaveBeenCalled(); + }); - expect(facade.endgueltigLoeschen).toHaveBeenCalledWith(loeschAnforderung, createVorgangLoeschenCommand()); - }) - }) + it('should get back button Url', () => { + service.getLoschAnforderungZuruecknehmenCommand(); - describe('getLoschAnforderungZuruecknehmenCommand', () => { + expect(vorgangService.getBackButtonUrl).toHaveBeenCalled(); + }); - const backButtonUrl: string = faker.internet.url(); - const command: CommandResource = createCommandResource(); - const commandStateResource: StateResource<CommandResource> = createStateResource(command); + it('should handleLoeschAnforderungZuruecknehmenCommandChanges', () => { + service.handleLoeschAnforderungZuruecknehmenCommandChanges = jest.fn(); - beforeEach(() => { - facade.getLoeschAnforderungZuruecknehmenCommand.mockReturnValue(of(commandStateResource)); - vorgangService.getBackButtonUrl.mockReturnValue(of(backButtonUrl)); - }) + service.getLoschAnforderungZuruecknehmenCommand().subscribe(); - it('should call facade', () => { - service.getLoschAnforderungZuruecknehmenCommand(); + expect(service.handleLoeschAnforderungZuruecknehmenCommandChanges).toHaveBeenCalledWith( + commandStateResource, + backButtonUrl, + ); + }); - expect(facade.getLoeschAnforderungZuruecknehmenCommand).toHaveBeenCalled(); - }) + it('should return command', (done) => { + service.getLoschAnforderungZuruecknehmenCommand().subscribe((command) => { + expect(command).toBe(commandStateResource); + done(); + }); + }); + }); - it('should get back button Url', () => { - service.getLoschAnforderungZuruecknehmenCommand(); + describe('handleLoeschAnforderungZuruecknehmenCommandChanges', () => { + const overviewUrl: string = faker.internet.url(); + const command: CommandResource = createCommandResource(); + const commandStateResource: StateResource<CommandResource> = { + ...createStateResource(command), + error: <any>{ ...createHttpErrorResponse(), status: HttpStatusCode.NotFound }, + }; - expect(vorgangService.getBackButtonUrl).toHaveBeenCalled(); - }) + it('should reload current vorgang on not found error', () => { + service.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStateResource, overviewUrl); - it('should handleLoeschAnforderungZuruecknehmenCommandChanges', () => { - service.handleLoeschAnforderungZuruecknehmenCommandChanges = jest.fn(); + expect(vorgangService.reloadCurrentVorgangWithAddtionalActions).toHaveBeenCalled(); + }); - service.getLoschAnforderungZuruecknehmenCommand().subscribe(); + it('should create additionalAction', () => { + service.createAdditionalActions = jest.fn(); - expect(service.handleLoeschAnforderungZuruecknehmenCommandChanges).toHaveBeenCalledWith(commandStateResource, backButtonUrl); - }) + service.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStateResource, overviewUrl); - it('should return command', (done) => { - service.getLoschAnforderungZuruecknehmenCommand().subscribe(command => { - expect(command).toBe(commandStateResource); - done(); - }); - }) - }) + expect(service.createAdditionalActions).toHaveBeenCalledWith(overviewUrl); + }); - describe('handleLoeschAnforderungZuruecknehmenCommandChanges', () => { + it('should reload current vorgang on not found error with additional actions', () => { + const additionalActions: AdditionalActions = <any>{}; + service.createAdditionalActions = jest.fn().mockReturnValue(additionalActions); - const overviewUrl: string = faker.internet.url(); - const command: CommandResource = createCommandResource(); - const commandStateResource: StateResource<CommandResource> = { ...createStateResource(command), error: <any>{ ...createHttpErrorResponse(), status: HttpStatusCode.NotFound } }; + service.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStateResource, overviewUrl); - it('should reload current vorgang on not found error', () => { - service.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStateResource, overviewUrl); + expect(vorgangService.reloadCurrentVorgangWithAddtionalActions).toHaveBeenCalledWith( + additionalActions, + ); + }); - expect(vorgangService.reloadCurrentVorgangWithAddtionalActions).toHaveBeenCalled(); - }) + describe('createAdditionalActions', () => { + it('shouldContainsAdditionalSuccessAction', () => { + const additionalActions = service.createAdditionalActions(overviewUrl); - it('should create additionalAction', () => { - service.createAdditionalActions = jest.fn(); + expect(additionalActions.additionalSuccessAction).not.toBeNull(); + }); - service.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStateResource, overviewUrl); + it('shouldContainsAdditionalFailureAction', () => { + const additionalActions = service.createAdditionalActions(overviewUrl); - expect(service.createAdditionalActions).toHaveBeenCalledWith(overviewUrl); - }) + expect(additionalActions.additionalFailureAction).not.toBeNull(); + }); + }); + }); - it('should reload current vorgang on not found error with additional actions', () => { - const additionalActions: AdditionalActions = <any>{}; - service.createAdditionalActions = jest.fn().mockReturnValue(additionalActions); + describe('loeschAnforderungZuruecknehmen', () => { + it('should call facade', () => { + const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); - service.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStateResource, overviewUrl); - - expect(vorgangService.reloadCurrentVorgangWithAddtionalActions).toHaveBeenCalledWith(additionalActions); - }) - - describe('createAdditionalActions', () => { - - it('shouldContainsAdditionalSuccessAction', () => { - const additionalActions = service.createAdditionalActions(overviewUrl); - - expect(additionalActions.additionalSuccessAction).not.toBeNull(); - }) - - it('shouldContainsAdditionalFailureAction', () => { - const additionalActions = service.createAdditionalActions(overviewUrl); - - expect(additionalActions.additionalFailureAction).not.toBeNull(); - }) - }) - }) - - describe('loeschAnforderungZuruecknehmen', () => { - - it('should call facade', () => { - const loeschAnforderung: LoeschAnforderungResource = createLoeschAnforderungResource(); - - service.zuruecknehmen(loeschAnforderung); - - expect(facade.loeschAnforderungZuruecknehmen).toHaveBeenCalledWith(loeschAnforderung, createLoeschAnforderungZuruecknehmenCommand()); - }) - }) -}) + service.zuruecknehmen(loeschAnforderung); + + expect(facade.loeschAnforderungZuruecknehmen).toHaveBeenCalledWith( + loeschAnforderung, + createLoeschAnforderungZuruecknehmenCommand(), + ); + }); + }); +}); diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.ts index 4cdc3fe2e7dc1ec2d51dcd0a861aa8e74b75bbe0..94c125c1ee533ab665edc8c1eeb001a1959f5638 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.ts @@ -3,69 +3,101 @@ import { Injectable } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; import { StateResource, isNotFound } from '@alfa-client/tech-shared'; -import { AdditionalActions, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + AdditionalActions, + VorgangService, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { Observable, map, tap, withLatestFrom } from 'rxjs'; import { LoeschAnforderungFacade } from './+state/loesch-anforderung.facade'; import { LoeschAnforderungResource } from './loesch-anforderung.model'; -import { createLoeschAnforderungZuruecknehmenCommand, createVorgangLoeschenCommand, createVorgangZumLoeschenMarkierenCommand } from './loesch-anforderung.util'; +import { + createLoeschAnforderungZuruecknehmenCommand, + createVorgangLoeschenCommand, + createVorgangZumLoeschenMarkierenCommand, +} from './loesch-anforderung.util'; import * as CommandUtil from '../../../command-shared/src/lib/command.util'; import * as LoeschAnforderungActions from './+state/loesch-anforderung.actions'; @Injectable() export class LoeschAnforderungService { + constructor( + private facade: LoeschAnforderungFacade, + private vorgangService: VorgangService, + private navigationService: NavigationService, + ) {} - constructor(private facade: LoeschAnforderungFacade, private vorgangService: VorgangService, private navigationService: NavigationService) { } + public getLoeschenAnfordernCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getLoeschenAnfordernCommand(); + } - public getLoeschenAnfordernCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getLoeschenAnfordernCommand(); - } + public loeschenAnfordern(vorgang: VorgangWithEingangResource): void { + this.facade.loeschenAnfordern(vorgang, createVorgangZumLoeschenMarkierenCommand()); + } - public loeschenAnfordern(vorgang: VorgangWithEingangResource): void { - this.facade.loeschenAnfordern(vorgang, createVorgangZumLoeschenMarkierenCommand()); - } + public getLoeschAnforderung(): Observable<StateResource<LoeschAnforderungResource>> { + return this.facade.getLoeschAnforderung(); + } - public getLoeschAnforderung(): Observable<StateResource<LoeschAnforderungResource>> { - return this.facade.getLoeschAnforderung(); - } + public getEndgueltigLoeschenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getEndgueltigLoeschenCommand().pipe( + withLatestFrom(this.vorgangService.getBackButtonUrl()), + tap(([commandStatResource, backButtonUrl]) => + this.handleEndgueltigLoeschenCommandChanges(commandStatResource.resource, backButtonUrl), + ), + map(([commandStatResource]) => commandStatResource), + ); + } - public getEndgueltigLoeschenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getEndgueltigLoeschenCommand().pipe( - withLatestFrom(this.vorgangService.getBackButtonUrl()), - tap(([commandStatResource, backButtonUrl]) => this.handleEndgueltigLoeschenCommandChanges(commandStatResource.resource, backButtonUrl)), - map(([commandStatResource,]) => commandStatResource), - ); - } + handleEndgueltigLoeschenCommandChanges( + commandResource: CommandResource, + backButtonUrl: string, + ): void { + if (CommandUtil.isSuccessfulDone(commandResource)) { + this.navigationService.navigate(backButtonUrl); + } + } - handleEndgueltigLoeschenCommandChanges(commandResource: CommandResource, backButtonUrl: string): void{ - if (CommandUtil.isSuccessfulDone(commandResource)) { - this.navigationService.navigate(backButtonUrl); - } - } + public endgueltigLoeschen(loeschAnforderung: LoeschAnforderungResource): void { + this.facade.endgueltigLoeschen(loeschAnforderung, createVorgangLoeschenCommand()); + } - public endgueltigLoeschen(loeschAnforderung: LoeschAnforderungResource): void { - this.facade.endgueltigLoeschen(loeschAnforderung, createVorgangLoeschenCommand()); - } + public getLoschAnforderungZuruecknehmenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getLoeschAnforderungZuruecknehmenCommand().pipe( + withLatestFrom(this.vorgangService.getBackButtonUrl()), + tap(([commandStatResource, overviewUrl]) => + this.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStatResource, overviewUrl), + ), + map(([commandStatResource]) => commandStatResource), + ); + } - public getLoschAnforderungZuruecknehmenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getLoeschAnforderungZuruecknehmenCommand().pipe( - withLatestFrom(this.vorgangService.getBackButtonUrl()), - tap(([commandStatResource, overviewUrl]) => this.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStatResource, overviewUrl)), - map(([commandStatResource]) => commandStatResource)); - } + handleLoeschAnforderungZuruecknehmenCommandChanges( + commandStateResource: StateResource<CommandResource>, + overviewUrl: string, + ): void { + if (isNotFound((<HttpErrorResponse>(<unknown>commandStateResource?.error))?.status)) { + this.vorgangService.reloadCurrentVorgangWithAddtionalActions( + this.createAdditionalActions(overviewUrl), + ); + } + } - handleLoeschAnforderungZuruecknehmenCommandChanges(commandStateResource: StateResource<CommandResource>, overviewUrl: string): void { - if (isNotFound((<HttpErrorResponse><unknown>commandStateResource?.error)?.status)) { - this.vorgangService.reloadCurrentVorgangWithAddtionalActions(this.createAdditionalActions(overviewUrl)); - } - } + createAdditionalActions(overviewUrl: string): AdditionalActions { + const additionalSuccessAction = + LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess; + const additionalFailureAction = (error: HttpErrorResponse) => + LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure({ + error, + overviewUrl, + }); + return { additionalSuccessAction, additionalFailureAction }; + } - createAdditionalActions(overviewUrl: string): AdditionalActions { - const additionalSuccessAction = LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess; - const additionalFailureAction = (error: HttpErrorResponse) => LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure({ error, overviewUrl }); - return { additionalSuccessAction, additionalFailureAction }; - } - - public zuruecknehmen(loeschAnforderung: LoeschAnforderungResource): void { - this.facade.loeschAnforderungZuruecknehmen(loeschAnforderung, createLoeschAnforderungZuruecknehmenCommand()); - } -} \ No newline at end of file + public zuruecknehmen(loeschAnforderung: LoeschAnforderungResource): void { + this.facade.loeschAnforderungZuruecknehmen( + loeschAnforderung, + createLoeschAnforderungZuruecknehmenCommand(), + ); + } +} diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.util.spec.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.util.spec.ts index 9cfab4edd19bf3c397e75a74d20e6ad7df99909f..921bee9e06fe510f8412225de19ebd5078875181 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.util.spec.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.util.spec.ts @@ -1,62 +1,64 @@ import { CommandOrder, CreateCommand } from '@alfa-client/command-shared'; -import { createLoeschAnforderungZuruecknehmenCommand, createVorgangLoeschenCommand, createVorgangZumLoeschenMarkierenCommand, isLoeschAnforderungZuruecknehmen, isVorgangLoeschenCommand } from './loesch-anforderung.util'; +import { + createLoeschAnforderungZuruecknehmenCommand, + createVorgangLoeschenCommand, + createVorgangZumLoeschenMarkierenCommand, + isLoeschAnforderungZuruecknehmen, + isVorgangLoeschenCommand, +} from './loesch-anforderung.util'; describe('LoeschAnforderungUtil', () => { + describe('create LoeschenAnfordernCommand', () => { + it('should return command', () => { + const command: CreateCommand = createVorgangZumLoeschenMarkierenCommand(); - describe('create LoeschenAnfordernCommand', () => { + expect(command.order).toBe(CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN); + }); + }); - it('should return command', () => { - const command: CreateCommand = createVorgangZumLoeschenMarkierenCommand(); + describe('create EndgueltigLoeschenCommand', () => { + it('should return command', () => { + const command: CreateCommand = createVorgangLoeschenCommand(); - expect(command.order).toBe(CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN); - }) - }) + expect(command.order).toBe(CommandOrder.VORGANG_LOESCHEN); + }); + }); - describe('create EndgueltigLoeschenCommand', () => { + describe('isVorgangLoeschenCommand', () => { + it('should return true on VORGANG_LOESCHEN order', () => { + const isCommand: boolean = isVorgangLoeschenCommand(CommandOrder.VORGANG_LOESCHEN); - it('should return command', () => { - const command: CreateCommand = createVorgangLoeschenCommand(); + expect(isCommand).toBeTruthy(); + }); - expect(command.order).toBe(CommandOrder.VORGANG_LOESCHEN); - }) - }) + it('should return true on other order', () => { + const isCommand: boolean = isVorgangLoeschenCommand(CommandOrder.CREATE_KOMMENTAR); - describe('isVorgangLoeschenCommand', () => { + expect(isCommand).toBeFalsy(); + }); + }); - it('should return true on VORGANG_LOESCHEN order', () => { - const isCommand: boolean = isVorgangLoeschenCommand(CommandOrder.VORGANG_LOESCHEN); + describe('createLoeschAnforderungZuruecknehmenCommand', () => { + it('should return command', () => { + const command: CreateCommand = createLoeschAnforderungZuruecknehmenCommand(); - expect(isCommand).toBeTruthy(); - }) + expect(command.order).toBe(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN); + }); + }); - it('should return true on other order', () => { - const isCommand: boolean = isVorgangLoeschenCommand(CommandOrder.CREATE_KOMMENTAR); + describe('isLoeschAnforderungZuruecknehmen', () => { + it('should return true', () => { + const result: boolean = isLoeschAnforderungZuruecknehmen( + CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN, + ); - expect(isCommand).toBeFalsy(); - }) - }) + expect(result).toBeTruthy(); + }); - describe('createLoeschAnforderungZuruecknehmenCommand', () => { + it('should return false', () => { + const result: boolean = isLoeschAnforderungZuruecknehmen(CommandOrder.EDIT_KOMMENTAR); - it('should return command', () => { - const command: CreateCommand = createLoeschAnforderungZuruecknehmenCommand(); - - expect(command.order).toBe(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN); - }) - }) - - describe('isLoeschAnforderungZuruecknehmen', () => { - - it('should return true', () => { - const result: boolean = isLoeschAnforderungZuruecknehmen(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN); - - expect(result).toBeTruthy(); - }) - - it('should return false', () => { - const result: boolean = isLoeschAnforderungZuruecknehmen(CommandOrder.EDIT_KOMMENTAR); - - expect(result).toBeFalsy(); - }) - }) -}) \ No newline at end of file + expect(result).toBeFalsy(); + }); + }); +}); diff --git a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.util.ts b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.util.ts index 60c42670f9d683bd1785da506287ddc460f8752a..ee28226738778807cbf102ea376a4802e015eb02 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.util.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.util.ts @@ -1,25 +1,25 @@ import { CommandOrder, CreateCommand } from '@alfa-client/command-shared'; export function isVorgangZumLoeschenMarkierenCommand(order: CommandOrder): boolean { - return order === CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN; + return order === CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN; } export function createVorgangZumLoeschenMarkierenCommand(): CreateCommand { - return { order: CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN, body: null }; + return { order: CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN, body: null }; } export function isVorgangLoeschenCommand(order: CommandOrder): boolean { - return order === CommandOrder.VORGANG_LOESCHEN; + return order === CommandOrder.VORGANG_LOESCHEN; } export function createVorgangLoeschenCommand(): CreateCommand { - return { order: CommandOrder.VORGANG_LOESCHEN, body: null }; + return { order: CommandOrder.VORGANG_LOESCHEN, body: null }; } export function isLoeschAnforderungZuruecknehmen(order: CommandOrder): boolean { - return order === CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN; + return order === CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN; } export function createLoeschAnforderungZuruecknehmenCommand(): CreateCommand { - return { order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN, body: null }; -} \ No newline at end of file + return { order: CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN, body: null }; +} diff --git a/alfa-client/libs/loesch-anforderung-shared/src/test-setup.ts b/alfa-client/libs/loesch-anforderung-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/loesch-anforderung-shared/src/test-setup.ts +++ b/alfa-client/libs/loesch-anforderung-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/loesch-anforderung-shared/test/loesch-anforderung.ts b/alfa-client/libs/loesch-anforderung-shared/test/loesch-anforderung.ts index 50ef64d63369e597f29db6a684baaeb8a617e63a..b4a465e5581ec015394b51c561d4a8b959435a0b 100644 --- a/alfa-client/libs/loesch-anforderung-shared/test/loesch-anforderung.ts +++ b/alfa-client/libs/loesch-anforderung-shared/test/loesch-anforderung.ts @@ -4,12 +4,14 @@ import { VorgangStatus } from '../../vorgang-shared/src/lib/vorgang.model'; import { LoeschAnforderung, LoeschAnforderungResource } from '../src/lib/loesch-anforderung.model'; export function createLoeschAnforderung(): LoeschAnforderung { - return { - requestedBy: faker.internet.url(), - prevStatus: faker.helpers.arrayElement([VorgangStatus.ABGESCHLOSSEN, VorgangStatus.VERWORFEN]), - } + return { + requestedBy: faker.internet.url(), + prevStatus: faker.helpers.arrayElement([VorgangStatus.ABGESCHLOSSEN, VorgangStatus.VERWORFEN]), + }; } -export function createLoeschAnforderungResource(linkRelations: string[] = []): LoeschAnforderungResource { - return toResource(createLoeschAnforderung(), linkRelations); -} \ No newline at end of file +export function createLoeschAnforderungResource( + linkRelations: string[] = [], +): LoeschAnforderungResource { + return toResource(createLoeschAnforderung(), linkRelations); +} diff --git a/alfa-client/libs/loesch-anforderung-shared/tsconfig.json b/alfa-client/libs/loesch-anforderung-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/loesch-anforderung-shared/tsconfig.json +++ b/alfa-client/libs/loesch-anforderung-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/loesch-anforderung-shared/tsconfig.lib.json b/alfa-client/libs/loesch-anforderung-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/loesch-anforderung-shared/tsconfig.lib.json +++ b/alfa-client/libs/loesch-anforderung-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/loesch-anforderung-shared/tsconfig.spec.json b/alfa-client/libs/loesch-anforderung-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/loesch-anforderung-shared/tsconfig.spec.json +++ b/alfa-client/libs/loesch-anforderung-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/loesch-anforderung/.eslintrc.json b/alfa-client/libs/loesch-anforderung/.eslintrc.json index 7b7b6231394b8c5674ce1b007077d4327aea7fda..9416ef7fe3c2643718ea92627388bf35847fc788 100644 --- a/alfa-client/libs/loesch-anforderung/.eslintrc.json +++ b/alfa-client/libs/loesch-anforderung/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - }, - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ] - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + }, + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"] + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/loesch-anforderung/jest.config.ts b/alfa-client/libs/loesch-anforderung/jest.config.ts index 1a0df61686d96a21f08aa108d1fd37c29e0e307b..e88bf6022d65f936ddafce7f613123ab0e3566d0 100644 --- a/alfa-client/libs/loesch-anforderung/jest.config.ts +++ b/alfa-client/libs/loesch-anforderung/jest.config.ts @@ -1,23 +1,23 @@ /* eslint-disable */ export default { - displayName: 'loesch-anforderung', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/loesch-anforderung', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'loesch-anforderung', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/loesch-anforderung', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/loesch-anforderung/project.json b/alfa-client/libs/loesch-anforderung/project.json index c6af407e5e4e6e62047d3e06977e3394b60923fc..fe63ee86a96ba388d2ca185657e89d9702be56f9 100644 --- a/alfa-client/libs/loesch-anforderung/project.json +++ b/alfa-client/libs/loesch-anforderung/project.json @@ -1,29 +1,26 @@ { - "name": "loesch-anforderung", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/loesch-anforderung/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/loesch-anforderung"], - "options": { - "tsConfig": "libs/loesch-anforderung/tsconfig.spec.json", - "jestConfig": "libs/loesch-anforderung/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "libs/loesch-anforderung/**/*.ts", - "libs/loesch-anforderung/**/*.html" - ] - } - } - }, - "tags": [] + "name": "loesch-anforderung", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/loesch-anforderung/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/loesch-anforderung"], + "options": { + "tsConfig": "libs/loesch-anforderung/tsconfig.spec.json", + "jestConfig": "libs/loesch-anforderung/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/loesch-anforderung/**/*.ts", "libs/loesch-anforderung/**/*.html"] + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.html b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.html index f1747ce9b5a3793557dfe00e4ff295a0855652ee..5b86d12563b6b00a014bdcdec3b4fcb543c45bd1 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.html +++ b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.html @@ -1,12 +1,13 @@ <ng-container *ngIf="loeschAnforderungResource$ | async as loeschAnforderungResource"> - <ng-container *ngIf="loeschAnforderungResource.resource | hasLink: loeschAnforderungLinkRel.EXECUTE_LOESCHEN"> - <ng-container *ngIf="commandStateResource$ | async"> - - <alfa-endgueltig-loeschen-button - [showAsIconButton]="showAsIconButton" - (endgueltigLoeschen)="openEndgueltigLoeschenDialog(loeschAnforderungResource)"> - </alfa-endgueltig-loeschen-button> - - </ng-container> - </ng-container> -</ng-container> \ No newline at end of file + <ng-container + *ngIf="loeschAnforderungResource.resource | hasLink: loeschAnforderungLinkRel.EXECUTE_LOESCHEN" + > + <ng-container *ngIf="commandStateResource$ | async"> + <alfa-endgueltig-loeschen-button + [showAsIconButton]="showAsIconButton" + (endgueltigLoeschen)="openEndgueltigLoeschenDialog(loeschAnforderungResource)" + > + </alfa-endgueltig-loeschen-button> + </ng-container> + </ng-container> +</ng-container> diff --git a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.spec.ts b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.spec.ts index ac07f04c51500510b70d340d89f3f2d127de2155..ab5c2be0bd7112b7a07759ab3490978f9e4ab5fa 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.spec.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.spec.ts @@ -1,8 +1,16 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { LoeschAnforderungResource, LoeschAnforderungService } from '@alfa-client/loesch-anforderung-shared'; -import { HasLinkPipe, StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + LoeschAnforderungResource, + LoeschAnforderungService, +} from '@alfa-client/loesch-anforderung-shared'; +import { + HasLinkPipe, + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; import { BasicDialogComponent, BasicDialogData, DialogService } from '@alfa-client/ui'; import { VorgangService } from '@alfa-client/vorgang-shared'; @@ -13,131 +21,126 @@ import { EndgueltigLoeschenButtonContainerComponent } from './endgueltig-loesche import { EndgueltigLoeschenButtonComponent } from './endgueltig-loeschen-button/endgueltig-loeschen-button.component'; describe('EndgueltigLoeschenButtonContainerComponent', () => { - let component: EndgueltigLoeschenButtonContainerComponent; - let fixture: ComponentFixture<EndgueltigLoeschenButtonContainerComponent>; - - const loeschAnforderungResource: StateResource<LoeschAnforderungResource> = createEmptyStateResource(); - - const dialogRef = <MatDialogRef<BasicDialogComponent>>{}; - dialogRef.afterClosed = jest.fn().mockReturnValue(of(true)); - - const loeschAnforderungService = mock(LoeschAnforderungService); - const vorgangService = mock(VorgangService); - const dialogService = mock(DialogService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - EndgueltigLoeschenButtonContainerComponent, - HasLinkPipe, - MockComponent(EndgueltigLoeschenButtonComponent) - ], - imports: [ - BrowserAnimationsModule, - MatDialogModule - ], - providers: [ - { - provide: MatDialogRef, - useValue: {} - }, - { - provide: LoeschAnforderungService, - useValue: loeschAnforderungService - }, - { - provide: VorgangService, - useValue: vorgangService, - }, - { - provide: DialogService, - useValue: dialogService, - } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(EndgueltigLoeschenButtonContainerComponent); - component = fixture.componentInstance; - loeschAnforderungService.getEndgueltigLoeschenCommand.mockReturnValue(of(createStateResource(createCommandResource()))); - dialogService.openBasic = jest.fn().mockReturnValue(dialogRef); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call vorgangCommandService#getEndgueltigLoeschenCommand', () => { - component.ngOnInit(); - - expect(loeschAnforderungService.getEndgueltigLoeschenCommand).toHaveBeenCalled(); - }) - - it('should call loeschAnforderungService#getLoeschAnforderung', () => { - component.ngOnInit(); - - expect(loeschAnforderungService.getLoeschAnforderung).toHaveBeenCalled(); - }) - }) - - describe('openEndgueltigLoeschenDialog', () => { - - it('should call dialogService.openBasic', () => { - component.openEndgueltigLoeschenDialog(loeschAnforderungResource); - - expect(dialogService.openBasic).toHaveBeenCalled(); - }) - - it('should call createBasicDialogConfig', () => { - component.createBasicDialogConfig = jest.fn(); - - component.openEndgueltigLoeschenDialog(loeschAnforderungResource); - - expect(component.createBasicDialogConfig).toHaveBeenCalled(); - }) - - it('should call dialogRef.afterClosed', () => { - component.openEndgueltigLoeschenDialog(loeschAnforderungResource); - - expect(dialogRef.afterClosed).toHaveBeenCalled(); - }) - - it('should call component.endgueltigLoeschen', () => { - component.endgueltigLoeschen = jest.fn(); - - component.openEndgueltigLoeschenDialog(loeschAnforderungResource); - - expect(component.endgueltigLoeschen).toHaveBeenCalled(); - }) - - }) - - describe('createBasicDialogConfig', () => { - - it('should return BasicDialogData', () => { - const basicDialogData: BasicDialogData = { - title: 'Möchten Sie den Vorgang endgültig löschen?', - message: 'Diese Aktion kann nicht widerrufen werden.', - okText: 'Endgültig löschen', - okSvgIcon: 'delete_finally' - } - - const res = component.createBasicDialogConfig(); - - expect(res).toMatchObject<BasicDialogData>(basicDialogData); - }) - }) - - describe('endgueltigLoeschen', () => { - - it('should call service', () => { - const spy = jest.spyOn(loeschAnforderungService, 'endgueltigLoeschen'); - - component.endgueltigLoeschen(loeschAnforderungResource); - - expect(spy).toHaveBeenCalledWith(loeschAnforderungResource.resource); - }) - }) + let component: EndgueltigLoeschenButtonContainerComponent; + let fixture: ComponentFixture<EndgueltigLoeschenButtonContainerComponent>; + + const loeschAnforderungResource: StateResource<LoeschAnforderungResource> = + createEmptyStateResource(); + + const dialogRef = <MatDialogRef<BasicDialogComponent>>{}; + dialogRef.afterClosed = jest.fn().mockReturnValue(of(true)); + + const loeschAnforderungService = mock(LoeschAnforderungService); + const vorgangService = mock(VorgangService); + const dialogService = mock(DialogService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + EndgueltigLoeschenButtonContainerComponent, + HasLinkPipe, + MockComponent(EndgueltigLoeschenButtonComponent), + ], + imports: [BrowserAnimationsModule, MatDialogModule], + providers: [ + { + provide: MatDialogRef, + useValue: {}, + }, + { + provide: LoeschAnforderungService, + useValue: loeschAnforderungService, + }, + { + provide: VorgangService, + useValue: vorgangService, + }, + { + provide: DialogService, + useValue: dialogService, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(EndgueltigLoeschenButtonContainerComponent); + component = fixture.componentInstance; + loeschAnforderungService.getEndgueltigLoeschenCommand.mockReturnValue( + of(createStateResource(createCommandResource())), + ); + dialogService.openBasic = jest.fn().mockReturnValue(dialogRef); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call vorgangCommandService#getEndgueltigLoeschenCommand', () => { + component.ngOnInit(); + + expect(loeschAnforderungService.getEndgueltigLoeschenCommand).toHaveBeenCalled(); + }); + + it('should call loeschAnforderungService#getLoeschAnforderung', () => { + component.ngOnInit(); + + expect(loeschAnforderungService.getLoeschAnforderung).toHaveBeenCalled(); + }); + }); + + describe('openEndgueltigLoeschenDialog', () => { + it('should call dialogService.openBasic', () => { + component.openEndgueltigLoeschenDialog(loeschAnforderungResource); + + expect(dialogService.openBasic).toHaveBeenCalled(); + }); + + it('should call createBasicDialogConfig', () => { + component.createBasicDialogConfig = jest.fn(); + + component.openEndgueltigLoeschenDialog(loeschAnforderungResource); + + expect(component.createBasicDialogConfig).toHaveBeenCalled(); + }); + + it('should call dialogRef.afterClosed', () => { + component.openEndgueltigLoeschenDialog(loeschAnforderungResource); + + expect(dialogRef.afterClosed).toHaveBeenCalled(); + }); + + it('should call component.endgueltigLoeschen', () => { + component.endgueltigLoeschen = jest.fn(); + + component.openEndgueltigLoeschenDialog(loeschAnforderungResource); + + expect(component.endgueltigLoeschen).toHaveBeenCalled(); + }); + }); + + describe('createBasicDialogConfig', () => { + it('should return BasicDialogData', () => { + const basicDialogData: BasicDialogData = { + title: 'Möchten Sie den Vorgang endgültig löschen?', + message: 'Diese Aktion kann nicht widerrufen werden.', + okText: 'Endgültig löschen', + okSvgIcon: 'delete_finally', + }; + + const res = component.createBasicDialogConfig(); + + expect(res).toMatchObject<BasicDialogData>(basicDialogData); + }); + }); + + describe('endgueltigLoeschen', () => { + it('should call service', () => { + const spy = jest.spyOn(loeschAnforderungService, 'endgueltigLoeschen'); + + component.endgueltigLoeschen(loeschAnforderungResource); + + expect(spy).toHaveBeenCalledWith(loeschAnforderungResource.resource); + }); + }); }); diff --git a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.ts b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.ts index 64a18c03c80b0a2b013573d4cdb7854b205c20ca..48a451f4714b9f5ca7a7ca7a3763a99c04d679cc 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component.ts @@ -1,55 +1,74 @@ import { Component, Input } from '@angular/core'; import { MatDialogRef } from '@angular/material/dialog'; import { CommandResource } from '@alfa-client/command-shared'; -import { LoeschAnforderungResource, LoeschAnforderungService } from '@alfa-client/loesch-anforderung-shared'; +import { + LoeschAnforderungResource, + LoeschAnforderungService, +} from '@alfa-client/loesch-anforderung-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; import { BasicDialogComponent, BasicDialogData, DialogService } from '@alfa-client/ui'; -import { LoeschAnforderungLinkRel, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + LoeschAnforderungLinkRel, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { Observable, filter, first, of } from 'rxjs'; @Component({ - selector: 'alfa-endgueltig-loeschen-button-container', - templateUrl: './endgueltig-loeschen-button-container.component.html', - styleUrls: ['./endgueltig-loeschen-button-container.component.scss'], + selector: 'alfa-endgueltig-loeschen-button-container', + templateUrl: './endgueltig-loeschen-button-container.component.html', + styleUrls: ['./endgueltig-loeschen-button-container.component.scss'], }) export class EndgueltigLoeschenButtonContainerComponent { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean = false; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean = false; + commandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); + loeschAnforderungResource$: Observable<StateResource<LoeschAnforderungResource>>; - commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); - loeschAnforderungResource$: Observable<StateResource<LoeschAnforderungResource>>; + readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; + readonly loeschAnforderungLinkRel = LoeschAnforderungLinkRel; - readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; - readonly loeschAnforderungLinkRel = LoeschAnforderungLinkRel; + dialogRef: MatDialogRef<BasicDialogComponent>; - dialogRef: MatDialogRef<BasicDialogComponent>; + constructor( + private loeschAnforderungService: LoeschAnforderungService, + private dialogService: DialogService, + ) {} - constructor( - private loeschAnforderungService: LoeschAnforderungService, - private dialogService: DialogService) {} + ngOnInit(): void { + this.commandStateResource$ = this.loeschAnforderungService.getEndgueltigLoeschenCommand(); + this.loeschAnforderungResource$ = this.loeschAnforderungService.getLoeschAnforderung(); + } - ngOnInit(): void { - this.commandStateResource$ = this.loeschAnforderungService.getEndgueltigLoeschenCommand(); - this.loeschAnforderungResource$ = this.loeschAnforderungService.getLoeschAnforderung(); - } + public openEndgueltigLoeschenDialog( + loeschAnforderungResource: StateResource<LoeschAnforderungResource>, + ): void { + const dialogRef: MatDialogRef<BasicDialogComponent> = this.dialogService.openBasic( + this.createBasicDialogConfig(), + ); - public openEndgueltigLoeschenDialog(loeschAnforderungResource: StateResource<LoeschAnforderungResource>): void { - const dialogRef: MatDialogRef<BasicDialogComponent> = this.dialogService.openBasic(this.createBasicDialogConfig()); + dialogRef + .afterClosed() + .pipe( + first(), + filter((response) => response === true), + ) + .subscribe(() => this.endgueltigLoeschen(loeschAnforderungResource)); + } - dialogRef.afterClosed().pipe(first(), filter(response => response === true)).subscribe(() => this.endgueltigLoeschen(loeschAnforderungResource)); - } + createBasicDialogConfig(): BasicDialogData { + return { + title: 'Möchten Sie den Vorgang endgültig löschen?', + message: 'Diese Aktion kann nicht widerrufen werden.', + okText: 'Endgültig löschen', + okSvgIcon: 'delete_finally', + }; + } - createBasicDialogConfig(): BasicDialogData { - return { - title: 'Möchten Sie den Vorgang endgültig löschen?', - message: 'Diese Aktion kann nicht widerrufen werden.', - okText: 'Endgültig löschen', - okSvgIcon: 'delete_finally' - } - } - - endgueltigLoeschen(loeschAnforderungResource: StateResource<LoeschAnforderungResource>): void { - this.loeschAnforderungService.endgueltigLoeschen(loeschAnforderungResource.resource); - } + endgueltigLoeschen(loeschAnforderungResource: StateResource<LoeschAnforderungResource>): void { + this.loeschAnforderungService.endgueltigLoeschen(loeschAnforderungResource.resource); + } } diff --git a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.html b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.html index a61f3a7afa2150aa494f499b2c336c3a1fd7e748..a944b0097d8ce77200005f8d46b8044304ae4643 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.html +++ b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.html @@ -1,11 +1,17 @@ -<ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="endgueltig-loeschen-button" - text="Endgültig löschen" - svgIcon="delete_finally" - (clickEmitter)="endgueltigLoeschen.emit()"> +<ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="endgueltig-loeschen-button" + text="Endgültig löschen" + svgIcon="delete_finally" + (clickEmitter)="endgueltigLoeschen.emit()" +> </ozgcloud-stroked-button-with-spinner> -<ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="endgueltig-loeschen-icon-button" - toolTip="Endgültig löschen" - svgIcon="delete_finally" - (clickEmitter)="endgueltigLoeschen.emit()"> -</ozgcloud-icon-button-with-spinner> \ No newline at end of file +<ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="endgueltig-loeschen-icon-button" + toolTip="Endgültig löschen" + svgIcon="delete_finally" + (clickEmitter)="endgueltigLoeschen.emit()" +> +</ozgcloud-icon-button-with-spinner> diff --git a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.spec.ts b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.spec.ts index bd6c855c64064dc724088fbf2c221e8f73583b2e..a63bd7d06d3e299b07ebb8190e11df5366f241ef 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.spec.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.spec.ts @@ -1,70 +1,71 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent } from 'ng-mocks'; import { EndgueltigLoeschenButtonComponent } from './endgueltig-loeschen-button.component'; describe('EndgueltigLoeschenButtonComponent', () => { - let component: EndgueltigLoeschenButtonComponent; - let fixture: ComponentFixture<EndgueltigLoeschenButtonComponent>; + let component: EndgueltigLoeschenButtonComponent; + let fixture: ComponentFixture<EndgueltigLoeschenButtonComponent>; - const endgueltigLoeschenButton = getDataTestIdOf('endgueltig-loeschen-button'); - const endgueltigLoeschenIconButton = getDataTestIdOf('endgueltig-loeschen-icon-button'); + const endgueltigLoeschenButton = getDataTestIdOf('endgueltig-loeschen-button'); + const endgueltigLoeschenIconButton = getDataTestIdOf('endgueltig-loeschen-icon-button'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - EndgueltigLoeschenButtonComponent, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent), - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + EndgueltigLoeschenButtonComponent, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(EndgueltigLoeschenButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(EndgueltigLoeschenButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('button with spinner', () => { + describe('button with spinner', () => { + it('should be hidden', () => { + component.showAsIconButton = true; - it('should be hidden', () => { - component.showAsIconButton = true; + fixture.detectChanges(); - fixture.detectChanges(); + notExistsAsHtmlElement(fixture, endgueltigLoeschenButton); + }); - notExistsAsHtmlElement(fixture, endgueltigLoeschenButton); - }); + it('should be visible', () => { + component.showAsIconButton = false; - it('should be visible', () => { - component.showAsIconButton = false; + fixture.detectChanges(); - fixture.detectChanges(); + existsAsHtmlElement(fixture, endgueltigLoeschenButton); + }); + }); - existsAsHtmlElement(fixture, endgueltigLoeschenButton); - }); - }) + describe('icon button with spinner', () => { + it('should be hidden', () => { + component.showAsIconButton = false; - describe('icon button with spinner', () => { + fixture.detectChanges(); - it('should be hidden', () => { - component.showAsIconButton = false; + notExistsAsHtmlElement(fixture, endgueltigLoeschenIconButton); + }); - fixture.detectChanges(); + it('should be visible', () => { + component.showAsIconButton = true; - notExistsAsHtmlElement(fixture, endgueltigLoeschenIconButton); - }); + fixture.detectChanges(); - it('should be visible', () => { - component.showAsIconButton = true; - - fixture.detectChanges(); - - existsAsHtmlElement(fixture, endgueltigLoeschenIconButton); - }); - }) + existsAsHtmlElement(fixture, endgueltigLoeschenIconButton); + }); + }); }); diff --git a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.ts b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.ts index 2a91d2ab6385e24eb745bf77b4ff9bb6ca4ad424..d6b9a3434a4608549aebdf9da7aeba44c0734a83 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component.ts @@ -1,14 +1,12 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ - selector: 'alfa-endgueltig-loeschen-button', - templateUrl: './endgueltig-loeschen-button.component.html', - styleUrls: ['./endgueltig-loeschen-button.component.scss'], + selector: 'alfa-endgueltig-loeschen-button', + templateUrl: './endgueltig-loeschen-button.component.html', + styleUrls: ['./endgueltig-loeschen-button.component.scss'], }) export class EndgueltigLoeschenButtonComponent { + @Input() showAsIconButton: boolean = false; - @Input() showAsIconButton: boolean = false; - - @Output() endgueltigLoeschen: EventEmitter<void> = new EventEmitter<void>(); - -} \ No newline at end of file + @Output() endgueltigLoeschen: EventEmitter<void> = new EventEmitter<void>(); +} diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.html b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.html index e1662392021006b6b38be1410604e437de8b3cdf..cf07f218f246149d322a6baadd5b117355d5aff1 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.html +++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.html @@ -1,10 +1,13 @@ <ng-container *ngIf="loeschAnforderungStateResource$ | async as loeschAnforderungResource"> - <ng-container *ngIf="loeschAnforderungResource.resource | hasLink: loeschAnforderungLinkRel.ZURUECKNEHMEN"> - - <alfa-loesch-anforderung-zuruecknehmen-button data-test-id="loesch-anforderung-zuruecknehmen-button-component" - [showAsIconButton]="showAsIconButton" [loeschAnforderungZuruecknehmenCommand]="loeschAnforderungZuruecknehmenCommand$ | async" - (loeschAnforderungZuruecknehmen)="loeschAnforderungZuruecknehmen(loeschAnforderungResource)"> - </alfa-loesch-anforderung-zuruecknehmen-button> - - </ng-container> -</ng-container> \ No newline at end of file + <ng-container + *ngIf="loeschAnforderungResource.resource | hasLink: loeschAnforderungLinkRel.ZURUECKNEHMEN" + > + <alfa-loesch-anforderung-zuruecknehmen-button + data-test-id="loesch-anforderung-zuruecknehmen-button-component" + [showAsIconButton]="showAsIconButton" + [loeschAnforderungZuruecknehmenCommand]="loeschAnforderungZuruecknehmenCommand$ | async" + (loeschAnforderungZuruecknehmen)="loeschAnforderungZuruecknehmen(loeschAnforderungResource)" + > + </alfa-loesch-anforderung-zuruecknehmen-button> + </ng-container> +</ng-container> diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.spec.ts b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.spec.ts index 275339780386add206f0a5e4a352f198de5c57d6..5fd9423c5b68f2d357d92ccd0f720ca60a9cce1a 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.spec.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.spec.ts @@ -1,85 +1,100 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { LoeschAnforderungLinkRel, LoeschAnforderungResource, LoeschAnforderungService } from "@alfa-client/loesch-anforderung-shared"; -import { HasLinkPipe, StateResource, createEmptyStateResource, createStateResource } from "@alfa-client/tech-shared"; -import { Mock, existsAsHtmlElement, mock, notExistsAsHtmlElement } from "@alfa-client/test-utils"; +import { + LoeschAnforderungLinkRel, + LoeschAnforderungResource, + LoeschAnforderungService, +} from '@alfa-client/loesch-anforderung-shared'; +import { + HasLinkPipe, + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; +import { Mock, existsAsHtmlElement, mock, notExistsAsHtmlElement } from '@alfa-client/test-utils'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent } from 'ng-mocks'; import { of } from 'rxjs'; import { createLoeschAnforderungResource } from '../../../../loesch-anforderung-shared/test/loesch-anforderung'; -import { LoeschAnforderungZuruecknehmenButtonContainerComponent } from "./loesch-anforderung-zuruecknehmen-button-container.component"; +import { LoeschAnforderungZuruecknehmenButtonContainerComponent } from './loesch-anforderung-zuruecknehmen-button-container.component'; import { LoeschAnforderungZuruecknehmenButtonComponent } from './loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component'; describe('LoeschAnforderungZuruecknehmenButtonComponent', () => { - let component: LoeschAnforderungZuruecknehmenButtonContainerComponent; - let fixture: ComponentFixture<LoeschAnforderungZuruecknehmenButtonContainerComponent>; - - const service: Mock<LoeschAnforderungService> = mock(LoeschAnforderungService); - const loeschAnforderungResource: StateResource<LoeschAnforderungResource> = createEmptyStateResource(); - - const loeschAnforderungZuruecknehmenButtonComponent: string = getDataTestIdOf('loesch-anforderung-zuruecknehmen-button-component'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - LoeschAnforderungZuruecknehmenButtonContainerComponent, - HasLinkPipe, - MockComponent(LoeschAnforderungZuruecknehmenButtonComponent) - ], - providers: [ - { - provide: LoeschAnforderungService, - useValue: service - } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(LoeschAnforderungZuruecknehmenButtonContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }) - - it('should create', () => { - expect(component).toBeTruthy(); - }) - - describe('ngOnInit', () => { - - it('should get loeschAnforderungZuruecknehmenCommand', () => { - component.ngOnInit(); - - expect(service.getLoschAnforderungZuruecknehmenCommand).toHaveBeenCalled(); - }) - - it('should get LoeschAnforderung Resource', () => { - component.ngOnInit(); - - expect(service.getLoeschAnforderung).toHaveBeenCalled(); - }) - }) - - describe('loeschAnforderungZuruecknehmen', () => { - - it('should call service', () => { - component.loeschAnforderungZuruecknehmen(loeschAnforderungResource); - - expect(service.zuruecknehmen).toHaveBeenCalledWith(loeschAnforderungResource.resource); - }) - }) - - describe('loeschAnforderungButtonComponent', () => { - - it('should be visible if link exists on LoeschAnforderung', () => { - component.loeschAnforderungStateResource$ = of(createStateResource(createLoeschAnforderungResource([LoeschAnforderungLinkRel.ZURUECKNEHMEN]))); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, loeschAnforderungZuruecknehmenButtonComponent); - }) - - it('should be hidden if link NOT exists', () => { - component.loeschAnforderungStateResource$ = of(createStateResource(createLoeschAnforderungResource())); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, loeschAnforderungZuruecknehmenButtonComponent); - }) - }) -}); \ No newline at end of file + let component: LoeschAnforderungZuruecknehmenButtonContainerComponent; + let fixture: ComponentFixture<LoeschAnforderungZuruecknehmenButtonContainerComponent>; + + const service: Mock<LoeschAnforderungService> = mock(LoeschAnforderungService); + const loeschAnforderungResource: StateResource<LoeschAnforderungResource> = + createEmptyStateResource(); + + const loeschAnforderungZuruecknehmenButtonComponent: string = getDataTestIdOf( + 'loesch-anforderung-zuruecknehmen-button-component', + ); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + LoeschAnforderungZuruecknehmenButtonContainerComponent, + HasLinkPipe, + MockComponent(LoeschAnforderungZuruecknehmenButtonComponent), + ], + providers: [ + { + provide: LoeschAnforderungService, + useValue: service, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(LoeschAnforderungZuruecknehmenButtonContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should get loeschAnforderungZuruecknehmenCommand', () => { + component.ngOnInit(); + + expect(service.getLoschAnforderungZuruecknehmenCommand).toHaveBeenCalled(); + }); + + it('should get LoeschAnforderung Resource', () => { + component.ngOnInit(); + + expect(service.getLoeschAnforderung).toHaveBeenCalled(); + }); + }); + + describe('loeschAnforderungZuruecknehmen', () => { + it('should call service', () => { + component.loeschAnforderungZuruecknehmen(loeschAnforderungResource); + + expect(service.zuruecknehmen).toHaveBeenCalledWith(loeschAnforderungResource.resource); + }); + }); + + describe('loeschAnforderungButtonComponent', () => { + it('should be visible if link exists on LoeschAnforderung', () => { + component.loeschAnforderungStateResource$ = of( + createStateResource( + createLoeschAnforderungResource([LoeschAnforderungLinkRel.ZURUECKNEHMEN]), + ), + ); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, loeschAnforderungZuruecknehmenButtonComponent); + }); + + it('should be hidden if link NOT exists', () => { + component.loeschAnforderungStateResource$ = of( + createStateResource(createLoeschAnforderungResource()), + ); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, loeschAnforderungZuruecknehmenButtonComponent); + }); + }); +}); diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.ts b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.ts index a62261d39111f4b37282e7bfdf48d0e4f5f6114f..620063619ac385210e5719f9c79a2bff25d5a9ff 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component.ts @@ -1,31 +1,39 @@ import { Component, Input } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; -import { LoeschAnforderungLinkRel, LoeschAnforderungResource, LoeschAnforderungService } from '@alfa-client/loesch-anforderung-shared'; +import { + LoeschAnforderungLinkRel, + LoeschAnforderungResource, + LoeschAnforderungService, +} from '@alfa-client/loesch-anforderung-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-loesch-anforderung-zuruecknehmen-button-container', - templateUrl: './loesch-anforderung-zuruecknehmen-button-container.component.html', - styleUrls: ['./loesch-anforderung-zuruecknehmen-button-container.component.scss'], + selector: 'alfa-loesch-anforderung-zuruecknehmen-button-container', + templateUrl: './loesch-anforderung-zuruecknehmen-button-container.component.html', + styleUrls: ['./loesch-anforderung-zuruecknehmen-button-container.component.scss'], }) export class LoeschAnforderungZuruecknehmenButtonContainerComponent { + @Input() showAsIconButton: boolean = false; - @Input() showAsIconButton: boolean = false; + loeschAnforderungStateResource$: Observable<StateResource<LoeschAnforderungResource>>; + loeschAnforderungZuruecknehmenCommand$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - loeschAnforderungStateResource$: Observable<StateResource<LoeschAnforderungResource>>; - loeschAnforderungZuruecknehmenCommand$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly loeschAnforderungLinkRel = LoeschAnforderungLinkRel; - readonly loeschAnforderungLinkRel = LoeschAnforderungLinkRel; + constructor(private loeschAnforderungService: LoeschAnforderungService) {} - constructor(private loeschAnforderungService: LoeschAnforderungService) { } + ngOnInit(): void { + this.loeschAnforderungZuruecknehmenCommand$ = + this.loeschAnforderungService.getLoschAnforderungZuruecknehmenCommand(); + this.loeschAnforderungStateResource$ = this.loeschAnforderungService.getLoeschAnforderung(); + } - ngOnInit(): void { - this.loeschAnforderungZuruecknehmenCommand$ = this.loeschAnforderungService.getLoschAnforderungZuruecknehmenCommand(); - this.loeschAnforderungStateResource$ = this.loeschAnforderungService.getLoeschAnforderung(); - } - - public loeschAnforderungZuruecknehmen(loeschAnforderungResource: StateResource<LoeschAnforderungResource>): void { - this.loeschAnforderungService.zuruecknehmen(loeschAnforderungResource.resource); - } + public loeschAnforderungZuruecknehmen( + loeschAnforderungResource: StateResource<LoeschAnforderungResource>, + ): void { + this.loeschAnforderungService.zuruecknehmen(loeschAnforderungResource.resource); + } } diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.html b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.html index 7874ddf1c8c8fe9e225b3175d9b640df90aaa110..068e296fddb61d834ac20feb6ea22acef5edd3af 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.html +++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.html @@ -1,13 +1,19 @@ -<ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="loesch-anforderung-zuruecknehmen-button" - text="Löschanforderung zurücknehmen" - svgIcon="undo_request_deletion" - [stateResource]="loeschAnforderungZuruecknehmenCommand" - (clickEmitter)="loeschAnforderungZuruecknehmen.emit()"> +<ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="loesch-anforderung-zuruecknehmen-button" + text="Löschanforderung zurücknehmen" + svgIcon="undo_request_deletion" + [stateResource]="loeschAnforderungZuruecknehmenCommand" + (clickEmitter)="loeschAnforderungZuruecknehmen.emit()" +> </ozgcloud-stroked-button-with-spinner> -<ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="loesch-anforderung-zuruecknehmen-icon-button" - svgIcon="undo_request_deletion" - toolTip="Löschanforderung zurücknehmen" - [stateResource]="loeschAnforderungZuruecknehmenCommand" - (clickEmitter)="loeschAnforderungZuruecknehmen.emit()"> -</ozgcloud-icon-button-with-spinner> \ No newline at end of file +<ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="loesch-anforderung-zuruecknehmen-icon-button" + svgIcon="undo_request_deletion" + toolTip="Löschanforderung zurücknehmen" + [stateResource]="loeschAnforderungZuruecknehmenCommand" + (clickEmitter)="loeschAnforderungZuruecknehmen.emit()" +> +</ozgcloud-icon-button-with-spinner> diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.spec.ts b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.spec.ts index 3734011dc12064a55a9b99f4a54b41b047ebb457..e8e8a2406724b4c456fb5b482193f73ffe6aa722 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.spec.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.spec.ts @@ -1,64 +1,69 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from "@alfa-client/ui"; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; -import { MockComponent } from "ng-mocks"; +import { MockComponent } from 'ng-mocks'; import { LoeschAnforderungZuruecknehmenButtonComponent } from './loesch-anforderung-zuruecknehmen-button.component'; describe('LoeschAnforderungZuruecknehmenButtonComponent', () => { - let component: LoeschAnforderungZuruecknehmenButtonComponent; - let fixture: ComponentFixture<LoeschAnforderungZuruecknehmenButtonComponent>; + let component: LoeschAnforderungZuruecknehmenButtonComponent; + let fixture: ComponentFixture<LoeschAnforderungZuruecknehmenButtonComponent>; - const loeschenAnfordernZuruecknehmenButton: string = getDataTestIdOf('loesch-anforderung-zuruecknehmen-button'); - const loeschenAnfordernZuruecknehmenIconButton: string = getDataTestIdOf('loesch-anforderung-zuruecknehmen-icon-button'); + const loeschenAnfordernZuruecknehmenButton: string = getDataTestIdOf( + 'loesch-anforderung-zuruecknehmen-button', + ); + const loeschenAnfordernZuruecknehmenIconButton: string = getDataTestIdOf( + 'loesch-anforderung-zuruecknehmen-icon-button', + ); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - LoeschAnforderungZuruecknehmenButtonComponent, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + LoeschAnforderungZuruecknehmenButtonComponent, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(LoeschAnforderungZuruecknehmenButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(LoeschAnforderungZuruecknehmenButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('show as icon button', () => { + describe('show as icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) + it('should hide button', () => { + notExistsAsHtmlElement(fixture, loeschenAnfordernZuruecknehmenButton); + }); - it('should hide button', () => { - notExistsAsHtmlElement(fixture, loeschenAnfordernZuruecknehmenButton); - }); + it('should show iconButton', () => { + existsAsHtmlElement(fixture, loeschenAnfordernZuruecknehmenIconButton); + }); + }); - it('should show iconButton', () => { - existsAsHtmlElement(fixture, loeschenAnfordernZuruecknehmenIconButton); - }); - }) + describe('show as button', () => { + beforeEach(() => { + component.showAsIconButton = false; + fixture.detectChanges(); + }); - describe('show as button', () => { + it('should show button', () => { + existsAsHtmlElement(fixture, loeschenAnfordernZuruecknehmenButton); + }); - beforeEach(() => { - component.showAsIconButton = false; - fixture.detectChanges(); - }) - - it('should show button', () => { - existsAsHtmlElement(fixture, loeschenAnfordernZuruecknehmenButton); - }); - - it('should hide iconButton visible', () => { - notExistsAsHtmlElement(fixture, loeschenAnfordernZuruecknehmenIconButton); - }); - }) -}); \ No newline at end of file + it('should hide iconButton visible', () => { + notExistsAsHtmlElement(fixture, loeschenAnfordernZuruecknehmenIconButton); + }); + }); +}); diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.ts b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.ts index 20f832ba5949035aa807c829531a6f73d8d34906..d7e34b92d94c393da56a4cc920cc2080c7cce1ee 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component.ts @@ -1,16 +1,15 @@ -import { Component, EventEmitter, Input, Output } from "@angular/core"; -import { CommandResource } from "@alfa-client/command-shared"; -import { StateResource } from "@alfa-client/tech-shared"; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { CommandResource } from '@alfa-client/command-shared'; +import { StateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-loesch-anforderung-zuruecknehmen-button', - templateUrl: './loesch-anforderung-zuruecknehmen-button.component.html', - styleUrls: ['./loesch-anforderung-zuruecknehmen-button.component.scss'], + selector: 'alfa-loesch-anforderung-zuruecknehmen-button', + templateUrl: './loesch-anforderung-zuruecknehmen-button.component.html', + styleUrls: ['./loesch-anforderung-zuruecknehmen-button.component.scss'], }) export class LoeschAnforderungZuruecknehmenButtonComponent { + @Input() showAsIconButton: boolean = false; + @Input() loeschAnforderungZuruecknehmenCommand: StateResource<CommandResource>; - @Input() showAsIconButton: boolean = false; - @Input() loeschAnforderungZuruecknehmenCommand: StateResource<CommandResource>; - - @Output() loeschAnforderungZuruecknehmen: EventEmitter<void> = new EventEmitter<void>(); + @Output() loeschAnforderungZuruecknehmen: EventEmitter<void> = new EventEmitter<void>(); } diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.spec.ts b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.spec.ts index 20a140a2e44b1a9dcc3837d0fbb63ffbed35d185..665fe0cbcf1aae0bbe2458c40119422f49a860db 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.spec.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.spec.ts @@ -2,14 +2,13 @@ import { TestBed } from '@angular/core/testing'; import { LoeschAnforderungModule } from './loesch-anforderung.module'; describe('LoeschAnforderungModule', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [LoeschAnforderungModule], + }).compileComponents(); + }); - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [LoeschAnforderungModule], - }).compileComponents(); - }); - - it('should create', () => { - expect(LoeschAnforderungModule).toBeDefined(); - }); + it('should create', () => { + expect(LoeschAnforderungModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts index c0b06e94d46ee3ab8b5afede423ff2e7d5340dfd..c51686f38c360e3e3174ded6eed555e0edc894af 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/loesch-anforderung.module.ts @@ -5,41 +5,32 @@ import { TechSharedModule } from '@alfa-client/tech-shared'; import { UiModule } from '@alfa-client/ui'; import { VorgangSharedModule } from '@alfa-client/vorgang-shared'; import { EndgueltigLoeschenButtonContainerComponent } from './endgueltig-loeschen-button-container/endgueltig-loeschen-button-container.component'; -import { - EndgueltigLoeschenButtonComponent -} from './endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component'; +import { EndgueltigLoeschenButtonComponent } from './endgueltig-loeschen-button-container/endgueltig-loeschen-button/endgueltig-loeschen-button.component'; import { LoeschenAnfordernButtonContainerComponent } from './loeschen-anfordern-button-container/loeschen-anfordern-button-container.component'; -import { - LoeschenAnfordernButtonComponent -} from './loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component'; -import { - LoeschAnforderungZuruecknehmenButtonComponent -} from './loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component'; -import { - LoeschAnforderungZuruecknehmenButtonContainerComponent -} from "./loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component"; +import { LoeschenAnfordernButtonComponent } from './loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component'; +import { LoeschAnforderungZuruecknehmenButtonComponent } from './loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button/loesch-anforderung-zuruecknehmen-button.component'; +import { LoeschAnforderungZuruecknehmenButtonContainerComponent } from './loesch-anforderung-zuruecknehmen-button-container/loesch-anforderung-zuruecknehmen-button-container.component'; @NgModule({ - imports: [ - CommonModule, - LoeschAnforderungSharedModule, - TechSharedModule, - UiModule, - VorgangSharedModule, - ], - declarations: [ - LoeschenAnfordernButtonContainerComponent, - LoeschenAnfordernButtonComponent, - EndgueltigLoeschenButtonContainerComponent, - EndgueltigLoeschenButtonComponent, - LoeschAnforderungZuruecknehmenButtonComponent, - LoeschAnforderungZuruecknehmenButtonContainerComponent - ], - exports: [ - LoeschenAnfordernButtonContainerComponent, - EndgueltigLoeschenButtonContainerComponent, - LoeschAnforderungZuruecknehmenButtonContainerComponent, - ] + imports: [ + CommonModule, + LoeschAnforderungSharedModule, + TechSharedModule, + UiModule, + VorgangSharedModule, + ], + declarations: [ + LoeschenAnfordernButtonContainerComponent, + LoeschenAnfordernButtonComponent, + EndgueltigLoeschenButtonContainerComponent, + EndgueltigLoeschenButtonComponent, + LoeschAnforderungZuruecknehmenButtonComponent, + LoeschAnforderungZuruecknehmenButtonContainerComponent, + ], + exports: [ + LoeschenAnfordernButtonContainerComponent, + EndgueltigLoeschenButtonContainerComponent, + LoeschAnforderungZuruecknehmenButtonContainerComponent, + ], }) -export class LoeschAnforderungModule { -} +export class LoeschAnforderungModule {} diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.html b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.html index 6aeda53617e945cc0dc793a2d3c5b7865b71656c..1722ce111727c5a2f335bd42e32bc7f348ae9379 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.html +++ b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.html @@ -1,4 +1,6 @@ <alfa-loeschen-anfordern-button - [showAsIconButton]="showAsIconButton" [loeschenAnfordernCommand]="loeschenAnfordernCommand$ | async" - (loeschenAnfordern)="loeschenAnfordern()"> -</alfa-loeschen-anfordern-button> \ No newline at end of file + [showAsIconButton]="showAsIconButton" + [loeschenAnfordernCommand]="loeschenAnfordernCommand$ | async" + (loeschenAnfordern)="loeschenAnfordern()" +> +</alfa-loeschen-anfordern-button> diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.spec.ts b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.spec.ts index c078e3a576002704f9fe51d30dfaace1b5ff4f1b..d7049346ad05c61e03e5721e1f7ae7cdc74b83ba 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.spec.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.spec.ts @@ -9,53 +9,51 @@ import { LoeschenAnfordernButtonContainerComponent } from './loeschen-anfordern- import { LoeschenAnfordernButtonComponent } from './loeschen-anfordern-button/loeschen-anfordern-button.component'; describe('LoeschenAnfordernButtonContainerComponent', () => { - let component: LoeschenAnfordernButtonContainerComponent; - let fixture: ComponentFixture<LoeschenAnfordernButtonContainerComponent>; - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - const service: Mock<LoeschAnforderungService> = mock(LoeschAnforderungService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - LoeschenAnfordernButtonContainerComponent, - HasLinkPipe, - MockComponent(LoeschenAnfordernButtonComponent) - ], - providers: [ - { - provide: LoeschAnforderungService, - useValue: service - } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(LoeschenAnfordernButtonContainerComponent); - component = fixture.componentInstance; - component.vorgang = vorgangWithEingang; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call service', () => { - component.ngOnInit(); - - expect(service.getLoeschenAnfordernCommand).toHaveBeenCalled(); - }) - }) - - describe('loeschenAnfordern', () => { - - it('should call service', () => { - component.loeschenAnfordern(); - - expect(service.loeschenAnfordern).toHaveBeenCalledWith(vorgangWithEingang); - }) - }) + let component: LoeschenAnfordernButtonContainerComponent; + let fixture: ComponentFixture<LoeschenAnfordernButtonContainerComponent>; + + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + const service: Mock<LoeschAnforderungService> = mock(LoeschAnforderungService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + LoeschenAnfordernButtonContainerComponent, + HasLinkPipe, + MockComponent(LoeschenAnfordernButtonComponent), + ], + providers: [ + { + provide: LoeschAnforderungService, + useValue: service, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(LoeschenAnfordernButtonContainerComponent); + component = fixture.componentInstance; + component.vorgang = vorgangWithEingang; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call service', () => { + component.ngOnInit(); + + expect(service.getLoeschenAnfordernCommand).toHaveBeenCalled(); + }); + }); + + describe('loeschenAnfordern', () => { + it('should call service', () => { + component.loeschenAnfordern(); + + expect(service.loeschenAnfordern).toHaveBeenCalledWith(vorgangWithEingang); + }); + }); }); diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.ts b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.ts index bdfb5982e1ffaaae583b65ef72f284a9ad4a1744..142e01c4a3c90319deb9488c4bbb83a4624b1385 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button-container.component.ts @@ -6,26 +6,27 @@ import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-cli import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-loeschen-anfordern-button-container', - templateUrl: './loeschen-anfordern-button-container.component.html', - styleUrls: ['./loeschen-anfordern-button-container.component.scss'], + selector: 'alfa-loeschen-anfordern-button-container', + templateUrl: './loeschen-anfordern-button-container.component.html', + styleUrls: ['./loeschen-anfordern-button-container.component.scss'], }) export class LoeschenAnfordernButtonContainerComponent implements OnInit { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean = false; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean = false; + loeschenAnfordernCommand$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - loeschenAnfordernCommand$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = VorgangWithEingangLinkRel; - readonly linkRel = VorgangWithEingangLinkRel; + constructor(private loeschAnforderungService: LoeschAnforderungService) {} - constructor(private loeschAnforderungService: LoeschAnforderungService) { } + ngOnInit(): void { + this.loeschenAnfordernCommand$ = this.loeschAnforderungService.getLoeschenAnfordernCommand(); + } - ngOnInit(): void { - this.loeschenAnfordernCommand$ = this.loeschAnforderungService.getLoeschenAnfordernCommand(); - } - - public loeschenAnfordern(): void { - this.loeschAnforderungService.loeschenAnfordern(this.vorgang); - } + public loeschenAnfordern(): void { + this.loeschAnforderungService.loeschenAnfordern(this.vorgang); + } } diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.html b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.html index 3837761af87a41f9d0695b0171783c8db59e4d16..1c1ad2cec3b8c94bddf3a0650554b670a342cddc 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.html +++ b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.html @@ -1,13 +1,19 @@ -<ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="loeschen-anfordern-button" - text="Löschen anfordern" - svgIcon="request_deletion" - [stateResource]="loeschenAnfordernCommand" - (clickEmitter)="loeschenAnfordern.emit()"> +<ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="loeschen-anfordern-button" + text="Löschen anfordern" + svgIcon="request_deletion" + [stateResource]="loeschenAnfordernCommand" + (clickEmitter)="loeschenAnfordern.emit()" +> </ozgcloud-stroked-button-with-spinner> -<ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="loeschen-anfordern-icon-button" - svgIcon="request_deletion" - toolTip="Löschen anfordern" - [stateResource]="loeschenAnfordernCommand" - (clickEmitter)="loeschenAnfordern.emit()"> -</ozgcloud-icon-button-with-spinner> \ No newline at end of file +<ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="loeschen-anfordern-icon-button" + svgIcon="request_deletion" + toolTip="Löschen anfordern" + [stateResource]="loeschenAnfordernCommand" + (clickEmitter)="loeschenAnfordern.emit()" +> +</ozgcloud-icon-button-with-spinner> diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.spec.ts b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.spec.ts index 8137b26b02a511a768dc36db773a58ba465e3c15..d5bee589de398245e9f25f29e3118565a5df0886 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.spec.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.spec.ts @@ -1,64 +1,65 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent } from 'ng-mocks'; import { LoeschenAnfordernButtonComponent } from './loeschen-anfordern-button.component'; describe('LoeschenAnfordernButtonComponent', () => { - let component: LoeschenAnfordernButtonComponent; - let fixture: ComponentFixture<LoeschenAnfordernButtonComponent>; + let component: LoeschenAnfordernButtonComponent; + let fixture: ComponentFixture<LoeschenAnfordernButtonComponent>; - const loeschenAnfordernButton: string = getDataTestIdOf('loeschen-anfordern-button'); - const loeschenAnfordernIconButton: string = getDataTestIdOf('loeschen-anfordern-icon-button'); + const loeschenAnfordernButton: string = getDataTestIdOf('loeschen-anfordern-button'); + const loeschenAnfordernIconButton: string = getDataTestIdOf('loeschen-anfordern-icon-button'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - LoeschenAnfordernButtonComponent, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + LoeschenAnfordernButtonComponent, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(LoeschenAnfordernButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(LoeschenAnfordernButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('show as icon button', () => { + describe('show as icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) + it('should hide button', () => { + notExistsAsHtmlElement(fixture, loeschenAnfordernButton); + }); - it('should hide button', () => { - notExistsAsHtmlElement(fixture, loeschenAnfordernButton); - }); + it('should show iconButton', () => { + existsAsHtmlElement(fixture, loeschenAnfordernIconButton); + }); + }); - it('should show iconButton', () => { - existsAsHtmlElement(fixture, loeschenAnfordernIconButton); - }); - }) + describe('show as button', () => { + beforeEach(() => { + component.showAsIconButton = false; + fixture.detectChanges(); + }); - describe('show as button', () => { + it('should show button', () => { + existsAsHtmlElement(fixture, loeschenAnfordernButton); + }); - beforeEach(() => { - component.showAsIconButton = false; - fixture.detectChanges(); - }) - - it('should show button', () => { - existsAsHtmlElement(fixture, loeschenAnfordernButton); - }); - - it('should hide iconButton visible', () => { - notExistsAsHtmlElement(fixture, loeschenAnfordernIconButton); - }); - }) + it('should hide iconButton visible', () => { + notExistsAsHtmlElement(fixture, loeschenAnfordernIconButton); + }); + }); }); diff --git a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.ts b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.ts index f066995bfa83d502c26cb67dbacee15e781e6b0b..681313df99fd8c3471332072a0832493a29a2583 100644 --- a/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.ts +++ b/alfa-client/libs/loesch-anforderung/src/lib/loeschen-anfordern-button-container/loeschen-anfordern-button/loeschen-anfordern-button.component.ts @@ -3,14 +3,13 @@ import { CommandResource } from '@alfa-client/command-shared'; import { StateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-loeschen-anfordern-button', - templateUrl: './loeschen-anfordern-button.component.html', - styleUrls: ['./loeschen-anfordern-button.component.scss'], + selector: 'alfa-loeschen-anfordern-button', + templateUrl: './loeschen-anfordern-button.component.html', + styleUrls: ['./loeschen-anfordern-button.component.scss'], }) export class LoeschenAnfordernButtonComponent { + @Input() showAsIconButton: boolean = false; + @Input() loeschenAnfordernCommand: StateResource<CommandResource>; - @Input() showAsIconButton: boolean = false; - @Input() loeschenAnfordernCommand: StateResource<CommandResource>; - - @Output() loeschenAnfordern: EventEmitter<void> = new EventEmitter<void>(); + @Output() loeschenAnfordern: EventEmitter<void> = new EventEmitter<void>(); } diff --git a/alfa-client/libs/loesch-anforderung/src/test-setup.ts b/alfa-client/libs/loesch-anforderung/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/loesch-anforderung/src/test-setup.ts +++ b/alfa-client/libs/loesch-anforderung/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/loesch-anforderung/tsconfig.json b/alfa-client/libs/loesch-anforderung/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/loesch-anforderung/tsconfig.json +++ b/alfa-client/libs/loesch-anforderung/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/loesch-anforderung/tsconfig.lib.json b/alfa-client/libs/loesch-anforderung/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/loesch-anforderung/tsconfig.lib.json +++ b/alfa-client/libs/loesch-anforderung/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/loesch-anforderung/tsconfig.spec.json b/alfa-client/libs/loesch-anforderung/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/loesch-anforderung/tsconfig.spec.json +++ b/alfa-client/libs/loesch-anforderung/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/navigation-shared/.eslintrc.json b/alfa-client/libs/navigation-shared/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/navigation-shared/.eslintrc.json +++ b/alfa-client/libs/navigation-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/navigation-shared/jest.config.ts b/alfa-client/libs/navigation-shared/jest.config.ts index 8f761dded1b7ac4f0321fa58733ff1e79831790b..95824e3e29ba528370562561cf0276f01edbcab9 100644 --- a/alfa-client/libs/navigation-shared/jest.config.ts +++ b/alfa-client/libs/navigation-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'navigation-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/navigation-shared', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'navigation-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/navigation-shared', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/navigation-shared/project.json b/alfa-client/libs/navigation-shared/project.json index 9fd0b88cdb33e327a863c91970d591c66ef966e4..ccb3386ff316ea7a66656085cc5158b096a34068 100644 --- a/alfa-client/libs/navigation-shared/project.json +++ b/alfa-client/libs/navigation-shared/project.json @@ -1,28 +1,28 @@ { - "name": "navigation-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/navigation-shared/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/navigation-shared"], - "options": { - "tsConfig": "libs/navigation-shared/tsconfig.spec.json", - "jestConfig": "libs/navigation-shared/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/navigation-shared/src/**/*.ts", - "libs/navigation-shared/src/**/*.html" - ] - } - } - }, - "tags": [] + "name": "navigation-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/navigation-shared/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/navigation-shared"], + "options": { + "tsConfig": "libs/navigation-shared/tsconfig.spec.json", + "jestConfig": "libs/navigation-shared/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/navigation-shared/src/**/*.ts", + "libs/navigation-shared/src/**/*.html" + ] + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/navigation-shared/src/index.ts b/alfa-client/libs/navigation-shared/src/index.ts index cddf4f5148c7b20bbf4931c26d5dc26ee9a3a047..edfca3f8df802099f2f141fb92cc9582975ccbff 100644 --- a/alfa-client/libs/navigation-shared/src/index.ts +++ b/alfa-client/libs/navigation-shared/src/index.ts @@ -29,4 +29,3 @@ export * from './lib/+state/navigation.selectors'; export * from './lib/navigation-shared.module'; export * from './lib/navigation.service'; export * from './lib/ozgcloud-url-serializer'; - diff --git a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.actions.ts b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.actions.ts index 849b432e5d8891f47b5edda90b2b8d0e1c593039..ec1c4b02042ab0f46af6ddc9ff930fc52537eef3 100644 --- a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.actions.ts +++ b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.actions.ts @@ -26,9 +26,10 @@ import { createAction, props } from '@ngrx/store'; import { RouteData } from './navigation.models'; export interface UpdateCurrentRouteDataProps { - routeData: RouteData + routeData: RouteData; } -export const updateCurrentRouteData: TypedActionCreatorWithProps<UpdateCurrentRouteDataProps> = createAction('[Navigation] Update current route data', props<UpdateCurrentRouteDataProps>()); +export const updateCurrentRouteData: TypedActionCreatorWithProps<UpdateCurrentRouteDataProps> = + createAction('[Navigation] Update current route data', props<UpdateCurrentRouteDataProps>()); -export const noOp: TypedActionCreator = createAction('[Navigation] No Operation'); \ No newline at end of file +export const noOp: TypedActionCreator = createAction('[Navigation] No Operation'); diff --git a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.effects.spec.ts b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.effects.spec.ts index 008147ff5d43af47239a0e42d7ac1373735e88ef..da6733754ba54d25dd759b29d6110c7326d99849 100644 --- a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.effects.spec.ts +++ b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.effects.spec.ts @@ -35,34 +35,31 @@ import * as NavigationUtil from '../navigation.util'; import * as NavigationActions from './navigation.actions'; describe('NavigationEffects', () => { - let actions: Observable<Action>; - let effects: NavigationEffects; + let actions: Observable<Action>; + let effects: NavigationEffects; - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - NavigationEffects, - provideMockActions(() => actions), - provideMockStore() - ] - }); + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [NavigationEffects, provideMockActions(() => actions), provideMockStore()], + }); - effects = TestBed.inject(NavigationEffects); - }); + effects = TestBed.inject(NavigationEffects); + }); - describe('navigate$', () => { + describe('navigate$', () => { + const action = routerNavigatedAction; - const action = routerNavigatedAction; + it('should dispatch updateCurrentRouteData action with data', () => { + jest.spyOn(NavigationUtil, 'buildRouteData').mockReturnValue(createRouteData()); + actions = hot('-a-|', { a: action }); - it('should dispatch updateCurrentRouteData action with data', () => { - jest.spyOn(NavigationUtil, 'buildRouteData').mockReturnValue(createRouteData()); - actions = hot('-a-|', { a: action }); + effects.navigateEnd$.subscribe(); - effects.navigateEnd$.subscribe(); + const expected = hot('-a-|', { + a: NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }), + }); - const expected = hot('-a-|', { a: NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }) }); - - expect(effects.navigateEnd$).toBeObservable(expected); - }) - }) -}); \ No newline at end of file + expect(effects.navigateEnd$).toBeObservable(expected); + }); + }); +}); diff --git a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.effects.ts b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.effects.ts index 7f02d47740023977368476c1ea553323d198c027..1770d61e3d3f991663737e9bf8d14e1aa0f07bb3 100644 --- a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.effects.ts +++ b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.effects.ts @@ -32,13 +32,14 @@ import * as NavigationActions from './navigation.actions'; @Injectable() export class NavigationEffects { + constructor(private readonly actions$: Actions) {} - constructor(private readonly actions$: Actions) { } - - navigateEnd$ = createEffect(() => - this.actions$.pipe( - ofType(routerNavigatedAction), - switchMap((action) => of(NavigationActions.updateCurrentRouteData({ routeData: buildRouteData(action) }))) - ) - ) -} \ No newline at end of file + navigateEnd$ = createEffect(() => + this.actions$.pipe( + ofType(routerNavigatedAction), + switchMap((action) => + of(NavigationActions.updateCurrentRouteData({ routeData: buildRouteData(action) })), + ), + ), + ); +} diff --git a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.facade.spec.ts b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.facade.spec.ts index 79b5c61cdcfa20ca82aec93b0995cfd3b8f445e7..f3e8fda47d810980da339e7c965056538519e469 100644 --- a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.facade.spec.ts +++ b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.facade.spec.ts @@ -30,42 +30,41 @@ import { RouteData } from './navigation.models'; import { currentRouteData } from './navigation.selectors'; describe('NavigationFacade', () => { - let facade: NavigationFacade; - let store: Mock<Store>; + let facade: NavigationFacade; + let store: Mock<Store>; - let selectionSubject: Subject<any>; + let selectionSubject: Subject<any>; - beforeEach(() => { - store = mock(Store); + beforeEach(() => { + store = mock(Store); - selectionSubject = new Subject(); + selectionSubject = new Subject(); - store.select.mockReturnValue(selectionSubject); - store.dispatch = jest.fn(); + store.select.mockReturnValue(selectionSubject); + store.dispatch = jest.fn(); - facade = new NavigationFacade(useFromMock(store)); - }) + facade = new NavigationFacade(useFromMock(store)); + }); - describe('getCurrentRouteData', () => { + describe('getCurrentRouteData', () => { + const routeData: RouteData = createRouteData(); - const routeData: RouteData = createRouteData(); + it('should call selector', (done) => { + facade.getCurrentRouteData().subscribe(() => { + expect(store.select).toHaveBeenCalledWith(currentRouteData); + done(); + }); - it('should call selector', (done) => { - facade.getCurrentRouteData().subscribe(() => { - expect(store.select).toHaveBeenCalledWith(currentRouteData); - done(); - }); + selectionSubject.next(routeData); + }); - selectionSubject.next(routeData); - }) + it('should return selected value', (done) => { + facade.getCurrentRouteData().subscribe((routeData) => { + expect(routeData).toBe(routeData); + done(); + }); - it('should return selected value', (done) => { - facade.getCurrentRouteData().subscribe(routeData => { - expect(routeData).toBe(routeData); - done(); - }); - - selectionSubject.next(routeData); - }); - }) -}) \ No newline at end of file + selectionSubject.next(routeData); + }); + }); +}); diff --git a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.facade.ts b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.facade.ts index 432f87fc2c0ce35f152e0fbb7f25d2c17afccc91..0a34cb3c4c79df193b388edf16df8ef897bfc1f3 100644 --- a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.facade.ts +++ b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.facade.ts @@ -29,10 +29,9 @@ import { currentRouteData } from './navigation.selectors'; @Injectable() export class NavigationFacade { + constructor(private readonly store: Store) {} - constructor(private readonly store: Store) { } - - public getCurrentRouteData(): Observable<RouteData> { - return this.store.select(currentRouteData); - } -} \ No newline at end of file + public getCurrentRouteData(): Observable<RouteData> { + return this.store.select(currentRouteData); + } +} diff --git a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.models.ts b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.models.ts index e3e42e17e7d523f5310ef449ad261d6c1b5afa67..2fbdbff2dd37921c89a606fe9df7cf2eea83cb9f 100644 --- a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.models.ts +++ b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.models.ts @@ -24,6 +24,6 @@ import { UrlSegment } from '@angular/router'; export interface RouteData { - urlSegments: UrlSegment[], - queryParameter: any -} \ No newline at end of file + urlSegments: UrlSegment[]; + queryParameter: any; +} diff --git a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.reducer.spec.ts b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.reducer.spec.ts index 0957abcdafae33f36a56c5de8877b14a5bcba309..61ec7967be73abb9cc45e970406ce23482591992 100644 --- a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.reducer.spec.ts +++ b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.reducer.spec.ts @@ -28,26 +28,24 @@ import { initialState, NavigationState, reducer } from './navigation.reducer'; import * as NavigationActions from './navigation.actions'; describe('Navigation Reducer', () => { + describe('on get updateRouteData action', () => { + it('should set route data', () => { + const routeData: RouteData = createRouteData(); + const action = NavigationActions.updateCurrentRouteData({ routeData }); - describe('on get updateRouteData action', () => { + const result: NavigationState = reducer(initialState, action); - it('should set route data', () => { - const routeData: RouteData = createRouteData(); - const action = NavigationActions.updateCurrentRouteData({ routeData }); + expect(result.currentRouteData).toBe(routeData); + }); - const result: NavigationState = reducer(initialState, action); + it('should return original state if route data not changed', () => { + const currentRouteData: RouteData = createRouteData(); + const currentState: NavigationState = { ...initialState, currentRouteData }; - expect(result.currentRouteData).toBe(routeData); - }) + const action = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); + const result: NavigationState = reducer(currentState, action); - it('should return original state if route data not changed', () => { - const currentRouteData: RouteData = createRouteData(); - const currentState: NavigationState = { ...initialState, currentRouteData }; - - const action = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); - const result: NavigationState = reducer(currentState, action); - - expect(result.currentRouteData).toStrictEqual(currentRouteData); - }) - }) -}); \ No newline at end of file + expect(result.currentRouteData).toStrictEqual(currentRouteData); + }); + }); +}); diff --git a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.reducer.ts b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.reducer.ts index 898a437beb065e22b21dfe9e2e7ac12e678f4308..c634846b66fdf7e4e9c54e6ad5290c08d629aea1 100644 --- a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.reducer.ts +++ b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.reducer.ts @@ -30,27 +30,29 @@ import * as NavigationActions from './navigation.actions'; export const NAVIGATION_FEATURE_KEY = 'NavigationState'; export interface NavigationPartialState { - readonly [NAVIGATION_FEATURE_KEY]: NavigationState; + readonly [NAVIGATION_FEATURE_KEY]: NavigationState; } export interface NavigationState { - currentRouteData: RouteData + currentRouteData: RouteData; } export const initialState: NavigationState = { - currentRouteData: null + currentRouteData: null, }; const navigationReducer = createReducer( - initialState, - on(NavigationActions.updateCurrentRouteData, (state: NavigationState, action) => (handleChangedRoute(state, action.routeData))) + initialState, + on(NavigationActions.updateCurrentRouteData, (state: NavigationState, action) => + handleChangedRoute(state, action.routeData), + ), ); function handleChangedRoute(state: NavigationState, newRouteData: RouteData): NavigationState { - const hasRouteChanged: boolean = !isEqual(state.currentRouteData, newRouteData); - return hasRouteChanged ? { ...state, currentRouteData: newRouteData } : state; + const hasRouteChanged: boolean = !isEqual(state.currentRouteData, newRouteData); + return hasRouteChanged ? { ...state, currentRouteData: newRouteData } : state; } export function reducer(state: NavigationState, action: Action) { - return navigationReducer(state, action); -} \ No newline at end of file + return navigationReducer(state, action); +} diff --git a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.selectors.spec.ts b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.selectors.spec.ts index a239acb360dd7e55f11f445d10f989f01b94ab1f..11ebc2348a1ad8cba1e4e803276d045df52a5b7b 100644 --- a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.selectors.spec.ts +++ b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.selectors.spec.ts @@ -28,21 +28,22 @@ import { initialState, NavigationPartialState } from './navigation.reducer'; import * as NavigationSelectors from './navigation.selectors'; describe('Navigation Selectors', () => { + let state: NavigationPartialState; - let state: NavigationPartialState; + const currentRouteData: RouteData = createRouteData(); - const currentRouteData: RouteData = createRouteData(); + beforeEach(() => { + state = { + NavigationState: { + ...initialState, + currentRouteData, + }, + }; + }); - beforeEach(() => { - state = { - NavigationState: { - ...initialState, - currentRouteData - } - } - }); - - it('should return currentRouteData', () => { - expect(NavigationSelectors.currentRouteData.projector(state.NavigationState)).toBe(currentRouteData); - }) -}) \ No newline at end of file + it('should return currentRouteData', () => { + expect(NavigationSelectors.currentRouteData.projector(state.NavigationState)).toBe( + currentRouteData, + ); + }); +}); diff --git a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.selectors.ts b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.selectors.ts index 9daceeed70035ee447d22fea369d3aab98fd98f3..2e935821c969638e01cfa2468317bede4bf8b46e 100644 --- a/alfa-client/libs/navigation-shared/src/lib/+state/navigation.selectors.ts +++ b/alfa-client/libs/navigation-shared/src/lib/+state/navigation.selectors.ts @@ -25,6 +25,10 @@ import { createFeatureSelector, createSelector, MemoizedSelector } from '@ngrx/s import { RouteData } from './navigation.models'; import { NavigationState, NAVIGATION_FEATURE_KEY } from './navigation.reducer'; -export const getNavigationState: MemoizedSelector<object, NavigationState> = createFeatureSelector<NavigationState>(NAVIGATION_FEATURE_KEY); +export const getNavigationState: MemoizedSelector<object, NavigationState> = + createFeatureSelector<NavigationState>(NAVIGATION_FEATURE_KEY); -export const currentRouteData: MemoizedSelector<NavigationState, RouteData> = createSelector(getNavigationState, (state: NavigationState) => state.currentRouteData); \ No newline at end of file +export const currentRouteData: MemoizedSelector<NavigationState, RouteData> = createSelector( + getNavigationState, + (state: NavigationState) => state.currentRouteData, +); diff --git a/alfa-client/libs/navigation-shared/src/lib/navigation-shared.module.ts b/alfa-client/libs/navigation-shared/src/lib/navigation-shared.module.ts index 23f71eeb9d87bb1684f9e06fa59d02f1a829a5a4..b6992eb76878006ef60763566baa1ef3cd313db9 100644 --- a/alfa-client/libs/navigation-shared/src/lib/navigation-shared.module.ts +++ b/alfa-client/libs/navigation-shared/src/lib/navigation-shared.module.ts @@ -32,12 +32,12 @@ import * as fromNavigation from './+state/navigation.reducer'; import { NavigationService } from './navigation.service'; @NgModule({ - imports: [ - CommonModule, - StoreModule.forFeature(fromNavigation.NAVIGATION_FEATURE_KEY, fromNavigation.reducer), - EffectsModule.forFeature([NavigationEffects]), - TechSharedModule - ], - providers: [NavigationFacade, NavigationService] + imports: [ + CommonModule, + StoreModule.forFeature(fromNavigation.NAVIGATION_FEATURE_KEY, fromNavigation.reducer), + EffectsModule.forFeature([NavigationEffects]), + TechSharedModule, + ], + providers: [NavigationFacade, NavigationService], }) -export class NavigationSharedModule { } +export class NavigationSharedModule {} diff --git a/alfa-client/libs/navigation-shared/src/lib/navigation.service.spec.ts b/alfa-client/libs/navigation-shared/src/lib/navigation.service.spec.ts index df68935be588e517fac876f8bf9a90289c2cb560..3e145df00f98d92bea93280ca06fedb67a4fae90 100644 --- a/alfa-client/libs/navigation-shared/src/lib/navigation.service.spec.ts +++ b/alfa-client/libs/navigation-shared/src/lib/navigation.service.spec.ts @@ -31,344 +31,355 @@ import { EMPTY_STRING } from '../../../tech-shared/src/lib/tech.util'; import { NavigationFacade } from './+state/navigation.facade'; import { NavigationService } from './navigation.service'; - describe('NavigationService', () => { - let service: NavigationService; - - let facade: Mock<NavigationFacade>; - let appService: Mock<AppService>; - let authService: Mock<OAuthService>; - - const router = { - ...mock(Router), - url: EMPTY_STRING, - events: of({}) - }; - - const activatedRouteParams: Params = {}; - const activatedRoute = { - ...mock(ActivatedRoute), - root: { - firstChild: { - params: of(activatedRouteParams) - } - }, - params: of(activatedRouteParams) - }; - - - beforeEach(() => { - facade = mock(NavigationFacade); - appService = mock(AppService); - - service = new NavigationService(useFromMock(<any>router), useFromMock(<any>activatedRoute), useFromMock(facade), useFromMock(authService)); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); - - describe('navigation', () => { - - describe('to vorganglist', () => { - - it('should navigate to all with empty url', () => { - router.url = NavigationService.ROOT_PATH; - - service.navigateToVorgangList(); - - expect(router.navigate).toHaveBeenCalledWith([NavigationService.ROOT_PATH, NavigationService.URL_PARAM_ALLE]); - }) - - it('should navigate to meine with url containing "meine"', () => { - router.url = NavigationService.MEINE_VORGAENGE_PATH;; - - service.navigateToVorgangList(); - - expect(router.navigate).toHaveBeenCalledWith([NavigationService.ROOT_PATH, NavigationService.URL_PARAM_MY_VORGAENGE]); - }) - - it('should navigate to all with url containing "alle"', () => { - router.url = NavigationService.ALLE_VORGAENGE_PATH; - - service.navigateToVorgangList(); - - expect(router.navigate).toHaveBeenCalledWith([NavigationService.ROOT_PATH, NavigationService.URL_PARAM_ALLE]); - }) - - it('should navigate to unassigned with url containing "unassigned"', () => { - router.url = NavigationService.UNASSIGNED_VORGAENGE_PATH; - - service.navigateToVorgangList(); - - expect(router.navigate).toHaveBeenCalledWith([NavigationService.ROOT_PATH, NavigationService.URL_PARAM_UNASSIGNED]); - }) - }) - - it('should navigate to vorgang with given url', () => { - const linkRel: ResourceUri = 'dummyUrl'; - - service.navigateToVorgang(linkRel); - - expect(router.navigate).toHaveBeenCalledWith([NavigationService.ROOT_PATH, NavigationService.URL_PARAM_MY_VORGANG, linkRel]); - }) - - it('should navigate with search string', () => { - router.url = NavigationService.ROOT_PATH; - const searchString: string = 'testSearchString'; - - service.search(searchString); - - expect(router.navigate).toHaveBeenCalledWith([NavigationService.ROOT_PATH, NavigationService.URL_PARAM_ALLE, NavigationService.URL_PARAM_SEARCH, encodeURIComponent(searchString)]); - }) - - it('should navigate to route by path segments', () => { - const pathSegments: string[] = ['meine', 'neu']; - - service.navigateByPathSegments(pathSegments); - - expect(router.navigate).toHaveBeenCalledWith(pathSegments) - }) - }) - - describe('isVorgangListPage', () => { - - it('should return true if params are empty', () => { - const isPage: boolean = NavigationService.isVorgangListPage({ }); + let service: NavigationService; + + let facade: Mock<NavigationFacade>; + let appService: Mock<AppService>; + let authService: Mock<OAuthService>; + + const router = { + ...mock(Router), + url: EMPTY_STRING, + events: of({}), + }; + + const activatedRouteParams: Params = {}; + const activatedRoute = { + ...mock(ActivatedRoute), + root: { + firstChild: { + params: of(activatedRouteParams), + }, + }, + params: of(activatedRouteParams), + }; + + beforeEach(() => { + facade = mock(NavigationFacade); + appService = mock(AppService); + + service = new NavigationService( + useFromMock(<any>router), + useFromMock(<any>activatedRoute), + useFromMock(facade), + useFromMock(authService), + ); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + describe('navigation', () => { + describe('to vorganglist', () => { + it('should navigate to all with empty url', () => { + router.url = NavigationService.ROOT_PATH; + + service.navigateToVorgangList(); + + expect(router.navigate).toHaveBeenCalledWith([ + NavigationService.ROOT_PATH, + NavigationService.URL_PARAM_ALLE, + ]); + }); + + it('should navigate to meine with url containing "meine"', () => { + router.url = NavigationService.MEINE_VORGAENGE_PATH; + + service.navigateToVorgangList(); + + expect(router.navigate).toHaveBeenCalledWith([ + NavigationService.ROOT_PATH, + NavigationService.URL_PARAM_MY_VORGAENGE, + ]); + }); + + it('should navigate to all with url containing "alle"', () => { + router.url = NavigationService.ALLE_VORGAENGE_PATH; - expect(isPage).toBeTruthy(); - }) + service.navigateToVorgangList(); + + expect(router.navigate).toHaveBeenCalledWith([ + NavigationService.ROOT_PATH, + NavigationService.URL_PARAM_ALLE, + ]); + }); + + it('should navigate to unassigned with url containing "unassigned"', () => { + router.url = NavigationService.UNASSIGNED_VORGAENGE_PATH; + + service.navigateToVorgangList(); - it('return true if params contains status only', () => { - const isPage: boolean = NavigationService.isVorgangListPage({ status: 'neu' }); + expect(router.navigate).toHaveBeenCalledWith([ + NavigationService.ROOT_PATH, + NavigationService.URL_PARAM_UNASSIGNED, + ]); + }); + }); - expect(isPage).toBeTruthy(); - }) + it('should navigate to vorgang with given url', () => { + const linkRel: ResourceUri = 'dummyUrl'; + + service.navigateToVorgang(linkRel); - it('return true if params contains search only', () => { - const isPage: boolean = NavigationService.isVorgangListPage({ search: 'SearchFor' }); + expect(router.navigate).toHaveBeenCalledWith([ + NavigationService.ROOT_PATH, + NavigationService.URL_PARAM_MY_VORGANG, + linkRel, + ]); + }); - expect(isPage).toBeTruthy(); - }) - }) + it('should navigate with search string', () => { + router.url = NavigationService.ROOT_PATH; + const searchString: string = 'testSearchString'; - describe('updateRouteData', () => { + service.search(searchString); + + expect(router.navigate).toHaveBeenCalledWith([ + NavigationService.ROOT_PATH, + NavigationService.URL_PARAM_ALLE, + NavigationService.URL_PARAM_SEARCH, + encodeURIComponent(searchString), + ]); + }); - beforeEach(() => { - service.updateRouteUrlSegment = jest.fn(); - service.updateRouteParameter = jest.fn(); - }) + it('should navigate to route by path segments', () => { + const pathSegments: string[] = ['meine', 'neu']; - it('should call updateRouteUrlSegment', () => { - service.updateRouteData(<any>activatedRoute); + service.navigateByPathSegments(pathSegments); - expect(service.updateRouteUrlSegment).toHaveBeenCalled(); - }) + expect(router.navigate).toHaveBeenCalledWith(pathSegments); + }); + }); - it('should call updateRouteParameter', () => { - service.updateRouteData(<any>activatedRoute); + describe('isVorgangListPage', () => { + it('should return true if params are empty', () => { + const isPage: boolean = NavigationService.isVorgangListPage({}); - expect(service.updateRouteParameter).toHaveBeenCalled(); - }) - }) + expect(isPage).toBeTruthy(); + }); - describe('updateRouteParameter', () => { + it('return true if params contains status only', () => { + const isPage: boolean = NavigationService.isVorgangListPage({ status: 'neu' }); - it('should check if route changed', () => { - service.isNewRoute = jest.fn(); + expect(isPage).toBeTruthy(); + }); - service.updateRouteParameter(<any>activatedRoute); + it('return true if params contains search only', () => { + const isPage: boolean = NavigationService.isVorgangListPage({ search: 'SearchFor' }); - expect(service.isNewRoute).toHaveBeenCalledWith(activatedRouteParams); - }) + expect(isPage).toBeTruthy(); + }); + }); - describe('on new route', () => { + describe('updateRouteData', () => { + beforeEach(() => { + service.updateRouteUrlSegment = jest.fn(); + service.updateRouteParameter = jest.fn(); + }); - beforeEach(() => { - service.isNewRoute = jest.fn(); - (<any>service).isNewRoute.mockReturnValue(true); - }) + it('should call updateRouteUrlSegment', () => { + service.updateRouteData(<any>activatedRoute); - it('should update route parameter', () => { - service.setRouteParameter = jest.fn(); + expect(service.updateRouteUrlSegment).toHaveBeenCalled(); + }); - service.updateRouteParameter(<any>activatedRoute); + it('should call updateRouteParameter', () => { + service.updateRouteData(<any>activatedRoute); - expect(service.setRouteParameter).toHaveBeenCalledWith(activatedRouteParams); - }) - }) + expect(service.updateRouteParameter).toHaveBeenCalled(); + }); + }); - describe('on same route', () => { + describe('updateRouteParameter', () => { + it('should check if route changed', () => { + service.isNewRoute = jest.fn(); - beforeEach(() => { - service.isNewRoute = jest.fn(); - (<any>service).isNewRoute.mockReturnValue(false); - }) + service.updateRouteParameter(<any>activatedRoute); - it('should NOT update route parameter if is new route', () => { - service.setRouteParameter = jest.fn(); + expect(service.isNewRoute).toHaveBeenCalledWith(activatedRouteParams); + }); - service.updateRouteParameter(<any>activatedRoute); + describe('on new route', () => { + beforeEach(() => { + service.isNewRoute = jest.fn(); + (<any>service).isNewRoute.mockReturnValue(true); + }); - expect(service.setRouteParameter).not.toHaveBeenCalled(); - }) - }) - }) + it('should update route parameter', () => { + service.setRouteParameter = jest.fn(); - describe('updateRouteUrlSegement', () => { + service.updateRouteParameter(<any>activatedRoute); - it('should update routeUrlSegement by route url', () => { - const urlSegement: UrlSegment[] = [<any>{ path: 'irgendein/pfad' }] - const route = { ...mock(ActivatedRoute), url: of(urlSegement) }; + expect(service.setRouteParameter).toHaveBeenCalledWith(activatedRouteParams); + }); + }); - service.updateRouteUrlSegment(<any>route); + describe('on same route', () => { + beforeEach(() => { + service.isNewRoute = jest.fn(); + (<any>service).isNewRoute.mockReturnValue(false); + }); - expect(service.routeUrlSegment$.value).toEqual(urlSegement); - }) - }) + it('should NOT update route parameter if is new route', () => { + service.setRouteParameter = jest.fn(); - describe('is postfach page', () => { + service.updateRouteParameter(<any>activatedRoute); - it('should return true if "postfach" exists in url', () => { - service.routeUrlSegment$.next(<any>[{ path: 'postfach' }]); + expect(service.setRouteParameter).not.toHaveBeenCalled(); + }); + }); + }); - const isPostfachPage: boolean = service.isPostfachPage(); + describe('updateRouteUrlSegement', () => { + it('should update routeUrlSegement by route url', () => { + const urlSegement: UrlSegment[] = [<any>{ path: 'irgendein/pfad' }]; + const route = { ...mock(ActivatedRoute), url: of(urlSegement) }; - expect(isPostfachPage).toBeTruthy(); - }) + service.updateRouteUrlSegment(<any>route); - it('should return false if "postfach" not exists in url', () => { - service.routeUrlSegment$.next(<any>[{ path: 'something else' }]); + expect(service.routeUrlSegment$.value).toEqual(urlSegement); + }); + }); - const isPostfachPage: boolean = service.isPostfachPage(); + describe('is postfach page', () => { + it('should return true if "postfach" exists in url', () => { + service.routeUrlSegment$.next(<any>[{ path: 'postfach' }]); - expect(isPostfachPage).toBeFalsy(); - }) + const isPostfachPage: boolean = service.isPostfachPage(); - it('should return false if routeUrl is empty', () => { - service.routeUrlSegment$.next(<any>[]); + expect(isPostfachPage).toBeTruthy(); + }); - const isPostfachPage: boolean = service.isPostfachPage(); + it('should return false if "postfach" not exists in url', () => { + service.routeUrlSegment$.next(<any>[{ path: 'something else' }]); - expect(isPostfachPage).toBeFalsy(); - }) - }) + const isPostfachPage: boolean = service.isPostfachPage(); - describe('navigate', () => { + expect(isPostfachPage).toBeFalsy(); + }); - const navigationRoute: string = 'dummyNavigationRoute'; + it('should return false if routeUrl is empty', () => { + service.routeUrlSegment$.next(<any>[]); - it('should call router with given navigationRoute', () => { - service.navigate(navigationRoute); + const isPostfachPage: boolean = service.isPostfachPage(); - expect(router.navigate).toHaveBeenCalledWith([navigationRoute]); - }) - }) + expect(isPostfachPage).toBeFalsy(); + }); + }); - describe('getCurrentRouteData', () => { + describe('navigate', () => { + const navigationRoute: string = 'dummyNavigationRoute'; - it('should call facade', () => { - service.getCurrentRouteData(); + it('should call router with given navigationRoute', () => { + service.navigate(navigationRoute); - expect(facade.getCurrentRouteData).toHaveBeenCalled(); - }) - }) + expect(router.navigate).toHaveBeenCalledWith([navigationRoute]); + }); + }); - describe('navigate by filter', () => { + describe('getCurrentRouteData', () => { + it('should call facade', () => { + service.getCurrentRouteData(); - it('should navigate', () => { - router.url = '/alle/neu'; + expect(facade.getCurrentRouteData).toHaveBeenCalled(); + }); + }); - service.navigateByFilter('meine'); + describe('navigate by filter', () => { + it('should navigate', () => { + router.url = '/alle/neu'; - expect(router.navigate).toHaveBeenCalledWith([EMPTY_STRING, 'meine', 'neu']); - }) - }) + service.navigateByFilter('meine'); - describe('getFilterPathSegment', () => { + expect(router.navigate).toHaveBeenCalledWith([EMPTY_STRING, 'meine', 'neu']); + }); + }); - it('should return alle with empty url', () => { - router.url = '/'; + describe('getFilterPathSegment', () => { + it('should return alle with empty url', () => { + router.url = '/'; - const pathSegment: string = service.getFilterPathSegment(); + const pathSegment: string = service.getFilterPathSegment(); - expect(pathSegment).toBe(NavigationService.URL_PARAM_ALLE); - }) + expect(pathSegment).toBe(NavigationService.URL_PARAM_ALLE); + }); - it('should return alle with non-filter url', () => { - router.url = '/vorgang/123'; + it('should return alle with non-filter url', () => { + router.url = '/vorgang/123'; - const pathSegment: string = service.getFilterPathSegment(); + const pathSegment: string = service.getFilterPathSegment(); - expect(pathSegment).toBe(NavigationService.URL_PARAM_ALLE); - }) + expect(pathSegment).toBe(NavigationService.URL_PARAM_ALLE); + }); - it('should return meine with url containing "meine"', () => { - router.url = '/meine/neu'; + it('should return meine with url containing "meine"', () => { + router.url = '/meine/neu'; - const pathSegment: string = service.getFilterPathSegment(); + const pathSegment: string = service.getFilterPathSegment(); - expect(pathSegment).toBe(NavigationService.URL_PARAM_MY_VORGAENGE); - }) + expect(pathSegment).toBe(NavigationService.URL_PARAM_MY_VORGAENGE); + }); - it('should return alle with url containing "alle', () => { - router.url = '/alle/neu'; + it('should return alle with url containing "alle', () => { + router.url = '/alle/neu'; - const pathSegment: string = service.getFilterPathSegment(); + const pathSegment: string = service.getFilterPathSegment(); - expect(pathSegment).toBe(NavigationService.URL_PARAM_ALLE); - }) + expect(pathSegment).toBe(NavigationService.URL_PARAM_ALLE); + }); - it('should return unassigned with url containing "unassigned"', () => { - router.url = '/unassigned/neu'; + it('should return unassigned with url containing "unassigned"', () => { + router.url = '/unassigned/neu'; - const pathSegment: string = service.getFilterPathSegment(); + const pathSegment: string = service.getFilterPathSegment(); - expect(pathSegment).toBe(NavigationService.URL_PARAM_UNASSIGNED); - }) - }) + expect(pathSegment).toBe(NavigationService.URL_PARAM_UNASSIGNED); + }); + }); - describe('isFilterPathSegment', () => { - it('should return true for "alle"', () => { - const result: boolean = service.isFilterPathSegment(NavigationService.URL_PARAM_ALLE); + describe('isFilterPathSegment', () => { + it('should return true for "alle"', () => { + const result: boolean = service.isFilterPathSegment(NavigationService.URL_PARAM_ALLE); - expect(result).toBeTruthy(); - }) + expect(result).toBeTruthy(); + }); - it('should return true for "meine"', () => { - const result: boolean = service.isFilterPathSegment(NavigationService.URL_PARAM_MY_VORGAENGE); + it('should return true for "meine"', () => { + const result: boolean = service.isFilterPathSegment(NavigationService.URL_PARAM_MY_VORGAENGE); - expect(result).toBeTruthy(); - }) + expect(result).toBeTruthy(); + }); - it('should return true for "unassigned"', () => { - const result: boolean = service.isFilterPathSegment(NavigationService.URL_PARAM_UNASSIGNED); + it('should return true for "unassigned"', () => { + const result: boolean = service.isFilterPathSegment(NavigationService.URL_PARAM_UNASSIGNED); - expect(result).toBeTruthy(); - }) + expect(result).toBeTruthy(); + }); - it('should return false for "vorgang"', () => { - const result: boolean = service.isFilterPathSegment(NavigationService.URL_PARAM_MY_VORGANG); + it('should return false for "vorgang"', () => { + const result: boolean = service.isFilterPathSegment(NavigationService.URL_PARAM_MY_VORGANG); - expect(result).toBeFalsy(); - }) - }) + expect(result).toBeFalsy(); + }); + }); - describe('isNotRootPath', () => { - it('should return true for non-root paths', () => { - router.url = '/alle'; + describe('isNotRootPath', () => { + it('should return true for non-root paths', () => { + router.url = '/alle'; - const result: boolean = service.isNotRootPath(); + const result: boolean = service.isNotRootPath(); - expect(result).toBeTruthy(); - }) + expect(result).toBeTruthy(); + }); - it('should return false for root path', () => { - router.url = '/'; + it('should return false for root path', () => { + router.url = '/'; - const result: boolean = service.isNotRootPath(); + const result: boolean = service.isNotRootPath(); - expect(result).toBeFalsy(); - }) - }) -}) \ No newline at end of file + expect(result).toBeFalsy(); + }); + }); +}); diff --git a/alfa-client/libs/navigation-shared/src/lib/navigation.service.ts b/alfa-client/libs/navigation-shared/src/lib/navigation.service.ts index faa5efe0ea44a274a4f0dff3b47b01f1b6ffcaae..f026dc54b49dd0be9457230bfdfdadbb9978112e 100644 --- a/alfa-client/libs/navigation-shared/src/lib/navigation.service.ts +++ b/alfa-client/libs/navigation-shared/src/lib/navigation.service.ts @@ -22,8 +22,21 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Injectable } from '@angular/core'; -import { ActivatedRoute, NavigationEnd, Params, PRIMARY_OUTLET, Router, UrlSegment } from '@angular/router'; -import { decodeUrlFromEmbedding, isEmptyObject, isNotNil, isNotNull, isNotUndefined } from '@alfa-client/tech-shared'; +import { + ActivatedRoute, + NavigationEnd, + Params, + PRIMARY_OUTLET, + Router, + UrlSegment, +} from '@angular/router'; +import { + decodeUrlFromEmbedding, + isEmptyObject, + isNotNil, + isNotNull, + isNotUndefined, +} from '@alfa-client/tech-shared'; import { ResourceUri } from '@ngxp/rest'; import { OAuthService } from 'angular-oauth2-oidc'; import { has, isNil, isUndefined } from 'lodash-es'; @@ -35,188 +48,216 @@ import { RouteData } from './+state/navigation.models'; @Injectable({ providedIn: 'root' }) export class NavigationService { - - //@deprecated use NavigationFacade#getCurrentRouteData; - readonly routeUrlSegment$: BehaviorSubject<UrlSegment[]> = new BehaviorSubject<UrlSegment[]>([]); - private readonly routeParameter$: BehaviorSubject<Params> = new BehaviorSubject<Params>({}); - // - - public static readonly URL_PARAM_MY_VORGAENGE: string = 'meine'; - public static readonly URL_PARAM_MY_VORGANG: string = 'vorgang'; - public static readonly URL_PARAM_ALLE: string = 'alle'; - public static readonly URL_PARAM_SEARCH: string = 'search'; - public static readonly URL_PARAM_UNASSIGNED: string = 'unassigned'; - - public readonly VORGANG_WITH_EINGANG_URL: string = 'vorgangWithEingangUrl'; - - static readonly ROOT_PATH: string = '/'; - static readonly VORGANG_BASE_PATH: string = NavigationService.ROOT_PATH + NavigationService.URL_PARAM_MY_VORGANG + '/'; - public static readonly MEINE_VORGAENGE_PATH: string = NavigationService.ROOT_PATH + NavigationService.URL_PARAM_MY_VORGAENGE + '/'; - public static readonly ALLE_VORGAENGE_PATH: string = NavigationService.ROOT_PATH + NavigationService.URL_PARAM_ALLE + '/'; - public static readonly UNASSIGNED_VORGAENGE_PATH: string = NavigationService.ROOT_PATH + NavigationService.URL_PARAM_UNASSIGNED + '/'; - - private routeSubscription: Subscription; - private urlSubscription: Subscription; - - constructor( - private router: Router, - private activatedRoute: ActivatedRoute, - private facade: NavigationFacade, - private authService: OAuthService - ) { - this.init(); - } - - private init(): void { - this.prefillRouterData(); - - this.subscribeToRouterEvents(); - } - - private prefillRouterData(): void { - this.getLastFirstChild(this.activatedRoute.root).params.subscribe((params: Params) => this.routeParameter$.next(params)); - } - - private subscribeToRouterEvents(): void { - this.router.events.pipe( - filter(() => isNotNull(this.authService.getAccessToken())), - filter(event => event instanceof NavigationEnd), - map(() => this.getLastFirstChild(this.activatedRoute)), - filter(route => route.outlet === PRIMARY_OUTLET)) - .subscribe(route => this.updateRouteData(route)); - } - - private getLastFirstChild(route: ActivatedRoute): ActivatedRoute { - while (route.firstChild) route = route.firstChild; - return route; - } - - updateRouteData(route: ActivatedRoute): void { - if (isNotUndefined(this.urlSubscription)) this.urlSubscription.unsubscribe(); - this.updateRouteUrlSegment(route); - if (isNotUndefined(this.routeSubscription)) this.routeSubscription.unsubscribe(); - this.updateRouteParameter(route); - } - - updateRouteUrlSegment(route: ActivatedRoute): void { - this.urlSubscription = route.url.subscribe((currentUrlSegment: UrlSegment[]) => this.routeUrlSegment$.next(currentUrlSegment)); - } - - updateRouteParameter(route: ActivatedRoute): void { - this.routeSubscription = route.params.subscribe((params: Params) => { - if (this.isNewRoute(params)) { - this.setRouteParameter(params); - } - }); - } - - isNewRoute(newParams: Params): boolean { - return newParams != this.routeParameter$.value; - } - - setRouteParameter(params: Params): void { - this.routeParameter$.next(params); - } - - public urlChanged(): Observable<Params> { - return this.routeParameter$.asObservable(); - } - - public getParam(paramName: string): string { - return this.routeParameter$.value[paramName]; - } - - public getDecodedParam(paramName: string): string { - if (this.isParamPresent(paramName)) return undefined; - return NavigationService.decodeParamUrl(this.routeParameter$.value[paramName]); - } - - static decodeParamUrl(encodedUrl: string): string { - let decodeUrl: string; - - try { - decodeUrl = decodeUrlFromEmbedding(encodedUrl); - } catch (e) { - console.warn('cannot decode url param', e); - } - return decodeUrl; - } - - public getDecodedUriParam(paramName: string): string { - if (this.isParamPresent(paramName)) return undefined; - return decodeURI(this.routeParameter$.value[paramName]); - } - - private isParamPresent(paramName: string): boolean { - return isEmptyObject(this.routeParameter$.value) || isUndefined(this.routeParameter$.value[paramName]); - } - - static isVorgangListPage(params: Params): boolean { - return isEmptyObject(params) || has(params, 'status') || has(params, this.URL_PARAM_SEARCH); - } - - static isVorgangDetailPage(params: Params, paramName: string): boolean { - return Object.keys(params).length === 1 && isNotUndefined(params[paramName]); - } - - static isSearch(params: Params): boolean { - return Object.keys(params).length === 1 && !isNil(params[NavigationService.URL_PARAM_SEARCH]); - } - - public navigateRelativeTo(relativePath: string, relativeTo: ActivatedRoute): void { - this.router.navigate([relativePath], { relativeTo }); - } - - public search(searchString: string): void { - this.router.navigate([NavigationService.ROOT_PATH, this.getFilterPathSegment(), NavigationService.URL_PARAM_SEARCH, encodeURIComponent(searchString)]); - } - - public navigateToVorgangList(): void { - this.router.navigate([NavigationService.ROOT_PATH, this.getFilterPathSegment()]); - } - - getFilterPathSegment(): string { - const firstPathSegment: string = this.router.url.split('/')[1]; - return this.isFilterPathSegment(firstPathSegment) ? firstPathSegment : NavigationService.URL_PARAM_ALLE; - } - - isFilterPathSegment(pathSegment: string): boolean { - return pathSegment === NavigationService.URL_PARAM_ALLE || pathSegment === NavigationService.URL_PARAM_MY_VORGAENGE - || pathSegment === NavigationService.URL_PARAM_UNASSIGNED; - } - - navigate(navigationRoute: string): void { - this.router.navigate([navigationRoute]); - } - - public navigateToVorgang(linkUri: ResourceUri): void { - this.router.navigate([NavigationService.ROOT_PATH, NavigationService.URL_PARAM_MY_VORGANG, linkUri]); - } - - public isPostfachPage(): boolean { - const postfachUrlSegement: UrlSegment = this.routeUrlSegment$.value.find(urlSegment => urlSegment.path.includes('postfach')); - return isNotNil(postfachUrlSegement); - } - - public getCurrentRouteData(): Observable<RouteData> { - return this.facade.getCurrentRouteData(); - } - - public navigateByPathSegments(pathSegments: string[]): void { - this.router.navigate(pathSegments); - } - - public navigateByFilter(filter: string): void { - let urlSegments: string[] = this.getUrlSegments(); - urlSegments[1] = filter; - this.router.navigate(urlSegments); - } - - private getUrlSegments(): string[] { - return this.router.url.split('/'); - } - - isNotRootPath(): boolean { - return this.router.url !== '/'; - } -} \ No newline at end of file + //@deprecated use NavigationFacade#getCurrentRouteData; + readonly routeUrlSegment$: BehaviorSubject<UrlSegment[]> = new BehaviorSubject<UrlSegment[]>([]); + private readonly routeParameter$: BehaviorSubject<Params> = new BehaviorSubject<Params>({}); + // + + public static readonly URL_PARAM_MY_VORGAENGE: string = 'meine'; + public static readonly URL_PARAM_MY_VORGANG: string = 'vorgang'; + public static readonly URL_PARAM_ALLE: string = 'alle'; + public static readonly URL_PARAM_SEARCH: string = 'search'; + public static readonly URL_PARAM_UNASSIGNED: string = 'unassigned'; + + public readonly VORGANG_WITH_EINGANG_URL: string = 'vorgangWithEingangUrl'; + + static readonly ROOT_PATH: string = '/'; + static readonly VORGANG_BASE_PATH: string = + NavigationService.ROOT_PATH + NavigationService.URL_PARAM_MY_VORGANG + '/'; + public static readonly MEINE_VORGAENGE_PATH: string = + NavigationService.ROOT_PATH + NavigationService.URL_PARAM_MY_VORGAENGE + '/'; + public static readonly ALLE_VORGAENGE_PATH: string = + NavigationService.ROOT_PATH + NavigationService.URL_PARAM_ALLE + '/'; + public static readonly UNASSIGNED_VORGAENGE_PATH: string = + NavigationService.ROOT_PATH + NavigationService.URL_PARAM_UNASSIGNED + '/'; + + private routeSubscription: Subscription; + private urlSubscription: Subscription; + + constructor( + private router: Router, + private activatedRoute: ActivatedRoute, + private facade: NavigationFacade, + private authService: OAuthService, + ) { + this.init(); + } + + private init(): void { + this.prefillRouterData(); + + this.subscribeToRouterEvents(); + } + + private prefillRouterData(): void { + this.getLastFirstChild(this.activatedRoute.root).params.subscribe((params: Params) => + this.routeParameter$.next(params), + ); + } + + private subscribeToRouterEvents(): void { + this.router.events + .pipe( + filter(() => isNotNull(this.authService.getAccessToken())), + filter((event) => event instanceof NavigationEnd), + map(() => this.getLastFirstChild(this.activatedRoute)), + filter((route) => route.outlet === PRIMARY_OUTLET), + ) + .subscribe((route) => this.updateRouteData(route)); + } + + private getLastFirstChild(route: ActivatedRoute): ActivatedRoute { + while (route.firstChild) route = route.firstChild; + return route; + } + + updateRouteData(route: ActivatedRoute): void { + if (isNotUndefined(this.urlSubscription)) this.urlSubscription.unsubscribe(); + this.updateRouteUrlSegment(route); + if (isNotUndefined(this.routeSubscription)) this.routeSubscription.unsubscribe(); + this.updateRouteParameter(route); + } + + updateRouteUrlSegment(route: ActivatedRoute): void { + this.urlSubscription = route.url.subscribe((currentUrlSegment: UrlSegment[]) => + this.routeUrlSegment$.next(currentUrlSegment), + ); + } + + updateRouteParameter(route: ActivatedRoute): void { + this.routeSubscription = route.params.subscribe((params: Params) => { + if (this.isNewRoute(params)) { + this.setRouteParameter(params); + } + }); + } + + isNewRoute(newParams: Params): boolean { + return newParams != this.routeParameter$.value; + } + + setRouteParameter(params: Params): void { + this.routeParameter$.next(params); + } + + public urlChanged(): Observable<Params> { + return this.routeParameter$.asObservable(); + } + + public getParam(paramName: string): string { + return this.routeParameter$.value[paramName]; + } + + public getDecodedParam(paramName: string): string { + if (this.isParamPresent(paramName)) return undefined; + return NavigationService.decodeParamUrl(this.routeParameter$.value[paramName]); + } + + static decodeParamUrl(encodedUrl: string): string { + let decodeUrl: string; + + try { + decodeUrl = decodeUrlFromEmbedding(encodedUrl); + } catch (e) { + console.warn('cannot decode url param', e); + } + return decodeUrl; + } + + public getDecodedUriParam(paramName: string): string { + if (this.isParamPresent(paramName)) return undefined; + return decodeURI(this.routeParameter$.value[paramName]); + } + + private isParamPresent(paramName: string): boolean { + return ( + isEmptyObject(this.routeParameter$.value) || + isUndefined(this.routeParameter$.value[paramName]) + ); + } + + static isVorgangListPage(params: Params): boolean { + return isEmptyObject(params) || has(params, 'status') || has(params, this.URL_PARAM_SEARCH); + } + + static isVorgangDetailPage(params: Params, paramName: string): boolean { + return Object.keys(params).length === 1 && isNotUndefined(params[paramName]); + } + + static isSearch(params: Params): boolean { + return Object.keys(params).length === 1 && !isNil(params[NavigationService.URL_PARAM_SEARCH]); + } + + public navigateRelativeTo(relativePath: string, relativeTo: ActivatedRoute): void { + this.router.navigate([relativePath], { relativeTo }); + } + + public search(searchString: string): void { + this.router.navigate([ + NavigationService.ROOT_PATH, + this.getFilterPathSegment(), + NavigationService.URL_PARAM_SEARCH, + encodeURIComponent(searchString), + ]); + } + + public navigateToVorgangList(): void { + this.router.navigate([NavigationService.ROOT_PATH, this.getFilterPathSegment()]); + } + + getFilterPathSegment(): string { + const firstPathSegment: string = this.router.url.split('/')[1]; + return this.isFilterPathSegment(firstPathSegment) ? firstPathSegment : ( + NavigationService.URL_PARAM_ALLE + ); + } + + isFilterPathSegment(pathSegment: string): boolean { + return ( + pathSegment === NavigationService.URL_PARAM_ALLE || + pathSegment === NavigationService.URL_PARAM_MY_VORGAENGE || + pathSegment === NavigationService.URL_PARAM_UNASSIGNED + ); + } + + navigate(navigationRoute: string): void { + this.router.navigate([navigationRoute]); + } + + public navigateToVorgang(linkUri: ResourceUri): void { + this.router.navigate([ + NavigationService.ROOT_PATH, + NavigationService.URL_PARAM_MY_VORGANG, + linkUri, + ]); + } + + public isPostfachPage(): boolean { + const postfachUrlSegement: UrlSegment = this.routeUrlSegment$.value.find((urlSegment) => + urlSegment.path.includes('postfach'), + ); + return isNotNil(postfachUrlSegement); + } + + public getCurrentRouteData(): Observable<RouteData> { + return this.facade.getCurrentRouteData(); + } + + public navigateByPathSegments(pathSegments: string[]): void { + this.router.navigate(pathSegments); + } + + public navigateByFilter(filter: string): void { + let urlSegments: string[] = this.getUrlSegments(); + urlSegments[1] = filter; + this.router.navigate(urlSegments); + } + + private getUrlSegments(): string[] { + return this.router.url.split('/'); + } + + isNotRootPath(): boolean { + return this.router.url !== '/'; + } +} diff --git a/alfa-client/libs/navigation-shared/src/lib/navigation.util.spec.ts b/alfa-client/libs/navigation-shared/src/lib/navigation.util.spec.ts index ce1cb3793fa4124daefb1d58d80b9d8b39c5f082..6e62af45f4cd3a3d011e987a7c62f03863178679 100644 --- a/alfa-client/libs/navigation-shared/src/lib/navigation.util.spec.ts +++ b/alfa-client/libs/navigation-shared/src/lib/navigation.util.spec.ts @@ -1,9 +1,9 @@ import { revertDoubleEncodingOfPercentageSign } from './navigation.util'; describe('decodeEncodedPercentageSign', () => { - it('should remove %25 by %', () => { - const text: string = revertDoubleEncodingOfPercentageSign('Test%25text'); + it('should remove %25 by %', () => { + const text: string = revertDoubleEncodingOfPercentageSign('Test%25text'); - expect(text).toBe('Test%text'); - }) -}) \ No newline at end of file + expect(text).toBe('Test%text'); + }); +}); diff --git a/alfa-client/libs/navigation-shared/src/lib/navigation.util.ts b/alfa-client/libs/navigation-shared/src/lib/navigation.util.ts index e9b81aed3ba59028d369cd69e2e7e8dcb721ef33..2d1cb125f2b0fcac479748ba9f498c877e1f23b2 100644 --- a/alfa-client/libs/navigation-shared/src/lib/navigation.util.ts +++ b/alfa-client/libs/navigation-shared/src/lib/navigation.util.ts @@ -25,16 +25,16 @@ import { isNotUndefined } from '@alfa-client/tech-shared'; import { RouteData } from './+state/navigation.models'; export function buildRouteData(action: any): RouteData { - const root = action.payload.routerState.root; - const lastFirst = getLastFirstChild(root); - return { queryParameter: lastFirst.params, urlSegments: lastFirst.url }; + const root = action.payload.routerState.root; + const lastFirst = getLastFirstChild(root); + return { queryParameter: lastFirst.params, urlSegments: lastFirst.url }; } function getLastFirstChild(route: any) { - while (isNotUndefined(route.firstChild)) route = route.firstChild; - return route; + while (isNotUndefined(route.firstChild)) route = route.firstChild; + return route; } export function revertDoubleEncodingOfPercentageSign(text: string): string { - return text.replace(/%25/g, '%'); -} \ No newline at end of file + return text.replace(/%25/g, '%'); +} diff --git a/alfa-client/libs/navigation-shared/src/lib/ozgcloud-url-serializer.spec.ts b/alfa-client/libs/navigation-shared/src/lib/ozgcloud-url-serializer.spec.ts index 21048e5c360920e7c08868d78aa9659e943cff53..aeb15237390d84442aac4171daa64d311a4f7518 100644 --- a/alfa-client/libs/navigation-shared/src/lib/ozgcloud-url-serializer.spec.ts +++ b/alfa-client/libs/navigation-shared/src/lib/ozgcloud-url-serializer.spec.ts @@ -1,5 +1,5 @@ import { Router, UrlTree } from '@angular/router'; -import { RouterTestingModule } from "@angular/router/testing"; +import { RouterTestingModule } from '@angular/router/testing'; import { faker } from '@faker-js/faker'; import { OzgCloudUrlSerializer } from './ozgcloud-url-serializer'; @@ -7,50 +7,51 @@ import { TestBed } from '@angular/core/testing'; import * as NavigationUtil from './navigation.util'; describe('OzgCloudUrlSerializer', () => { + let serializer: OzgCloudUrlSerializer; + let router: Router; - let serializer: OzgCloudUrlSerializer; - let router: Router; + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [RouterTestingModule], + }); - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [RouterTestingModule] - }); + router = TestBed.inject(Router); + serializer = new OzgCloudUrlSerializer(); + }); - router = TestBed.inject(Router); - serializer = new OzgCloudUrlSerializer(); - }) + it('should be created', () => { + expect(serializer).toBeTruthy(); + }); - it('should be created', () => { - expect(serializer).toBeTruthy(); - }); + describe('parse', () => { + it('should return URLTree', () => { + const url: string = faker.internet.url(); - describe('parse', () => { - it('should return URLTree', () => { - const url: string = faker.internet.url(); + const urlTree: UrlTree = serializer.parse(url); - const urlTree: UrlTree = serializer.parse(url); + expect(urlTree).toBeInstanceOf(UrlTree); + }); + }); - expect(urlTree).toBeInstanceOf(UrlTree); - }) - }) + describe('serialize', () => { + it('should call revertDoubleEncodingOfPercentageSign', () => { + const spy: jest.SpyInstance<string, [text: string]> = jest.spyOn( + NavigationUtil, + 'revertDoubleEncodingOfPercentageSign', + ); + const urlTree: UrlTree = router.createUrlTree(['/']); - describe('serialize', () => { - it('should call revertDoubleEncodingOfPercentageSign', () => { - const spy: jest.SpyInstance<string, [text: string]> = jest.spyOn(NavigationUtil, 'revertDoubleEncodingOfPercentageSign'); - const urlTree: UrlTree = router.createUrlTree(['/']); + serializer.serialize(urlTree); - serializer.serialize(urlTree); + expect(spy).toHaveBeenCalled(); + }); - expect(spy).toHaveBeenCalled(); - }) + it('should ensure percentage sign is not double encoded', () => { + const urlTree: UrlTree = router.createUrlTree(['/', '%25']); - it('should ensure percentage sign is not double encoded', () => { - const urlTree: UrlTree = router.createUrlTree(['/', '%25']); + const path: string = serializer.serialize(urlTree); - const path: string = serializer.serialize(urlTree); - - expect(path).toBe('/%25'); - }) - }) - -}) \ No newline at end of file + expect(path).toBe('/%25'); + }); + }); +}); diff --git a/alfa-client/libs/navigation-shared/src/lib/ozgcloud-url-serializer.ts b/alfa-client/libs/navigation-shared/src/lib/ozgcloud-url-serializer.ts index 310708272ca82a524bb39bf6daf49b8d506171b0..4939cfddcb6ce5a2240ef446fecd9e6a2f4c4e8c 100644 --- a/alfa-client/libs/navigation-shared/src/lib/ozgcloud-url-serializer.ts +++ b/alfa-client/libs/navigation-shared/src/lib/ozgcloud-url-serializer.ts @@ -2,13 +2,12 @@ import { DefaultUrlSerializer, UrlTree } from '@angular/router'; import { revertDoubleEncodingOfPercentageSign } from './navigation.util'; export class OzgCloudUrlSerializer extends DefaultUrlSerializer { - parse(url: string) : UrlTree { - return super.parse(url); - } + parse(url: string): UrlTree { + return super.parse(url); + } - serialize(tree: UrlTree): string { - const path: string = super.serialize(tree); - return revertDoubleEncodingOfPercentageSign(path); - } + serialize(tree: UrlTree): string { + const path: string = super.serialize(tree); + return revertDoubleEncodingOfPercentageSign(path); + } } - diff --git a/alfa-client/libs/navigation-shared/test/navigation-test-factory.ts b/alfa-client/libs/navigation-shared/test/navigation-test-factory.ts index 77a64e50e84f1fe2dfbfdd1fa823b40eeb5faa4a..8b78b4ffbbc907d2fee92e807f80d268108ed021 100644 --- a/alfa-client/libs/navigation-shared/test/navigation-test-factory.ts +++ b/alfa-client/libs/navigation-shared/test/navigation-test-factory.ts @@ -24,5 +24,5 @@ import { RouteData } from '../src/lib/+state/navigation.models'; export function createRouteData(): RouteData { - return { queryParameter: { }, urlSegments: [] }; + return { queryParameter: {}, urlSegments: [] }; } diff --git a/alfa-client/libs/navigation-shared/tsconfig.json b/alfa-client/libs/navigation-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/navigation-shared/tsconfig.json +++ b/alfa-client/libs/navigation-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/navigation-shared/tsconfig.lib.json b/alfa-client/libs/navigation-shared/tsconfig.lib.json index ead8f8bdba5aca4d713f65c9003b06695a69c2f4..2e762bd23944def694724f2ce7c0ea2d922ae1e5 100644 --- a/alfa-client/libs/navigation-shared/tsconfig.lib.json +++ b/alfa-client/libs/navigation-shared/tsconfig.lib.json @@ -1,17 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [] - }, - "exclude": [ - "src/test-setup.ts", - "**/*.spec.ts", - "**/*.test.ts", - "jest.config.ts" - ], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "**/*.test.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/navigation-shared/tsconfig.spec.json b/alfa-client/libs/navigation-shared/tsconfig.spec.json index 4950ae2f7859509b300543bff1c1e5ce4b1e2d5c..c3cb17f784fa2f7b9a4b0e7c9b03663500f4ee3d 100644 --- a/alfa-client/libs/navigation-shared/tsconfig.spec.json +++ b/alfa-client/libs/navigation-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/navigation/.eslintrc.json b/alfa-client/libs/navigation/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/navigation/.eslintrc.json +++ b/alfa-client/libs/navigation/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/navigation/jest.config.ts b/alfa-client/libs/navigation/jest.config.ts index c3d300f08bd97f6d39e55f9cb7374132b9467e3c..266cd0593782b566074f5d595352e9153594dd18 100644 --- a/alfa-client/libs/navigation/jest.config.ts +++ b/alfa-client/libs/navigation/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'navigation', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/navigation', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'navigation', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/navigation', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/navigation/project.json b/alfa-client/libs/navigation/project.json index 99661a0203d27317587b0ef99db3a8bb9f914d2c..c67de4304d3ef568513956161478d9c548c1390b 100644 --- a/alfa-client/libs/navigation/project.json +++ b/alfa-client/libs/navigation/project.json @@ -1,34 +1,31 @@ { - "name": "navigation", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/navigation/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/navigation/src/**/*.ts", - "libs/navigation/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/navigation/tsconfig.spec.json", - "jestConfig": "libs/navigation/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/navigation"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "navigation", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/navigation/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/navigation/src/**/*.ts", "libs/navigation/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/navigation/tsconfig.spec.json", + "jestConfig": "libs/navigation/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/navigation"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/navigation/src/lib/build-info/build-info.component.html b/alfa-client/libs/navigation/src/lib/build-info/build-info.component.html index 89ae52d2d1a9f841c3917ebb080a4a50c37157ae..3befc6c17ff6c1c67843bb0969acfb0ed2ce4ef3 100644 --- a/alfa-client/libs/navigation/src/lib/build-info/build-info.component.html +++ b/alfa-client/libs/navigation/src/lib/build-info/build-info.component.html @@ -24,10 +24,12 @@ --> <p class="version"> - <span data-test-id="version">v{{ version }}</span> - <ng-container *ngIf="isNotProduction"> - <span data-test-id="build-time">{{ buildDate }}</span> - <span data-test-id="build-time">{{ buildTime }}</span> - </ng-container> + <span data-test-id="version">v{{ version }}</span> + <ng-container *ngIf="isNotProduction"> + <span data-test-id="build-time">{{ buildDate }}</span> + <span data-test-id="build-time">{{ buildTime }}</span> + </ng-container> +</p> +<p *ngIf="isNotProduction" data-test-id="not-production-text" class="test-environment"> + Achtung Testumgebung </p> -<p *ngIf="isNotProduction" data-test-id="not-production-text" class="test-environment">Achtung Testumgebung</p> \ No newline at end of file diff --git a/alfa-client/libs/navigation/src/lib/build-info/build-info.component.scss b/alfa-client/libs/navigation/src/lib/build-info/build-info.component.scss index 687bf9dc28611fe0de820edacad151dcd45114db..ec3f82e9c13c393371836db8fecfca6ecc6467d5 100644 --- a/alfa-client/libs/navigation/src/lib/build-info/build-info.component.scss +++ b/alfa-client/libs/navigation/src/lib/build-info/build-info.component.scss @@ -24,42 +24,42 @@ @import 'variables'; :host { - display: flex; - flex-direction: row; - justify-content: space-between; - width: 100vh; - position: absolute; - right: 0; - bottom: 0; - padding: 4px 8px; - transform: rotate(-90deg) translate(100%, 0); - transform-origin: right bottom; + display: flex; + flex-direction: row; + justify-content: space-between; + width: 100vh; + position: absolute; + right: 0; + bottom: 0; + padding: 4px 8px; + transform: rotate(-90deg) translate(100%, 0); + transform-origin: right bottom; } :host-context(.dark) { - color: #ccc; + color: #ccc; } p { - margin: 0; - line-height: 1; - white-space: nowrap; - font-style: normal; - font-weight: 400; - font-size: 11px; - color: #999; + margin: 0; + line-height: 1; + white-space: nowrap; + font-style: normal; + font-weight: 400; + font-size: 11px; + color: #999; - &.version { - span { - display: inline-block; - margin-right: 8px; - } - } + &.version { + span { + display: inline-block; + margin-right: 8px; + } + } } .test-environment { - margin-right: $navigation-height + $header-height; - letter-spacing: 0.42em; - text-transform: uppercase; - color: #FF0000; -} \ No newline at end of file + margin-right: $navigation-height + $header-height; + letter-spacing: 0.42em; + text-transform: uppercase; + color: #ff0000; +} diff --git a/alfa-client/libs/navigation/src/lib/build-info/build-info.component.spec.ts b/alfa-client/libs/navigation/src/lib/build-info/build-info.component.spec.ts index aaad84af06d014040bc81fb3875e32ee9e746f14..663ad95f94a684c5b02cae60201ed823b66e4eab 100644 --- a/alfa-client/libs/navigation/src/lib/build-info/build-info.component.spec.ts +++ b/alfa-client/libs/navigation/src/lib/build-info/build-info.component.spec.ts @@ -35,91 +35,87 @@ registerLocaleData(localeDe); jest.mock('@alfa-client/tech-shared', () => mockAsEsModule('@alfa-client/tech-shared')); function mockAsEsModule(module: string) { - return { - __esModule: true, - ...jest.requireActual(module) - }; + return { + __esModule: true, + ...jest.requireActual(module), + }; } describe('BuildInfoComponent', () => { - let component: BuildInfoComponent; - let fixture: ComponentFixture<BuildInfoComponent>; + let component: BuildInfoComponent; + let fixture: ComponentFixture<BuildInfoComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - BuildInfoComponent, - FormatDateWithTimePipe - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [BuildInfoComponent, FormatDateWithTimePipe], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(BuildInfoComponent); - component = fixture.componentInstance; - component.apiRoot = createApiRootResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(BuildInfoComponent); + component = fixture.componentInstance; + component.apiRoot = createApiRootResource(); + fixture.detectChanges(); + }); - it('should create', () => { - fixture.detectChanges(); - expect(component).toBeTruthy(); - }); + it('should create', () => { + fixture.detectChanges(); + expect(component).toBeTruthy(); + }); - describe('isNotProduction', () => { - it('should return true at non-production environment', () => { - component.apiRoot.production = false; + describe('isNotProduction', () => { + it('should return true at non-production environment', () => { + component.apiRoot.production = false; - expect(component.isNotProduction).toBeTruthy(); - }) + expect(component.isNotProduction).toBeTruthy(); + }); - it('should return false at production environment', () => { - component.apiRoot.production = true; + it('should return false at production environment', () => { + component.apiRoot.production = true; - expect(component.isNotProduction).toBeFalsy(); - }) - }) + expect(component.isNotProduction).toBeFalsy(); + }); + }); - describe('isProduction', () => { - it('should return false at non-production environment', () => { - component.apiRoot.production = false; + describe('isProduction', () => { + it('should return false at non-production environment', () => { + component.apiRoot.production = false; - expect(component.isProduction).toBeFalsy(); - }) + expect(component.isProduction).toBeFalsy(); + }); - it('should return true at production environment', () => { - component.apiRoot.production = true; + it('should return true at production environment', () => { + component.apiRoot.production = true; - expect(component.isProduction).toBeTruthy(); - }) - }) + expect(component.isProduction).toBeTruthy(); + }); + }); - describe('version', () => { - it('should return version fragment', () => { - component.apiRoot.version = '1.12.0-SNAPSHOT'; + describe('version', () => { + it('should return version fragment', () => { + component.apiRoot.version = '1.12.0-SNAPSHOT'; - expect(component.version).toBe('1.12.0-SNAPSHOT'); - }) - }) + expect(component.version).toBe('1.12.0-SNAPSHOT'); + }); + }); + describe('buildDate', () => { + it('should call formatFullDate', () => { + const formatFullDate = jest.spyOn(DateUtil, 'formatFullDate'); - describe('buildDate', () => { - it('should call formatFullDate', () => { - const formatFullDate = jest.spyOn(DateUtil, 'formatFullDate'); + component.buildDate; - component.buildDate; + expect(formatFullDate).toHaveBeenCalled(); + }); + }); - expect(formatFullDate).toHaveBeenCalled(); - }) - }) + describe('buildTime', () => { + it('should call formatHourMinute', () => { + const formatHourMinute = jest.spyOn(DateUtil, 'formatHourMinute'); - describe('buildTime', () => { - it('should call formatHourMinute', () => { - const formatHourMinute = jest.spyOn(DateUtil, 'formatHourMinute'); + component.buildTime; - component.buildTime; - - expect(formatHourMinute).toHaveBeenCalled(); - }) - }) + expect(formatHourMinute).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/navigation/src/lib/build-info/build-info.component.ts b/alfa-client/libs/navigation/src/lib/build-info/build-info.component.ts index 7fe2e123dbb79caec1e126576776cdb21316ec6c..be8f576c3288bfb1818b1976030e5f0894a10d8d 100644 --- a/alfa-client/libs/navigation/src/lib/build-info/build-info.component.ts +++ b/alfa-client/libs/navigation/src/lib/build-info/build-info.component.ts @@ -27,32 +27,30 @@ import { ApiRootResource } from '@alfa-client/api-root-shared'; import * as DateUtil from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-build-info', - templateUrl: './build-info.component.html', - styleUrls: ['./build-info.component.scss'] + selector: 'alfa-build-info', + templateUrl: './build-info.component.html', + styleUrls: ['./build-info.component.scss'], }) export class BuildInfoComponent { + @Input() apiRoot: ApiRootResource; - @Input() apiRoot: ApiRootResource; + get isNotProduction() { + return !this.apiRoot.production; + } - get isNotProduction() { - return ! this.apiRoot.production; - } + get isProduction() { + return this.apiRoot.production; + } - get isProduction() { - return this.apiRoot.production; - } + get version() { + return this.apiRoot.version; + } - get version() { - return this.apiRoot.version; - } - - get buildDate() { - return DateUtil.formatFullDate(new Date(this.apiRoot.buildTime)); - } - - get buildTime() { - return DateUtil.formatHourMinute(new Date(this.apiRoot.buildTime)); - } + get buildDate() { + return DateUtil.formatFullDate(new Date(this.apiRoot.buildTime)); + } + get buildTime() { + return DateUtil.formatHourMinute(new Date(this.apiRoot.buildTime)); + } } diff --git a/alfa-client/libs/navigation/src/lib/header-container/header-container.component.spec.ts b/alfa-client/libs/navigation/src/lib/header-container/header-container.component.spec.ts index 8e025870b9183c67707e72c3d28df6a1d9ec3d69..948a92d06692a7472753cab7ce241562d669b0cc 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header-container.component.spec.ts +++ b/alfa-client/libs/navigation/src/lib/header-container/header-container.component.spec.ts @@ -30,34 +30,31 @@ import { HeaderContainerComponent } from './header-container.component'; import { HeaderComponent } from './header/header.component'; describe('HeaderContainerComponent', () => { - let component: HeaderContainerComponent; - let fixture: ComponentFixture<HeaderContainerComponent>; + let component: HeaderContainerComponent; + let fixture: ComponentFixture<HeaderContainerComponent>; - const darkModeSubj: BehaviorSubject<boolean> = new BehaviorSubject(false); - const appService = { ...mock(AppService), getDarkMode: () => darkModeSubj }; + const darkModeSubj: BehaviorSubject<boolean> = new BehaviorSubject(false); + const appService = { ...mock(AppService), getDarkMode: () => darkModeSubj }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HeaderContainerComponent, - MockComponent(HeaderComponent), - ], - providers: [ - { - provide: AppService, - useValue: appService - } - ] - }) - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HeaderContainerComponent, MockComponent(HeaderComponent)], + providers: [ + { + provide: AppService, + useValue: appService, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HeaderContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HeaderContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/navigation/src/lib/header-container/header-container.component.ts b/alfa-client/libs/navigation/src/lib/header-container/header-container.component.ts index 1f5245d75e920d13e72406fd677461b7ad7a6131..83a1abe0ddf77dcaf09282b09ecced8601417607 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header-container.component.ts +++ b/alfa-client/libs/navigation/src/lib/header-container/header-container.component.ts @@ -28,9 +28,8 @@ import { StateResource } from '@alfa-client/tech-shared'; @Component({ selector: 'alfa-header-container', templateUrl: './header-container.component.html', - styleUrls: ['./header-container.component.scss'] + styleUrls: ['./header-container.component.scss'], }) export class HeaderContainerComponent { - - @Input() apiRootStateResource: StateResource<ApiRootResource>; + @Input() apiRootStateResource: StateResource<ApiRootResource>; } diff --git a/alfa-client/libs/navigation/src/lib/header-container/header/_header.theme.scss b/alfa-client/libs/navigation/src/lib/header-container/header/_header.theme.scss index 127aa7e97a2f10e987760780dfa7ccae9c0967ea..9b996e464b9d816898365162cc5d383d81a381ca 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header/_header.theme.scss +++ b/alfa-client/libs/navigation/src/lib/header-container/header/_header.theme.scss @@ -22,11 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ alfa-header header { - background-color: #fff; + background-color: #fff; } body.dark alfa-header { - header { - background-color: rgb(40, 40, 40); - } + header { + background-color: rgb(40, 40, 40); + } } diff --git a/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.html b/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.html index 8597db34694a4c478889365a5a3ddf79fbc5598c..081ee7129d8b6e5ce000f8e32832fd24a102c404 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.html +++ b/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.html @@ -1,3 +1,3 @@ <a routerLink="/" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }"> - <img src="/assets/img/logo.svg" alt="Alfa Logo" data-test-id="alfa-logo" /> + <img src="/assets/img/logo.svg" alt="Alfa Logo" data-test-id="alfa-logo" /> </a> diff --git a/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.scss b/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.scss index 4c692544e2d2960bf4f13c75dca32f70990f2d67..cc20a8eca06c0d52cbb788c1b8b8fd040a9678d5 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.scss +++ b/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.scss @@ -1,23 +1,23 @@ :host { - align-items: center; - justify-content: space-between; + align-items: center; + justify-content: space-between; } a { - outline: 0; - display: flex; - text-decoration: none; - align-items: inherit; - color: inherit; + outline: 0; + display: flex; + text-decoration: none; + align-items: inherit; + color: inherit; } img { - margin: 0 2rem 0 0; - height: 40px; - width: auto; + margin: 0 2rem 0 0; + height: 40px; + width: auto; } .active { - cursor: default; - pointer-events: none; + cursor: default; + pointer-events: none; } diff --git a/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.spec.ts b/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.spec.ts index 97745b18f3766b0e26a137505e35c7f26c77c2f2..ac4ae96e2e39dd51142877a3b8744cfee27acf94 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.spec.ts +++ b/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.spec.ts @@ -3,23 +3,21 @@ import { RouterTestingModule } from '@angular/router/testing'; import { HeaderLogoComponent } from './header-logo.component'; describe('HeaderLogoComponent', () => { - let component: HeaderLogoComponent; - let fixture: ComponentFixture<HeaderLogoComponent>; + let component: HeaderLogoComponent; + let fixture: ComponentFixture<HeaderLogoComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [HeaderLogoComponent], - imports: [ - RouterTestingModule - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [HeaderLogoComponent], + imports: [RouterTestingModule], + }).compileComponents(); - fixture = TestBed.createComponent(HeaderLogoComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(HeaderLogoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.ts b/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.ts index 56aeb29759ba74670313e047647fcaa20bda4fa9..8dc1ffabfa96d893204b05ed8dc9d2c40b70ccfd 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.ts +++ b/alfa-client/libs/navigation/src/lib/header-container/header/header-logo/header-logo.component.ts @@ -1,8 +1,8 @@ import { Component } from '@angular/core'; @Component({ - selector: 'alfa-header-logo', - templateUrl: './header-logo.component.html', - styleUrls: ['./header-logo.component.scss'], + selector: 'alfa-header-logo', + templateUrl: './header-logo.component.html', + styleUrls: ['./header-logo.component.scss'], }) export class HeaderLogoComponent {} diff --git a/alfa-client/libs/navigation/src/lib/header-container/header/header.component.html b/alfa-client/libs/navigation/src/lib/header-container/header/header.component.html index ea035731e6db68588c9b330fd795aa505d7d6906..3ef7590196924bd350d246c4b084c71a1cc7cdd3 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header/header.component.html +++ b/alfa-client/libs/navigation/src/lib/header-container/header/header.component.html @@ -24,15 +24,20 @@ --> <header data-test-id="header"> - <div class="left"> - <alfa-header-logo></alfa-header-logo> - </div> - <div class="middle"> - <alfa-vorgang-search-container></alfa-vorgang-search-container> - </div> - <div class="right"> - <alfa-help-menu [apiRootStateResource]="apiRootStateResource" data-test-id="help-menu"></alfa-help-menu> - <alfa-user-settings-container data-test-id="user-settings"></alfa-user-settings-container> - <alfa-user-profile-in-header-container data-test-id="current-user"></alfa-user-profile-in-header-container> - </div> + <div class="left"> + <alfa-header-logo></alfa-header-logo> + </div> + <div class="middle"> + <alfa-vorgang-search-container></alfa-vorgang-search-container> + </div> + <div class="right"> + <alfa-help-menu + [apiRootStateResource]="apiRootStateResource" + data-test-id="help-menu" + ></alfa-help-menu> + <alfa-user-settings-container data-test-id="user-settings"></alfa-user-settings-container> + <alfa-user-profile-in-header-container + data-test-id="current-user" + ></alfa-user-profile-in-header-container> + </div> </header> diff --git a/alfa-client/libs/navigation/src/lib/header-container/header/header.component.scss b/alfa-client/libs/navigation/src/lib/header-container/header/header.component.scss index d964b13e33bbd1e951cf9c2d08f3843789c326ea..167169bea4acdf42c9032a84041bf48006b45809 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header/header.component.scss +++ b/alfa-client/libs/navigation/src/lib/header-container/header/header.component.scss @@ -26,36 +26,36 @@ @import 'variables'; header { - height: $header-height; - box-shadow: $shadow-bottom; - padding: 0.5rem 2rem 0.5rem 1rem; - left: 0; - top: 0; - right: 0; - width: 100%; - z-index: 3; - display: flex; - align-items: center; - justify-content: space-between; - position: fixed; + height: $header-height; + box-shadow: $shadow-bottom; + padding: 0.5rem 2rem 0.5rem 1rem; + left: 0; + top: 0; + right: 0; + width: 100%; + z-index: 3; + display: flex; + align-items: center; + justify-content: space-between; + position: fixed; } .middle { - flex-grow: 1; - margin-right: 1rem; + flex-grow: 1; + margin-right: 1rem; } .left { - display: flex; - align-items: inherit; - margin-left: 0.75rem; - @include media('>desktop') { - min-width: 240px; - } + display: flex; + align-items: inherit; + margin-left: 0.75rem; + @include media('>desktop') { + min-width: 240px; + } } .right { - color: $grey; - display: flex; - align-items: center; + color: $grey; + display: flex; + align-items: center; } diff --git a/alfa-client/libs/navigation/src/lib/header-container/header/header.component.spec.ts b/alfa-client/libs/navigation/src/lib/header-container/header/header.component.spec.ts index 16319d18bcf9589621a6df16801c7a576f4af7ff..34785fb2ebc6a98efcfaa675cec5f40fe6e7b405 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header/header.component.spec.ts +++ b/alfa-client/libs/navigation/src/lib/header-container/header/header.component.spec.ts @@ -32,32 +32,30 @@ import { HeaderLogoComponent } from './header-logo/header-logo.component'; import { HeaderComponent } from './header.component'; describe('HeaderComponent', () => { - let component: HeaderComponent; - let fixture: ComponentFixture<HeaderComponent>; + let component: HeaderComponent; + let fixture: ComponentFixture<HeaderComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - UiModule - ], - declarations: [ - HeaderComponent, - MockComponent(HeaderLogoComponent), - MockComponent(VorgangSearchContainerComponent), - MockComponent(UserSettingsContainerComponent), - MockComponent(UserProfileInHeaderContainerComponent), - MockComponent(HelpMenuComponent) - ] - }) - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [UiModule], + declarations: [ + HeaderComponent, + MockComponent(HeaderLogoComponent), + MockComponent(VorgangSearchContainerComponent), + MockComponent(UserSettingsContainerComponent), + MockComponent(UserProfileInHeaderContainerComponent), + MockComponent(HelpMenuComponent), + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(HeaderComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(HeaderComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/navigation/src/lib/header-container/header/header.component.ts b/alfa-client/libs/navigation/src/lib/header-container/header/header.component.ts index 0d98f0456bd71fd7c80ce3f678a509b71b3077ec..a70ad5271fb6fc5fe60ba376a8dc408d5c885e75 100644 --- a/alfa-client/libs/navigation/src/lib/header-container/header/header.component.ts +++ b/alfa-client/libs/navigation/src/lib/header-container/header/header.component.ts @@ -28,9 +28,8 @@ import { StateResource } from '@alfa-client/tech-shared'; @Component({ selector: 'alfa-header', templateUrl: './header.component.html', - styleUrls: ['./header.component.scss'] + styleUrls: ['./header.component.scss'], }) export class HeaderComponent { - - @Input() apiRootStateResource: StateResource<ApiRootResource>; + @Input() apiRootStateResource: StateResource<ApiRootResource>; } diff --git a/alfa-client/libs/navigation/src/lib/navigation.module.spec.ts b/alfa-client/libs/navigation/src/lib/navigation.module.spec.ts index e8c9a1982ff323465ede42e9ddc3c263af7f08bd..8da8545041935e738310f3be4d97cdefbb35444b 100644 --- a/alfa-client/libs/navigation/src/lib/navigation.module.spec.ts +++ b/alfa-client/libs/navigation/src/lib/navigation.module.spec.ts @@ -25,18 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { NavigationModule } from './navigation.module'; describe('UiModule', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [NavigationModule], + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [NavigationModule], + }); + }); - }) - }); - - it('should create', () => { - expect(NavigationModule).toBeDefined(); - }); + it('should create', () => { + expect(NavigationModule).toBeDefined(); + }); }); - - - - diff --git a/alfa-client/libs/navigation/src/lib/navigation.module.ts b/alfa-client/libs/navigation/src/lib/navigation.module.ts index 25ba933223f029fe765688b9c8044bf7f24a5553..0a98c2c4232b12ea4f7e1004d30f8828bdd0769f 100644 --- a/alfa-client/libs/navigation/src/lib/navigation.module.ts +++ b/alfa-client/libs/navigation/src/lib/navigation.module.ts @@ -35,24 +35,21 @@ import { HeaderLogoComponent } from './header-container/header/header-logo/heade import { HeaderComponent } from './header-container/header/header.component'; @NgModule({ - declarations: [ - BuildInfoComponent, - HeaderComponent, - HeaderContainerComponent, - HeaderLogoComponent, - ], - imports: [ - CommonModule, - UiModule, - RouterModule, - VorgangSharedUiModule, - UserProfileModule, - UserSettingsModule, - UserAssistanceModule - ], - exports: [ - BuildInfoComponent, - HeaderContainerComponent, - ] + declarations: [ + BuildInfoComponent, + HeaderComponent, + HeaderContainerComponent, + HeaderLogoComponent, + ], + imports: [ + CommonModule, + UiModule, + RouterModule, + VorgangSharedUiModule, + UserProfileModule, + UserSettingsModule, + UserAssistanceModule, + ], + exports: [BuildInfoComponent, HeaderContainerComponent], }) export class NavigationModule {} diff --git a/alfa-client/libs/navigation/src/test-setup.ts b/alfa-client/libs/navigation/src/test-setup.ts index dc74cf29206a7ce287ef667322818782b2ba86b4..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/navigation/src/test-setup.ts +++ b/alfa-client/libs/navigation/src/test-setup.ts @@ -25,15 +25,14 @@ import '@testing-library/jest-dom'; import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; -import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, +} from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/navigation/tsconfig.json b/alfa-client/libs/navigation/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/navigation/tsconfig.json +++ b/alfa-client/libs/navigation/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/navigation/tsconfig.lib.json b/alfa-client/libs/navigation/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/navigation/tsconfig.lib.json +++ b/alfa-client/libs/navigation/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/navigation/tsconfig.spec.json b/alfa-client/libs/navigation/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/navigation/tsconfig.spec.json +++ b/alfa-client/libs/navigation/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/postfach-shared/.eslintrc.json b/alfa-client/libs/postfach-shared/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/postfach-shared/.eslintrc.json +++ b/alfa-client/libs/postfach-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/postfach-shared/jest.config.ts b/alfa-client/libs/postfach-shared/jest.config.ts index 7b052af37a15131ef8d3668d6be86c78d58b978e..5b9ed72557c399cd8d22eb476d1fd7c07a24d307 100644 --- a/alfa-client/libs/postfach-shared/jest.config.ts +++ b/alfa-client/libs/postfach-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'postfach-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/postfach-shared', - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'postfach-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/postfach-shared', + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/postfach-shared/project.json b/alfa-client/libs/postfach-shared/project.json index c4ca0eaec8515627d71a4b27c0d437033a845496..ce4ba4c5fa696c08c6cd6e987d4244202c26377c 100644 --- a/alfa-client/libs/postfach-shared/project.json +++ b/alfa-client/libs/postfach-shared/project.json @@ -1,29 +1,29 @@ { - "name": "postfach-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/postfach-shared/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/postfach-shared"], - "options": { - "tsConfig": "libs/postfach-shared/tsconfig.spec.json", - "jestConfig": "libs/postfach-shared/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/postfach-shared/src/**/*.ts", - "libs/postfach-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [] + "name": "postfach-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/postfach-shared/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/postfach-shared"], + "options": { + "tsConfig": "libs/postfach-shared/tsconfig.spec.json", + "jestConfig": "libs/postfach-shared/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/postfach-shared/src/**/*.ts", + "libs/postfach-shared/src/**/*.html" + ] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [] } diff --git a/alfa-client/libs/postfach-shared/src/index.ts b/alfa-client/libs/postfach-shared/src/index.ts index ad852d77b9bde3cea5133118c813ee2a59ce7876..dafa314d2a9fb26389657649f7f7f643aa942a65 100644 --- a/alfa-client/libs/postfach-shared/src/index.ts +++ b/alfa-client/libs/postfach-shared/src/index.ts @@ -30,4 +30,3 @@ export * from './lib/postfach.model'; export * from './lib/postfach.service'; export * from './lib/postfach.tokens'; export * from './lib/postfach.util'; - diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.actions.model.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.actions.model.ts index ac3d4b768127595f1f631af899c55eb7546e3a59..1d421eebea36e6cd9250d8c34023db7a71f0f695 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.actions.model.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.actions.model.ts @@ -1,5 +1,5 @@ import { PostfachMailResource } from '../postfach.model'; export interface PostfachNachrichtProps { - postfachNachricht: PostfachMailResource -} \ No newline at end of file + postfachNachricht: PostfachMailResource; +} diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.actions.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.actions.ts index 916dc2a5701830b1fe5b40908a419b8f16d7490a..f7789b49c8785d3527aee8e93644d5481e197968 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.actions.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.actions.ts @@ -22,15 +22,35 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { LoadBinaryFileListSuccessProps } from '@alfa-client/binary-file-shared'; -import { ApiErrorAction, TypedActionCreator, TypedActionCreatorWithProps } from '@alfa-client/tech-shared'; +import { + ApiErrorAction, + TypedActionCreator, + TypedActionCreatorWithProps, +} from '@alfa-client/tech-shared'; import { createAction, props } from '@ngrx/store'; import { PostfachNachrichtProps } from './postfach.actions.model'; -export const startDownloadAsPdf: TypedActionCreator = createAction('[Postfach] Start Download Nachrichten as pdf'); -export const downloadAsPdfSuccess: TypedActionCreator = createAction('[Postfach/API] Download Nachrichten as pdf Success'); -export const downloadAsPdfFailed: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Postfach/API] Download Nachrichten as pdf Failure', props<ApiErrorAction>()); +export const startDownloadAsPdf: TypedActionCreator = createAction( + '[Postfach] Start Download Nachrichten as pdf', +); +export const downloadAsPdfSuccess: TypedActionCreator = createAction( + '[Postfach/API] Download Nachrichten as pdf Success', +); +export const downloadAsPdfFailed: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[Postfach/API] Download Nachrichten as pdf Failure', + props<ApiErrorAction>(), +); -export const loadAttachmentList: TypedActionCreatorWithProps<PostfachNachrichtProps> = createAction('[Postfach] Load attachmentList', props<PostfachNachrichtProps>()); -export const loadAttachmentListSuccess: TypedActionCreatorWithProps<LoadBinaryFileListSuccessProps> = createAction('[Postfach] Load attachmentList success', props<LoadBinaryFileListSuccessProps>()); -export const loadAttachmentListFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Postfach] Load attachmentList failure', props<ApiErrorAction>()); -export const clearAttachmentList: TypedActionCreator = createAction('[Postfach] Clear AttachmentList'); \ No newline at end of file +export const loadAttachmentList: TypedActionCreatorWithProps<PostfachNachrichtProps> = createAction( + '[Postfach] Load attachmentList', + props<PostfachNachrichtProps>(), +); +export const loadAttachmentListSuccess: TypedActionCreatorWithProps<LoadBinaryFileListSuccessProps> = + createAction('[Postfach] Load attachmentList success', props<LoadBinaryFileListSuccessProps>()); +export const loadAttachmentListFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[Postfach] Load attachmentList failure', + props<ApiErrorAction>(), +); +export const clearAttachmentList: TypedActionCreator = createAction( + '[Postfach] Clear AttachmentList', +); diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.effects.spec.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.effects.spec.ts index 9a3b9cc4ba10581c418c699127bcf122a115fe83..ee2af0f933130d76147da5433ecc5925d76abd2e 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.effects.spec.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.effects.spec.ts @@ -44,106 +44,123 @@ import { PostfachEffects } from './postfach.effects'; import * as PostfachActions from './postfach.actions'; describe('PostfachEffects', () => { - let actions: Observable<Action>; - let effects: PostfachEffects; - - const snackBarService: Mock<SnackBarService> = mock(SnackBarService); - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - PostfachEffects, - provideMockActions(() => actions), - provideMockStore(), - { - provide: SnackBarService, - useValue: snackBarService - } - ] - }); - effects = TestBed.inject(PostfachEffects); - }); - - describe('downloadAsPdfFailed', () => { - - describe('on usermanager service unavailable message code', () => { - - it('should call snackbar service with error message', () => { - const apiError: ApiError = { ...createApiError(), issues: [{ ...createIssue(), messageCode: MessageCode.USER_MANAGER_SERVICE_UNAVAILABLE }] }; - const action: ApiErrorAction & TypedAction<string> = PostfachActions.downloadAsPdfFailed({ apiError }); - - actions = hot('-a', { a: action }); - - effects.downloadAsPdfFailed$.subscribe(() => { - expect(snackBarService.showError).toHaveBeenCalledWith(Messages.HTTP_USER_MANAGER_SERVICE_UNAVAILABLE); - }); - }); - }) - - describe('on other message code', () => { - - it('should not call snackbar service', () => { - const apiError: ApiError = { ...createApiError(), issues: [{ ...createIssue(), messageCode: 'nonMatchingMessageCode' }] }; - const action: ApiErrorAction & TypedAction<string> = PostfachActions.downloadAsPdfFailed({ apiError }); - - actions = hot('-a', { a: action }); - - effects.downloadAsPdfFailed$.subscribe(() => { - expect(snackBarService.showError).not.toHaveBeenCalledWith(); - }); - }); - }) - }) - - describe('loadAttachmentList', () => { - - const postfachNachricht: PostfachMailResource = createPostfachMailResource(); - const action: PostfachNachrichtProps & TypedAction<string> = PostfachActions.loadAttachmentList({ postfachNachricht }); - const props: LoadBinaryFileListProps = <any>{}; - - it('should dispatch "loadAttachmentList" action', () => { - effects.createLoadAttachmentListProps = jest.fn().mockReturnValue(props); - - actions = hot('-a-|', { a: action }); - - const expected = hot('-a-|', { a: loadBinaryFileList(props) }); - expect(effects.loadAttachmentList$).toBeObservable(expected); - }) - - it('should create props', () => { - effects.createLoadAttachmentListProps = jest.fn() - actions = of(action); - - effects.loadAttachmentList$.subscribe(); - - expect(effects.createLoadAttachmentListProps).toHaveBeenCalledWith(postfachNachricht); - }) - - describe('createLoadAttachmentListProps', () => { - - it('should have resource', () => { - const props: LoadBinaryFileListProps = effects.createLoadAttachmentListProps(postfachNachricht); - - expect(props.resource).toBe(postfachNachricht); - }) - - it('should have linkRel', () => { - const props: LoadBinaryFileListProps = effects.createLoadAttachmentListProps(postfachNachricht); - - expect(props.linkRel).toBe(PostfachMailLinkRel.ATTACHMENTS); - }) - - it('should have success action', () => { - const props: LoadBinaryFileListProps = effects.createLoadAttachmentListProps(postfachNachricht); - - expect(props.successAction(createBinaryFileListResource()).type).toEqual('[Postfach] Load attachmentList success'); - }) - - it('should have failure action', () => { - const props: LoadBinaryFileListProps = effects.createLoadAttachmentListProps(postfachNachricht); - - expect(props.failureAction(createApiError()).type).toEqual('[Postfach] Load attachmentList failure'); - }) - }) - }) -}); \ No newline at end of file + let actions: Observable<Action>; + let effects: PostfachEffects; + + const snackBarService: Mock<SnackBarService> = mock(SnackBarService); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + PostfachEffects, + provideMockActions(() => actions), + provideMockStore(), + { + provide: SnackBarService, + useValue: snackBarService, + }, + ], + }); + effects = TestBed.inject(PostfachEffects); + }); + + describe('downloadAsPdfFailed', () => { + describe('on usermanager service unavailable message code', () => { + it('should call snackbar service with error message', () => { + const apiError: ApiError = { + ...createApiError(), + issues: [{ ...createIssue(), messageCode: MessageCode.USER_MANAGER_SERVICE_UNAVAILABLE }], + }; + const action: ApiErrorAction & TypedAction<string> = PostfachActions.downloadAsPdfFailed({ + apiError, + }); + + actions = hot('-a', { a: action }); + + effects.downloadAsPdfFailed$.subscribe(() => { + expect(snackBarService.showError).toHaveBeenCalledWith( + Messages.HTTP_USER_MANAGER_SERVICE_UNAVAILABLE, + ); + }); + }); + }); + + describe('on other message code', () => { + it('should not call snackbar service', () => { + const apiError: ApiError = { + ...createApiError(), + issues: [{ ...createIssue(), messageCode: 'nonMatchingMessageCode' }], + }; + const action: ApiErrorAction & TypedAction<string> = PostfachActions.downloadAsPdfFailed({ + apiError, + }); + + actions = hot('-a', { a: action }); + + effects.downloadAsPdfFailed$.subscribe(() => { + expect(snackBarService.showError).not.toHaveBeenCalledWith(); + }); + }); + }); + }); + + describe('loadAttachmentList', () => { + const postfachNachricht: PostfachMailResource = createPostfachMailResource(); + const action: PostfachNachrichtProps & TypedAction<string> = PostfachActions.loadAttachmentList( + { postfachNachricht }, + ); + const props: LoadBinaryFileListProps = <any>{}; + + it('should dispatch "loadAttachmentList" action', () => { + effects.createLoadAttachmentListProps = jest.fn().mockReturnValue(props); + + actions = hot('-a-|', { a: action }); + + const expected = hot('-a-|', { a: loadBinaryFileList(props) }); + expect(effects.loadAttachmentList$).toBeObservable(expected); + }); + + it('should create props', () => { + effects.createLoadAttachmentListProps = jest.fn(); + actions = of(action); + + effects.loadAttachmentList$.subscribe(); + + expect(effects.createLoadAttachmentListProps).toHaveBeenCalledWith(postfachNachricht); + }); + + describe('createLoadAttachmentListProps', () => { + it('should have resource', () => { + const props: LoadBinaryFileListProps = + effects.createLoadAttachmentListProps(postfachNachricht); + + expect(props.resource).toBe(postfachNachricht); + }); + + it('should have linkRel', () => { + const props: LoadBinaryFileListProps = + effects.createLoadAttachmentListProps(postfachNachricht); + + expect(props.linkRel).toBe(PostfachMailLinkRel.ATTACHMENTS); + }); + + it('should have success action', () => { + const props: LoadBinaryFileListProps = + effects.createLoadAttachmentListProps(postfachNachricht); + + expect(props.successAction(createBinaryFileListResource()).type).toEqual( + '[Postfach] Load attachmentList success', + ); + }); + + it('should have failure action', () => { + const props: LoadBinaryFileListProps = + effects.createLoadAttachmentListProps(postfachNachricht); + + expect(props.failureAction(createApiError()).type).toEqual( + '[Postfach] Load attachmentList failure', + ); + }); + }); + }); +}); diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.effects.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.effects.ts index 63df5cb54f18f92853da0607ff9e5020d2aa469d..c792279f03ad848294998109e8bb06bee95d8f7c 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.effects.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.effects.ts @@ -23,7 +23,11 @@ */ import { Injectable } from '@angular/core'; -import { BinaryFileListResource, loadBinaryFileList, LoadBinaryFileListProps } from '@alfa-client/binary-file-shared'; +import { + BinaryFileListResource, + loadBinaryFileList, + LoadBinaryFileListProps, +} from '@alfa-client/binary-file-shared'; import { ApiError, ApiErrorAction, getMessageCode, MessageCode } from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; import { Actions, createEffect, ofType } from '@ngrx/effects'; @@ -38,24 +42,41 @@ import * as PostfachActions from './postfach.actions'; @Injectable() export class PostfachEffects { + constructor( + private readonly actions$: Actions, + private readonly snackBarService: SnackBarService, + ) {} - constructor(private readonly actions$: Actions, private readonly snackBarService: SnackBarService) { } + downloadAsPdfFailed$ = createEffect( + () => + this.actions$.pipe( + ofType(PostfachActions.downloadAsPdfFailed), + tap((action: ApiErrorAction) => { + if (getMessageCode(action.apiError) == MessageCode.USER_MANAGER_SERVICE_UNAVAILABLE) { + this.snackBarService.showError(Messages.HTTP_USER_MANAGER_SERVICE_UNAVAILABLE); + } + }), + ), + { dispatch: false }, + ); - downloadAsPdfFailed$ = createEffect(() => this.actions$.pipe(ofType(PostfachActions.downloadAsPdfFailed), - tap((action: ApiErrorAction) => { - if (getMessageCode(action.apiError) == MessageCode.USER_MANAGER_SERVICE_UNAVAILABLE) { - this.snackBarService.showError(Messages.HTTP_USER_MANAGER_SERVICE_UNAVAILABLE); - } - })), { dispatch: false }) + loadAttachmentList$ = createEffect(() => + this.actions$.pipe( + ofType(PostfachActions.loadAttachmentList), + switchMap((props: PostfachNachrichtProps) => + of(loadBinaryFileList(this.createLoadAttachmentListProps(props.postfachNachricht))), + ), + ), + ); - loadAttachmentList$ = createEffect(() => this.actions$.pipe(ofType(PostfachActions.loadAttachmentList), - switchMap((props: PostfachNachrichtProps) => of(loadBinaryFileList(this.createLoadAttachmentListProps(props.postfachNachricht)))) - )) - - createLoadAttachmentListProps(postfachNachricht: PostfachMailResource): LoadBinaryFileListProps { - return { resource: postfachNachricht, linkRel: PostfachMailLinkRel.ATTACHMENTS, - successAction: (binaryFileList: BinaryFileListResource) => PostfachActions.loadAttachmentListSuccess({ binaryFileList }), - failureAction: (apiError: ApiError) => PostfachActions.loadAttachmentListFailure({ apiError }) - } - } -} \ No newline at end of file + createLoadAttachmentListProps(postfachNachricht: PostfachMailResource): LoadBinaryFileListProps { + return { + resource: postfachNachricht, + linkRel: PostfachMailLinkRel.ATTACHMENTS, + successAction: (binaryFileList: BinaryFileListResource) => + PostfachActions.loadAttachmentListSuccess({ binaryFileList }), + failureAction: (apiError: ApiError) => + PostfachActions.loadAttachmentListFailure({ apiError }), + }; + } +} diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.spec.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.spec.ts index 8828c4fca44cab1ae6662d87e27bf26bbf50e8aa..ef93c78e196250e7fec602e596534791c02499a9 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.spec.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.spec.ts @@ -24,7 +24,10 @@ import { formatDate, registerLocaleData } from '@angular/common'; import localeDe from '@angular/common/locales/de'; -import { BinaryFileListResource, DownloadBinaryFileAsPdfAction } from '@alfa-client/binary-file-shared'; +import { + BinaryFileListResource, + DownloadBinaryFileAsPdfAction, +} from '@alfa-client/binary-file-shared'; import { StateResource, createStateResource } from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { VorgangHeaderLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @@ -44,136 +47,136 @@ import * as PostfachSelectors from './postfach.selectors'; registerLocaleData(localeDe); describe('PostfachFacade', () => { + let facade: PostfachFacade; + let store: Mock<Store>; - let facade: PostfachFacade; - let store: Mock<Store>; + let selectionSubject: Subject<any>; - let selectionSubject: Subject<any>; + beforeEach(() => { + store = mock(Store); - beforeEach(() => { - store = mock(Store); + selectionSubject = new Subject(); - selectionSubject = new Subject(); + store.select.mockReturnValue(selectionSubject); + store.dispatch = jest.fn(); - store.select.mockReturnValue(selectionSubject); - store.dispatch = jest.fn(); + facade = new PostfachFacade(useFromMock(<any>store)); + }); - facade = new PostfachFacade(useFromMock(<any>store)); - }) + it('is initialized', () => { + expect(facade).toBeTruthy(); + }); - it('is initialized', () => { - expect(facade).toBeTruthy(); - }) + describe('startDownloadPdf', () => { + it('should dispatch "startDownloadAsPdf" action', () => { + facade.startDownloadPdf(); - describe('startDownloadPdf', () => { + expect(store.dispatch).toHaveBeenCalledWith(PostfachActions.startDownloadAsPdf()); + }); + }); - it('should dispatch "startDownloadAsPdf" action', () => { - facade.startDownloadPdf(); + describe('isDownloadPdfInProgress', () => { + it('should return value', (done) => { + facade.isDownloadPdfInProgress().subscribe((isInProgress) => { + expect(isInProgress).toBeTruthy(); + done(); + }); - expect(store.dispatch).toHaveBeenCalledWith(PostfachActions.startDownloadAsPdf()); - }); - }) + selectionSubject.next(true); + }); + }); - describe('isDownloadPdfInProgress', () => { + describe('downloadPdf', () => { + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const downloadAction: DownloadBinaryFileAsPdfAction = <any>{}; - it('should return value', (done) => { - facade.isDownloadPdfInProgress().subscribe(isInProgress => { - expect(isInProgress).toBeTruthy(); - done(); - }); + beforeEach(() => { + facade.createDownloadPdfProps = jest.fn().mockReturnValue(downloadAction); + }); - selectionSubject.next(true); - }); - }) + it('should dispatch "downloadPdf" action', () => { + facade.downloadPdf(vorgang); - describe('downloadPdf', () => { + expect(store.dispatch).toHaveBeenCalledWith(BinaryFileActions.downloadPdf(downloadAction)); + }); - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const downloadAction: DownloadBinaryFileAsPdfAction = <any>{}; + it('should create props', () => { + facade.downloadPdf(vorgang); - beforeEach(() => { - facade.createDownloadPdfProps = jest.fn().mockReturnValue(downloadAction); - }) + expect(facade.createDownloadPdfProps).toHaveBeenCalledWith(vorgang); + }); + }); - it('should dispatch "downloadPdf" action', () => { - facade.downloadPdf(vorgang); + describe('createDownloadPdfProps', () => { + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangHeaderLinkRel.POSTFACH_MAILS, + ]); - expect(store.dispatch).toHaveBeenCalledWith(BinaryFileActions.downloadPdf(downloadAction)); - }) + it('should have uri', () => { + const props: DownloadBinaryFileAsPdfAction = facade.createDownloadPdfProps(vorgang); - it('should create props', () => { - facade.downloadPdf(vorgang); + expect(props.uri).toBe(getUrl(vorgang, VorgangHeaderLinkRel.POSTFACH_MAILS)); + }); - expect(facade.createDownloadPdfProps).toHaveBeenCalledWith(vorgang); - }) - }) + it('should have fileName', () => { + const props: DownloadBinaryFileAsPdfAction = facade.createDownloadPdfProps(vorgang); - describe('createDownloadPdfProps', () => { + expect(props.fileName).toBe( + `${vorgang.nummer}_${formatDate(new Date(), 'yyyyMMdd', 'de')}_Nachrichten.pdf`, + ); + }); - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangHeaderLinkRel.POSTFACH_MAILS]); + it('should have "downloadAsPdfSuccess" as success action', () => { + const props: DownloadBinaryFileAsPdfAction = facade.createDownloadPdfProps(vorgang); - it('should have uri', () => { - const props: DownloadBinaryFileAsPdfAction = facade.createDownloadPdfProps(vorgang); + expect(props.successAction).toBe(PostfachActions.downloadAsPdfSuccess); + }); - expect(props.uri).toBe(getUrl(vorgang, VorgangHeaderLinkRel.POSTFACH_MAILS)); - }) + it('should have "downloadAsPdfFailed" as failure action', () => { + const props: DownloadBinaryFileAsPdfAction = facade.createDownloadPdfProps(vorgang); - it('should have fileName', () => { - const props: DownloadBinaryFileAsPdfAction = facade.createDownloadPdfProps(vorgang); + expect(props.failureAction).toBe(facade.createFailureAction); + }); + }); - expect(props.fileName).toBe(`${vorgang.nummer}_${formatDate(new Date(), 'yyyyMMdd', 'de')}_Nachrichten.pdf`); - }) + describe('getAttachments', () => { + const attachmentListStateResource: StateResource<BinaryFileListResource> = createStateResource( + createBinaryFileListResource(), + ); - it('should have "downloadAsPdfSuccess" as success action', () => { - const props: DownloadBinaryFileAsPdfAction = facade.createDownloadPdfProps(vorgang); + it('should select attachmentList', () => { + facade.getAttachmentList(); - expect(props.successAction).toBe(PostfachActions.downloadAsPdfSuccess); - }) + expect(store.select).toHaveBeenCalledWith(PostfachSelectors.attachmentList); + }); - it('should have "downloadAsPdfFailed" as failure action', () => { - const props: DownloadBinaryFileAsPdfAction = facade.createDownloadPdfProps(vorgang); + it('should return selected value', (done) => { + store.select.mockReturnValue(of(attachmentListStateResource)); - expect(props.failureAction).toBe(facade.createFailureAction); - }) - }) + facade.getAttachmentList().subscribe((attachmentList) => { + expect(attachmentList).toBe(attachmentListStateResource); + done(); + }); + }); + }); - describe('getAttachments', () => { + describe('loadAttachmentList', () => { + const postfachNachricht: PostfachMailResource = createPostfachMailResource(); - const attachmentListStateResource: StateResource<BinaryFileListResource> = createStateResource(createBinaryFileListResource()); + it('should dispatch action', () => { + facade.loadAttachmentList(postfachNachricht); - it('should select attachmentList', () => { - facade.getAttachmentList(); + expect(store.dispatch).toHaveBeenCalledWith( + PostfachActions.loadAttachmentList({ postfachNachricht }), + ); + }); + }); - expect(store.select).toHaveBeenCalledWith(PostfachSelectors.attachmentList); - }) + describe('clearAttachmentList', () => { + it('should dispatch action', () => { + facade.clearAttachmentList(); - it('should return selected value', (done) => { - store.select.mockReturnValue(of(attachmentListStateResource)); - - facade.getAttachmentList().subscribe(attachmentList => { - expect(attachmentList).toBe(attachmentListStateResource); - done(); - }); - }) - }) - - describe('loadAttachmentList', () => { - - const postfachNachricht: PostfachMailResource = createPostfachMailResource(); - - it('should dispatch action', () => { - facade.loadAttachmentList(postfachNachricht); - - expect(store.dispatch).toHaveBeenCalledWith(PostfachActions.loadAttachmentList({ postfachNachricht })); - }) - }) - - describe('clearAttachmentList', () => { - - it('should dispatch action', () => { - facade.clearAttachmentList(); - - expect(store.dispatch).toHaveBeenCalledWith(PostfachActions.clearAttachmentList()); - }) - }) + expect(store.dispatch).toHaveBeenCalledWith(PostfachActions.clearAttachmentList()); + }); + }); }); diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts index 0bc1e6878587fff1f820cedf324dc7d8477c7334..423bbc52e53864dd9638e3eefa0de63edc984476 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.facade.ts @@ -22,8 +22,16 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Injectable } from '@angular/core'; -import { BinaryFileListResource, DownloadBinaryFileAsPdfAction } from '@alfa-client/binary-file-shared'; -import { ApiError, ApiErrorAction, StateResource, formatFullDateWithoutSeperator } from '@alfa-client/tech-shared'; +import { + BinaryFileListResource, + DownloadBinaryFileAsPdfAction, +} from '@alfa-client/binary-file-shared'; +import { + ApiError, + ApiErrorAction, + StateResource, + formatFullDateWithoutSeperator, +} from '@alfa-client/tech-shared'; import { VorgangHeaderLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { Store } from '@ngrx/store'; import { TypedAction } from '@ngrx/store/src/models'; @@ -37,47 +45,50 @@ import * as PostfachSelectors from './postfach.selectors'; @Injectable() export class PostfachFacade { + constructor(private readonly store: Store) {} - constructor(private readonly store: Store) { } + public startDownloadPdf(): void { + this.store.dispatch(PostfachActions.startDownloadAsPdf()); + } - public startDownloadPdf(): void { - this.store.dispatch(PostfachActions.startDownloadAsPdf()); - } + public isDownloadPdfInProgress(): Observable<boolean> { + return this.store.select(PostfachSelectors.isDownloadPdfInProgress); + } - public isDownloadPdfInProgress(): Observable<boolean> { - return this.store.select(PostfachSelectors.isDownloadPdfInProgress); - } + public downloadPdf(vorgangWithEingang: VorgangWithEingangResource): void { + this.store.dispatch( + BinaryFileActions.downloadPdf(this.createDownloadPdfProps(vorgangWithEingang)), + ); + } - public downloadPdf(vorgangWithEingang: VorgangWithEingangResource): void { - this.store.dispatch(BinaryFileActions.downloadPdf(this.createDownloadPdfProps(vorgangWithEingang))); - } + createDownloadPdfProps( + vorgangWithEingang: VorgangWithEingangResource, + ): DownloadBinaryFileAsPdfAction { + return { + uri: getUrl(vorgangWithEingang, VorgangHeaderLinkRel.POSTFACH_MAILS), + fileName: this.buildFileName(vorgangWithEingang), + successAction: PostfachActions.downloadAsPdfSuccess, + failureAction: this.createFailureAction, + }; + } - createDownloadPdfProps(vorgangWithEingang: VorgangWithEingangResource): DownloadBinaryFileAsPdfAction { - return { - uri: getUrl(vorgangWithEingang, VorgangHeaderLinkRel.POSTFACH_MAILS), - fileName: this.buildFileName(vorgangWithEingang), - successAction: PostfachActions.downloadAsPdfSuccess, - failureAction: this.createFailureAction - } - } + buildFileName(vorgangWithEingang: VorgangWithEingangResource): string { + return `${vorgangWithEingang.nummer}_${formatFullDateWithoutSeperator(new Date())}_Nachrichten.pdf`; + } - buildFileName(vorgangWithEingang: VorgangWithEingangResource): string { - return `${vorgangWithEingang.nummer}_${formatFullDateWithoutSeperator(new Date())}_Nachrichten.pdf`; - } + createFailureAction(apiError: ApiError): ApiErrorAction & TypedAction<string> { + return PostfachActions.downloadAsPdfFailed({ apiError }); + } - createFailureAction(apiError: ApiError): ApiErrorAction & TypedAction<string> { - return PostfachActions.downloadAsPdfFailed({ apiError }); - } + public getAttachmentList(): Observable<StateResource<BinaryFileListResource>> { + return this.store.select(PostfachSelectors.attachmentList); + } - public getAttachmentList(): Observable<StateResource<BinaryFileListResource>> { - return this.store.select(PostfachSelectors.attachmentList); - } + public loadAttachmentList(postfachNachricht: PostfachMailResource): void { + this.store.dispatch(PostfachActions.loadAttachmentList({ postfachNachricht })); + } - public loadAttachmentList(postfachNachricht: PostfachMailResource): void { - this.store.dispatch(PostfachActions.loadAttachmentList({ postfachNachricht })); - } - - public clearAttachmentList(): void { - this.store.dispatch(PostfachActions.clearAttachmentList()); - } -} \ No newline at end of file + public clearAttachmentList(): void { + this.store.dispatch(PostfachActions.clearAttachmentList()); + } +} diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.reducer.spec.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.reducer.spec.ts index c689548ec594007c3770a28ce92bd9a603cc44de..8044aff1e9583ac280b8c567a57aa3e8899d8aaf 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.reducer.spec.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.reducer.spec.ts @@ -21,8 +21,17 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { BinaryFileListResource, LoadBinaryFileListSuccessProps } from '@alfa-client/binary-file-shared'; -import { ApiError, ApiErrorAction, EMPTY_ACTION, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + BinaryFileListResource, + LoadBinaryFileListSuccessProps, +} from '@alfa-client/binary-file-shared'; +import { + ApiError, + ApiErrorAction, + EMPTY_ACTION, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { TypedAction } from '@ngrx/store/src/models'; import { createBinaryFileListResource } from 'libs/binary-file-shared/test/binary-file'; import { createPostfachMailResource } from 'libs/postfach-shared/test/postfach'; @@ -34,99 +43,105 @@ import { PostfachState, initialPostfachState, postfachReducer } from './postfach import * as PostfachActions from './postfach.actions'; describe('Postfach Reducer', () => { - - describe('unknown action', () => { - - it('should return current state', () => { - const state: PostfachState = postfachReducer(initialPostfachState, EMPTY_ACTION); - - expect(state).toBe(initialPostfachState); - }) - }) - - describe('isDownloadPdfInProgress', () => { - - describe('on "startDownloadAsPdf" action', () => { - - it('should set to true', () => { - const action: TypedAction<string> = PostfachActions.startDownloadAsPdf(); - - const state: PostfachState = postfachReducer(initialPostfachState, action); - - expect(state.isDownloadPdfInProgress).toBeTruthy(); - }) - }) - - describe('on "downloadAsPdfSuccess" action', () => { - - it('should set to false', () => { - const action: TypedAction<string> = PostfachActions.downloadAsPdfSuccess(); - - const state: PostfachState = postfachReducer({ ...initialPostfachState, isDownloadPdfInProgress: true }, action); - - expect(state.isDownloadPdfInProgress).toBeFalsy(); - }) - }) - - describe('on "downloadAsPdfFailed" action', () => { - - it('should set to false', () => { - const action: ApiErrorAction & TypedAction<string> = PostfachActions.downloadAsPdfFailed({ apiError: createApiError() }); - - const state: PostfachState = postfachReducer({ ...initialPostfachState, isDownloadPdfInProgress: true }, action); - - expect(state.isDownloadPdfInProgress).toBeFalsy(); - }) - }) - }) - - describe('attachmentList', () => { - - describe('on "loadAttachmentList" action', () => { - - it('should set loading', () => { - const postfachNachricht: PostfachMailResource = createPostfachMailResource(); - const action: PostfachNachrichtProps & TypedAction<string> = PostfachActions.loadAttachmentList({ postfachNachricht }); - - const state: PostfachState = postfachReducer(initialPostfachState, action); - - expect(state.attachmentList.loading).toBeTruthy(); - }) - }) - - describe('on "loadAttachmentListSuccess" action', () => { - - it('should create stateResource', () => { - const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); - const action: LoadBinaryFileListSuccessProps & TypedAction<string> = PostfachActions.loadAttachmentListSuccess({ binaryFileList }); - - const state: PostfachState = postfachReducer(initialPostfachState, action); - - expect(state.attachmentList.resource).toBe(binaryFileList); - }) - }) - - describe('on "loadAttachmentListFailure" action', () => { - - it('should create error stateResource', () => { - const apiError: ApiError = createApiError(); - const action: ApiErrorAction & TypedAction<string> = PostfachActions.loadAttachmentListFailure({ apiError }); - - const state: PostfachState = postfachReducer(initialPostfachState, action); - - expect(state.attachmentList.error).toBe(apiError); - }) - }) - - describe('on "clearAttachmentList" action', () => { - - it('should create empty stateResource', () => { - const action: TypedAction<string> = PostfachActions.clearAttachmentList(); - - const state: PostfachState = postfachReducer({ ...initialPostfachState, attachmentList: createStateResource(createBinaryFileListResource()) }, action); - - expect(state.attachmentList).toEqual(createEmptyStateResource()); - }) - }) - }) + describe('unknown action', () => { + it('should return current state', () => { + const state: PostfachState = postfachReducer(initialPostfachState, EMPTY_ACTION); + + expect(state).toBe(initialPostfachState); + }); + }); + + describe('isDownloadPdfInProgress', () => { + describe('on "startDownloadAsPdf" action', () => { + it('should set to true', () => { + const action: TypedAction<string> = PostfachActions.startDownloadAsPdf(); + + const state: PostfachState = postfachReducer(initialPostfachState, action); + + expect(state.isDownloadPdfInProgress).toBeTruthy(); + }); + }); + + describe('on "downloadAsPdfSuccess" action', () => { + it('should set to false', () => { + const action: TypedAction<string> = PostfachActions.downloadAsPdfSuccess(); + + const state: PostfachState = postfachReducer( + { ...initialPostfachState, isDownloadPdfInProgress: true }, + action, + ); + + expect(state.isDownloadPdfInProgress).toBeFalsy(); + }); + }); + + describe('on "downloadAsPdfFailed" action', () => { + it('should set to false', () => { + const action: ApiErrorAction & TypedAction<string> = PostfachActions.downloadAsPdfFailed({ + apiError: createApiError(), + }); + + const state: PostfachState = postfachReducer( + { ...initialPostfachState, isDownloadPdfInProgress: true }, + action, + ); + + expect(state.isDownloadPdfInProgress).toBeFalsy(); + }); + }); + }); + + describe('attachmentList', () => { + describe('on "loadAttachmentList" action', () => { + it('should set loading', () => { + const postfachNachricht: PostfachMailResource = createPostfachMailResource(); + const action: PostfachNachrichtProps & TypedAction<string> = + PostfachActions.loadAttachmentList({ postfachNachricht }); + + const state: PostfachState = postfachReducer(initialPostfachState, action); + + expect(state.attachmentList.loading).toBeTruthy(); + }); + }); + + describe('on "loadAttachmentListSuccess" action', () => { + it('should create stateResource', () => { + const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); + const action: LoadBinaryFileListSuccessProps & TypedAction<string> = + PostfachActions.loadAttachmentListSuccess({ binaryFileList }); + + const state: PostfachState = postfachReducer(initialPostfachState, action); + + expect(state.attachmentList.resource).toBe(binaryFileList); + }); + }); + + describe('on "loadAttachmentListFailure" action', () => { + it('should create error stateResource', () => { + const apiError: ApiError = createApiError(); + const action: ApiErrorAction & TypedAction<string> = + PostfachActions.loadAttachmentListFailure({ apiError }); + + const state: PostfachState = postfachReducer(initialPostfachState, action); + + expect(state.attachmentList.error).toBe(apiError); + }); + }); + + describe('on "clearAttachmentList" action', () => { + it('should create empty stateResource', () => { + const action: TypedAction<string> = PostfachActions.clearAttachmentList(); + + const state: PostfachState = postfachReducer( + { + ...initialPostfachState, + attachmentList: createStateResource(createBinaryFileListResource()), + }, + action, + ); + + expect(state.attachmentList).toEqual(createEmptyStateResource()); + }); + }); + }); }); diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.reducer.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.reducer.ts index 8d8f5757e786afeb193db777a519b394bc1fef2b..f8a3c891f123a042e46979b14746292780098595 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.reducer.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.reducer.ts @@ -21,8 +21,17 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { BinaryFileListResource, LoadBinaryFileListSuccessProps } from '@alfa-client/binary-file-shared'; -import { ApiErrorAction, StateResource, createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + BinaryFileListResource, + LoadBinaryFileListSuccessProps, +} from '@alfa-client/binary-file-shared'; +import { + ApiErrorAction, + StateResource, + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Action, ActionReducer, createReducer, on } from '@ngrx/store'; import * as PostfachActions from './postfach.actions'; @@ -30,51 +39,72 @@ import * as PostfachActions from './postfach.actions'; export const POSTFACH_FEATURE_KEY = 'PostfachState'; export interface PostfachPartialState { - readonly [POSTFACH_FEATURE_KEY]: PostfachState; + readonly [POSTFACH_FEATURE_KEY]: PostfachState; } export interface PostfachState { - isDownloadPdfInProgress: boolean; - attachmentList: StateResource<BinaryFileListResource>; + isDownloadPdfInProgress: boolean; + attachmentList: StateResource<BinaryFileListResource>; } export const initialPostfachState: PostfachState = { - isDownloadPdfInProgress: false, - attachmentList: createEmptyStateResource() + isDownloadPdfInProgress: false, + attachmentList: createEmptyStateResource(), }; const reducer: ActionReducer<PostfachState, Action> = createReducer( - initialPostfachState, - on(PostfachActions.startDownloadAsPdf, (state: PostfachState): PostfachState => ({ - ...state, - isDownloadPdfInProgress: true - })), - on(PostfachActions.downloadAsPdfSuccess, (state: PostfachState): PostfachState => ({ - ...state, - isDownloadPdfInProgress: false - })), - on(PostfachActions.downloadAsPdfFailed, (state: PostfachState): PostfachState => ({ - ...state, - isDownloadPdfInProgress: false - })), + initialPostfachState, + on( + PostfachActions.startDownloadAsPdf, + (state: PostfachState): PostfachState => ({ + ...state, + isDownloadPdfInProgress: true, + }), + ), + on( + PostfachActions.downloadAsPdfSuccess, + (state: PostfachState): PostfachState => ({ + ...state, + isDownloadPdfInProgress: false, + }), + ), + on( + PostfachActions.downloadAsPdfFailed, + (state: PostfachState): PostfachState => ({ + ...state, + isDownloadPdfInProgress: false, + }), + ), - on(PostfachActions.loadAttachmentList, (state: PostfachState): PostfachState => ({ - ...state, - attachmentList: { ...state.attachmentList, loading: true } - })), - on(PostfachActions.loadAttachmentListSuccess, (state: PostfachState, props: LoadBinaryFileListSuccessProps): PostfachState => ({ - ...state, - attachmentList: createStateResource(props.binaryFileList) - })), - on(PostfachActions.loadAttachmentListFailure, (state: PostfachState, props: ApiErrorAction): PostfachState => ({ - ...state, - attachmentList: createErrorStateResource(props.apiError) - })), - on(PostfachActions.clearAttachmentList, (state: PostfachState): PostfachState => ({ - ...state, - attachmentList: createEmptyStateResource() - })), + on( + PostfachActions.loadAttachmentList, + (state: PostfachState): PostfachState => ({ + ...state, + attachmentList: { ...state.attachmentList, loading: true }, + }), + ), + on( + PostfachActions.loadAttachmentListSuccess, + (state: PostfachState, props: LoadBinaryFileListSuccessProps): PostfachState => ({ + ...state, + attachmentList: createStateResource(props.binaryFileList), + }), + ), + on( + PostfachActions.loadAttachmentListFailure, + (state: PostfachState, props: ApiErrorAction): PostfachState => ({ + ...state, + attachmentList: createErrorStateResource(props.apiError), + }), + ), + on( + PostfachActions.clearAttachmentList, + (state: PostfachState): PostfachState => ({ + ...state, + attachmentList: createEmptyStateResource(), + }), + ), ); export function postfachReducer(state: PostfachState, action: Action): PostfachState { - return reducer(state, action); + return reducer(state, action); } diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.selectors.spec.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.selectors.spec.ts index 7b4cab61f02733d458bcc0df42b5ad26b726499f..5b2488c9ea142b0b46ce44bd9636f4094d3d9b5b 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.selectors.spec.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.selectors.spec.ts @@ -29,26 +29,30 @@ import { createBinaryFileListResource } from 'libs/binary-file-shared/test/binar import * as PostfachSelectors from './postfach.selectors'; describe('Postfach Selectors', () => { - let state: PostfachPartialState; + let state: PostfachPartialState; - const isDownloadPdfInProgress: boolean = true; - const attachmentList: StateResource<BinaryFileListResource> = createStateResource(createBinaryFileListResource()); + const isDownloadPdfInProgress: boolean = true; + const attachmentList: StateResource<BinaryFileListResource> = createStateResource( + createBinaryFileListResource(), + ); - beforeEach(() => { - state = { - PostfachState: { - ...initialPostfachState, - isDownloadPdfInProgress, - attachmentList - } - }; - }); + beforeEach(() => { + state = { + PostfachState: { + ...initialPostfachState, + isDownloadPdfInProgress, + attachmentList, + }, + }; + }); - it('should return isDownloadPdfInProgress', () => { - expect(PostfachSelectors.isDownloadPdfInProgress.projector(state.PostfachState)).toBe(isDownloadPdfInProgress); - }) + it('should return isDownloadPdfInProgress', () => { + expect(PostfachSelectors.isDownloadPdfInProgress.projector(state.PostfachState)).toBe( + isDownloadPdfInProgress, + ); + }); - it('should return attachmentList', () => { - expect(PostfachSelectors.attachmentList.projector(state.PostfachState)).toBe(attachmentList); - }) -}); \ No newline at end of file + it('should return attachmentList', () => { + expect(PostfachSelectors.attachmentList.projector(state.PostfachState)).toBe(attachmentList); + }); +}); diff --git a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.selectors.ts b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.selectors.ts index c6d6b6c490ea6bd60e2f47effcbfb3ff994752a0..7539f395bfeb6fdbca71c1198902045ddbbd926d 100644 --- a/alfa-client/libs/postfach-shared/src/lib/+state/postfach.selectors.ts +++ b/alfa-client/libs/postfach-shared/src/lib/+state/postfach.selectors.ts @@ -26,7 +26,14 @@ import { StateResource } from '@alfa-client/tech-shared'; import { MemoizedSelector, createFeatureSelector, createSelector } from '@ngrx/store'; import { POSTFACH_FEATURE_KEY, PostfachState } from './postfach.reducer'; -export const getPostfachState: MemoizedSelector<object, PostfachState> = createFeatureSelector<PostfachState>(POSTFACH_FEATURE_KEY); +export const getPostfachState: MemoizedSelector<object, PostfachState> = + createFeatureSelector<PostfachState>(POSTFACH_FEATURE_KEY); -export const isDownloadPdfInProgress: MemoizedSelector<PostfachState, boolean> = createSelector(getPostfachState, (state: PostfachState) => state.isDownloadPdfInProgress); -export const attachmentList: MemoizedSelector<PostfachState, StateResource<BinaryFileListResource>> = createSelector(getPostfachState, (state: PostfachState) => state.attachmentList); \ No newline at end of file +export const isDownloadPdfInProgress: MemoizedSelector<PostfachState, boolean> = createSelector( + getPostfachState, + (state: PostfachState) => state.isDownloadPdfInProgress, +); +export const attachmentList: MemoizedSelector< + PostfachState, + StateResource<BinaryFileListResource> +> = createSelector(getPostfachState, (state: PostfachState) => state.attachmentList); diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.spec.ts b/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.spec.ts index 894a98da6e8bcd9323ac749e15b078ec8852401d..daca33bf36b95cbd277807bcad9d016b0baf7011 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.spec.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { PostfachSharedModule } from './postfach-shared.module'; describe('PostfachSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [PostfachSharedModule] - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [PostfachSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(PostfachSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(PostfachSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.ts b/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.ts index b7fde9c57dd3239a5eb6c692807e2abfdb55a763..696d8e73eb29d91eda23cc828b950f0f2a615508 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach-shared.module.ts @@ -31,15 +31,12 @@ import { PostfachFacade } from './+state/postfach.facade'; import * as fromPostfach from './+state/postfach.reducer'; @NgModule({ - imports: [ - CommonModule, - CommandSharedModule, - StoreModule.forFeature( - fromPostfach.POSTFACH_FEATURE_KEY, - fromPostfach.postfachReducer - ), - EffectsModule.forFeature([PostfachEffects]) - ], - providers: [PostfachFacade], + imports: [ + CommonModule, + CommandSharedModule, + StoreModule.forFeature(fromPostfach.POSTFACH_FEATURE_KEY, fromPostfach.postfachReducer), + EffectsModule.forFeature([PostfachEffects]), + ], + providers: [PostfachFacade], }) -export class PostfachSharedModule { } +export class PostfachSharedModule {} diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.linkrel.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.linkrel.ts index c758253ba8469c4473b1f84475fd0b31c16dbcf7..54aea94c093d9733165f448834f89d63625631e3 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.linkrel.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.linkrel.ts @@ -22,16 +22,16 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum PostfachMailListLinkRel { - POSTFACH_MAIL_LIST = 'postfachMailList', - SEND_POSTFACH_MAIL = 'sendPostfachMail', - UPLOAD_ATTACHMENT = 'uploadAttachment', - RESET_HAS_NEW_POSTFACH_NACHRICHT = "resetHasNewPostfachNachricht" + POSTFACH_MAIL_LIST = 'postfachMailList', + SEND_POSTFACH_MAIL = 'sendPostfachMail', + UPLOAD_ATTACHMENT = 'uploadAttachment', + RESET_HAS_NEW_POSTFACH_NACHRICHT = 'resetHasNewPostfachNachricht', } export enum PostfachMailLinkRel { - CREATED_BY = 'createdBy', - RESEND_POSTFACH_MAIL = 'resendPostfachMail', - ATTACHMENTS = 'attachments', - EDIT = 'edit', - SEND = 'send' + CREATED_BY = 'createdBy', + RESEND_POSTFACH_MAIL = 'resendPostfachMail', + ATTACHMENTS = 'attachments', + EDIT = 'edit', + SEND = 'send', } diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.message-code.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.message-code.ts index 057c14f9bd34065acf0cfcdaaf68f65d359c91c8..36043a9b2b15c5fa1ffb26c50cfe1e5c2d02b993 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.message-code.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.message-code.ts @@ -22,11 +22,13 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum PostfachNachrichtMessageCode { - PROCESSING_FAILED = 'postfachnachricht.server.processing_failed', - CONNECTION_FAILED = 'postfachnachricht.server.connection_failed' + PROCESSING_FAILED = 'postfachnachricht.server.processing_failed', + CONNECTION_FAILED = 'postfachnachricht.server.connection_failed', } export const postfachNachrichtMessageCodeMessages = { - [PostfachNachrichtMessageCode.CONNECTION_FAILED]: 'Verbindungsfehler: Die Verbindung zum Zielserver des Osi-Postfachs ist nicht zustandegekommen.', - [PostfachNachrichtMessageCode.PROCESSING_FAILED]: 'Fehlerhafte Verarbeitung: Die Nachricht wurde an das Osi-Postfach geschickt, konnte dort aber nicht richtig verarbeitet werden.' -} \ No newline at end of file + [PostfachNachrichtMessageCode.CONNECTION_FAILED]: + 'Verbindungsfehler: Die Verbindung zum Zielserver des Osi-Postfachs ist nicht zustandegekommen.', + [PostfachNachrichtMessageCode.PROCESSING_FAILED]: + 'Fehlerhafte Verarbeitung: Die Nachricht wurde an das Osi-Postfach geschickt, konnte dort aber nicht richtig verarbeitet werden.', +}; diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.message.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.message.ts index d6936887c130da2ccc569e687c4b79a0faaba2af..77af620a15bb9c13f5a66f25148c764b9d710a5e 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.message.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.message.ts @@ -22,6 +22,6 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum PostfachMessages { - SEND_SUCCESSFUL = 'Die Nachricht wurde erfolgreich versendet.', - SEND_FAILED = 'Die Nachricht konnte nicht versendet werden' -} \ No newline at end of file + SEND_SUCCESSFUL = 'Die Nachricht wurde erfolgreich versendet.', + SEND_FAILED = 'Die Nachricht konnte nicht versendet werden', +} diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.model.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.model.ts index cc38e795608888bf3ae9c25a3545291ee0aecc64..e0da72cebbd87689172262fba7a0393652b18302 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.model.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.model.ts @@ -28,59 +28,59 @@ import { Resource, ResourceUri } from '@ngxp/rest'; import { PostfachNachrichtMessageCode } from './postfach.message-code'; export interface PostfachMail { - subject: string; - createdAt: Date; - direction: Direction; - mailBody: string; - replyOption: ReplyOption; - sentAt: Date; - sentSuccessful: boolean; - messageCode: PostfachNachrichtMessageCode; - attachments: ResourceUri[] | string; + subject: string; + createdAt: Date; + direction: Direction; + mailBody: string; + replyOption: ReplyOption; + sentAt: Date; + sentSuccessful: boolean; + messageCode: PostfachNachrichtMessageCode; + attachments: ResourceUri[] | string; } export enum Direction { - IN = 'IN', - OUT = 'OUT' + IN = 'IN', + OUT = 'OUT', } export enum ReplyOption { - POSSIBLE = 'POSSIBLE', - MANDATORY = 'MANDATORY', - FORBIDDEN = 'FORBIDDEN' + POSSIBLE = 'POSSIBLE', + MANDATORY = 'MANDATORY', + FORBIDDEN = 'FORBIDDEN', } export enum PostfachOrder { - SEND_POSTFACH_NACHRICHT = 'SEND_POSTFACH_NACHRICHT', - RESEND_POSTFACH_MAIL = 'RESEND_POSTFACH_MAIL' + SEND_POSTFACH_NACHRICHT = 'SEND_POSTFACH_NACHRICHT', + RESEND_POSTFACH_MAIL = 'RESEND_POSTFACH_MAIL', } export interface CreatePostfachMailCommand extends CreateCommand { - order: PostfachOrder; + order: PostfachOrder; } export interface PostfachMailResource extends Resource, PostfachMail {} export interface PostfachMailListResource extends ListResource { - features: Features; + features: Features; } export enum PostfachNachrichtenCount { - NONE, - SINGLE, - MULTIPLE + NONE, + SINGLE, + MULTIPLE, } -export interface PostfachDialogComponent { } +export interface PostfachDialogComponent {} //TODO Rename PostfachNachrichtDialogData export interface PostfachMailFormDialogData extends FixedDialogData { - empfaenger: string, - postfachMailListStateResource?: StateResource<PostfachMailListResource>, - postfachNachricht?: PostfachMailResource, - + empfaenger: string; + postfachMailListStateResource?: StateResource<PostfachMailListResource>; + postfachNachricht?: PostfachMailResource; } -export interface Features { //TODO Rename to PostfachFeatures - reply: boolean; -} \ No newline at end of file +export interface Features { + //TODO Rename to PostfachFeatures + reply: boolean; +} diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.repository.spec.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.repository.spec.ts index 808a32aa945f6cd22519c3e836144a2527ef8332..171127841cfe5913252a67586c28cd97ef1d6651 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.repository.spec.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.repository.spec.ts @@ -32,59 +32,62 @@ import { PostfachMailListResource } from './postfach.model'; import { PostfachRepository } from './postfach.repository'; describe('PostfachRepository', () => { + let repository: PostfachRepository; + const resourceFactory = mock(ResourceFactory); + const resourceWrapper = { get: jest.fn(), put: jest.fn() }; - let repository: PostfachRepository; - const resourceFactory = mock(ResourceFactory); - const resourceWrapper = { get: jest.fn(), put: jest.fn() }; + beforeEach(() => { + resourceFactory.from.mockReturnValue(resourceWrapper); - beforeEach(() => { - resourceFactory.from.mockReturnValue(resourceWrapper); + repository = new PostfachRepository(useFromMock(resourceFactory)); + }); - repository = new PostfachRepository(useFromMock(resourceFactory)); - }) + describe('loadPostfachMailList', () => { + const postfachMailListResource: PostfachMailListResource = createPostfachMailListResource(); + const vorgang: VorgangResource = createVorgangResource(); - describe('loadPostfachMailList', () => { - const postfachMailListResource: PostfachMailListResource = createPostfachMailListResource(); - const vorgang: VorgangResource = createVorgangResource(); + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: postfachMailListResource })); + }); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: postfachMailListResource })); - }) + it('should call resourceFactory with resource', () => { + repository.loadPostfachMailList(vorgang); - it('should call resourceFactory with resource', () => { - repository.loadPostfachMailList(vorgang); + expect(resourceFactory.from).toHaveBeenCalledWith(vorgang); + }); - expect(resourceFactory.from).toHaveBeenCalledWith(vorgang); - }) + it('should call resourceWrapper with link', () => { + repository.loadPostfachMailList(vorgang); - it('should call resourceWrapper with link', () => { - repository.loadPostfachMailList(vorgang); + expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangHeaderLinkRel.POSTFACH_MAILS); + }); - expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangHeaderLinkRel.POSTFACH_MAILS) - }) + it('should return result', () => { + const result = repository.loadPostfachMailList(vorgang); - it('should return result', () => { - const result = repository.loadPostfachMailList(vorgang); + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: postfachMailListResource })); + }); + }); - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: postfachMailListResource })); - }) - }) + describe('resetHasNewPostfachNachrichten', () => { + const postfachMailListResource: PostfachMailListResource = createPostfachMailListResource([ + PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT, + ]); - describe('resetHasNewPostfachNachrichten', () => { + it('should call resourceFactory with resource', () => { + repository.resetHasNewPostfachNachrichten(postfachMailListResource); - const postfachMailListResource: PostfachMailListResource = createPostfachMailListResource([PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT]); + expect(resourceFactory.from).toHaveBeenCalledWith(postfachMailListResource); + }); - it('should call resourceFactory with resource', () => { - repository.resetHasNewPostfachNachrichten(postfachMailListResource); + it('should call resourceWrapper with link', () => { + repository.resetHasNewPostfachNachrichten(postfachMailListResource); - expect(resourceFactory.from).toHaveBeenCalledWith(postfachMailListResource); - }) - - it('should call resourceWrapper with link', () => { - repository.resetHasNewPostfachNachrichten(postfachMailListResource); - - expect(resourceWrapper.put).toHaveBeenCalledWith(PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT, { hasNewPostfachNachricht: false }) - }) - }) -}) \ No newline at end of file + expect(resourceWrapper.put).toHaveBeenCalledWith( + PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT, + { hasNewPostfachNachricht: false }, + ); + }); + }); +}); diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.repository.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.repository.ts index f1981be32ece8c1d4f51c13ae0362f60a91b2606..d602af564b3f1ffe868c4e8e96dc0f687018ce99 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.repository.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.repository.ts @@ -30,14 +30,19 @@ import { PostfachMailListResource } from './postfach.model'; @Injectable({ providedIn: 'root' }) export class PostfachRepository { + constructor(private resourceFactory: ResourceFactory) {} - constructor(private resourceFactory: ResourceFactory) { } + public loadPostfachMailList(vorgang: VorgangResource): Observable<PostfachMailListResource> { + return this.resourceFactory.from(vorgang).get(VorgangHeaderLinkRel.POSTFACH_MAILS); + } - public loadPostfachMailList(vorgang: VorgangResource): Observable<PostfachMailListResource> { - return this.resourceFactory.from(vorgang).get(VorgangHeaderLinkRel.POSTFACH_MAILS); - } - - public resetHasNewPostfachNachrichten(postfachNachrichtenList: PostfachMailListResource): Observable<unknown> { - return this.resourceFactory.from(postfachNachrichtenList).put(PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT, { hasNewPostfachNachricht: false }); - } -} \ No newline at end of file + public resetHasNewPostfachNachrichten( + postfachNachrichtenList: PostfachMailListResource, + ): Observable<unknown> { + return this.resourceFactory + .from(postfachNachrichtenList) + .put(PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT, { + hasNewPostfachNachricht: false, + }); + } +} diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.service.spec.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.service.spec.ts index 7fcfea4331761cbabc49273ce2f3f3690ecaed08..1d00b7d41af9f9851a34f07c3035251d140eeb2c 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.service.spec.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.service.spec.ts @@ -22,19 +22,37 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { MatDialog } from '@angular/material/dialog'; -import { BinaryFileListResource, BinaryFileResource, BinaryFileService } from '@alfa-client/binary-file-shared'; +import { + BinaryFileListResource, + BinaryFileResource, + BinaryFileService, +} from '@alfa-client/binary-file-shared'; import { CommandResource, CommandService } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { SnackBarService } from '@alfa-client/ui'; import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; -import { createBinaryFileListResource, createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; +import { + createBinaryFileListResource, + createBinaryFileResource, +} from 'libs/binary-file-shared/test/binary-file'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; -import { createCommandErrorResource, createCommandResource } from 'libs/command-shared/test/command'; +import { + createCommandErrorResource, + createCommandResource, +} from 'libs/command-shared/test/command'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { BehaviorSubject, of } from 'rxjs'; -import { createPostfachMail, createPostfachMailListResource, createPostfachMailResource } from '../../test/postfach'; +import { + createPostfachMail, + createPostfachMailListResource, + createPostfachMailResource, +} from '../../test/postfach'; import { PostfachFacade } from './+state/postfach.facade'; import { PostfachMailLinkRel, PostfachMailListLinkRel } from './postfach.linkrel'; import { PostfachMessages } from './postfach.message'; @@ -44,547 +62,577 @@ import { PostfachService } from './postfach.service'; import { createSendPostfachMailCommand } from './postfach.util'; describe('PostfachService', () => { - let service: PostfachService; + let service: PostfachService; + + let repository: Mock<PostfachRepository>; + const commandService: Mock<CommandService> = mock(CommandService); + const navigationService: Mock<NavigationService> = mock(NavigationService); + const vorgangService: Mock<VorgangService> = mock(VorgangService); + const snackbarService: Mock<SnackBarService> = mock(SnackBarService); + const dialog: Mock<MatDialog> = <Mock<MatDialog>>{ closeAll: jest.fn() }; + const binaryFileService: Mock<BinaryFileService> = mock(BinaryFileService); + const postfachFacade: Mock<PostfachFacade> = mock(PostfachFacade); + + const urlChangedParams = {}; + + beforeEach(() => { + navigationService.urlChanged = jest.fn(); + navigationService.urlChanged.mockReturnValue(of(urlChangedParams)); + + repository = mock(PostfachRepository); - let repository: Mock<PostfachRepository>; - const commandService: Mock<CommandService> = mock(CommandService); - const navigationService: Mock<NavigationService> = mock(NavigationService); - const vorgangService: Mock<VorgangService> = mock(VorgangService); - const snackbarService: Mock<SnackBarService> = mock(SnackBarService); - const dialog: Mock<MatDialog> = <Mock<MatDialog>>{ closeAll: jest.fn() }; - const binaryFileService: Mock<BinaryFileService> = mock(BinaryFileService); - const postfachFacade: Mock<PostfachFacade> = mock(PostfachFacade); + service = new PostfachService( + useFromMock(repository), + useFromMock(commandService), + useFromMock(navigationService), + useFromMock(vorgangService), + useFromMock(snackbarService), + useFromMock(dialog), + useFromMock(binaryFileService), + useFromMock(postfachFacade), + ); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + describe('send message', () => { + const postfachMail: PostfachMail = createPostfachMail(); + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + + beforeEach(() => { + commandService.createCommand.mockReturnValue(of(commandStateResource)); + vorgangService.getPendingSendPostfachMailCommand.mockReturnValue(of(commandStateResource)); + }); - const urlChangedParams = {}; + it('should call vorgang service and set command on loading', () => { + service.sendMail(postfachMail); + + expect(vorgangService.setPendingSendPostfachMailSingleCommandLoading).toHaveBeenCalled(); + }); - beforeEach(() => { - navigationService.urlChanged = jest.fn(); - navigationService.urlChanged.mockReturnValue(of(urlChangedParams)); + it('should call command service', () => { + service.sendMail(postfachMail); - repository = mock(PostfachRepository); + expect(commandService.createCommand).toHaveBeenCalled(); + }); + + it('should call vorgang service and get command', () => { + service.sendMail(postfachMail); + + expect(vorgangService.getPendingSendPostfachMailCommand).toHaveBeenCalled(); + }); - service = new PostfachService( - useFromMock(repository), - useFromMock(commandService), - useFromMock(navigationService), - useFromMock(vorgangService), - useFromMock(snackbarService), - useFromMock(dialog), - useFromMock(binaryFileService), - useFromMock(postfachFacade)); - }); + describe('reload postfach list', () => { + beforeEach(() => { + service.refreshPostfachMailList = jest.fn(); + }); + + it('should execute on command is done', () => { + const commandStateResource: StateResource<CommandResource> = createStateResource( + createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), + ); + commandService.createCommand.mockReturnValue(of(commandStateResource)); - it('should be created', () => { - expect(service).toBeTruthy(); - }); + service.sendMail(postfachMail); + + expect(service.refreshPostfachMailList).toHaveBeenCalledWith(commandStateResource); + }); - describe('send message', () => { + it('should not execute on pending command', () => { + commandService.createCommand.mockReturnValue( + of(createStateResource(createCommandResource([CommandLinkRel.UPDATE]))), + ); + + service.sendMail(postfachMail); - const postfachMail: PostfachMail = createPostfachMail(); - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); + expect(service.refreshPostfachMailList).not.toHaveBeenCalled(); + }); + }); + }); - beforeEach(() => { - commandService.createCommand.mockReturnValue(of(commandStateResource)); - vorgangService.getPendingSendPostfachMailCommand.mockReturnValue(of(commandStateResource)); - }) + describe('sendExistingNachricht', () => { + const postfachNachricht: PostfachMailResource = createPostfachMailResource(); + const nachricht: PostfachMail = createPostfachMail(); - it('should call vorgang service and set command on loading', () => { - service.sendMail(postfachMail); + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + + it('should call doSendNachricht', () => { + service.doSendNachricht = jest.fn(); + commandService.createCommand.mockReturnValue(of(commandStateResource)); + vorgangService.getPendingSendPostfachMailCommand.mockReturnValue(of(commandStateResource)); + + service.sendExistingMail(postfachNachricht, nachricht); - expect(vorgangService.setPendingSendPostfachMailSingleCommandLoading).toHaveBeenCalled(); - }) + expect(service.doSendNachricht).toHaveBeenCalledWith( + postfachNachricht, + PostfachMailLinkRel.SEND, + createSendPostfachMailCommand(nachricht), + ); + }); + }); - it('should call command service', () => { - service.sendMail(postfachMail); + describe('resend message', () => { + const postfachMailResource: PostfachMailResource = createPostfachMailResource(); - expect(commandService.createCommand).toHaveBeenCalled(); - }) + beforeEach(() => { + service.handleSendPostfachMailIsDone = jest.fn(); + + commandService.createCommand.mockReturnValue( + of(createStateResource(createCommandResource())), + ); + vorgangService.getPendingSendPostfachMailCommand.mockReturnValue( + of(createStateResource(createCommandResource())), + ); + }); - it('should call vorgang service and get command', () => { - service.sendMail(postfachMail); + it('should call vorgang service and set command on loading', () => { + service.resendMail(postfachMailResource); - expect(vorgangService.getPendingSendPostfachMailCommand).toHaveBeenCalled(); - }) + expect(vorgangService.setPendingSendPostfachMailSingleCommandLoading).toHaveBeenCalled(); + }); - describe('reload postfach list', () => { + it('should call command service', () => { + service.resendMail(postfachMailResource); - beforeEach(() => { - service.refreshPostfachMailList = jest.fn(); - }) + expect(commandService.createCommand).toHaveBeenCalled(); + }); - it('should execute on command is done', () => { - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE])); - commandService.createCommand.mockReturnValue(of(commandStateResource)); + it('should call vorgang service and get command', () => { + service.resendMail(postfachMailResource); - service.sendMail(postfachMail); + expect(vorgangService.getPendingSendPostfachMailCommand).toHaveBeenCalled(); + }); - expect(service.refreshPostfachMailList).toHaveBeenCalledWith(commandStateResource); - }) + it('should NOT call handleSendPostfachMailIsDone if command is pending', () => { + commandService.createCommand.mockReturnValue( + of(createStateResource(createCommandResource([CommandLinkRel.UPDATE]))), + ); + service.resendMail(postfachMailResource); - it('should not execute on pending command', () => { - commandService.createCommand.mockReturnValue(of(createStateResource(createCommandResource([CommandLinkRel.UPDATE])))); + expect(service.handleSendPostfachMailIsDone).not.toHaveBeenCalled(); + }); - service.sendMail(postfachMail); + it('should call handleSendPostfachMailIsDone if command is done', () => { + const commandResponse: StateResource<CommandResource> = createStateResource( + createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), + ); + commandService.createCommand.mockReturnValue(of(commandResponse)); - expect(service.refreshPostfachMailList).not.toHaveBeenCalled(); - }) - }) - }) + service.resendMail(postfachMailResource); - describe('sendExistingNachricht', () => { + expect(service.handleSendPostfachMailIsDone).toHaveBeenCalledWith(commandResponse); + }); + }); - const postfachNachricht: PostfachMailResource = createPostfachMailResource(); - const nachricht: PostfachMail = createPostfachMail(); + describe('handleSendNachrichtCommand', () => { + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); + beforeEach(() => { + service.commandIsDone = jest.fn(); + }); - it('should call doSendNachricht', () => { - service.doSendNachricht = jest.fn(); - commandService.createCommand.mockReturnValue(of(commandStateResource)); - vorgangService.getPendingSendPostfachMailCommand.mockReturnValue(of(commandStateResource)); + it('should call vorgang service', () => { + service.handleSendNachrichtCommand(commandStateResource); - service.sendExistingMail(postfachNachricht, nachricht); + expect(vorgangService.setPendingSendPostfachMailCommand).toHaveBeenCalledWith( + commandStateResource, + ); + }); - expect(service.doSendNachricht).toHaveBeenCalledWith(postfachNachricht, PostfachMailLinkRel.SEND, createSendPostfachMailCommand(nachricht)); - }) - }) + it('should call commandIsDone', () => { + service.handleSendNachrichtCommand(commandStateResource); - describe('resend message', () => { + expect(service.commandIsDone).toHaveBeenCalledWith(commandStateResource); + }); + }); - const postfachMailResource: PostfachMailResource = createPostfachMailResource(); + describe('commandIsDone', () => { + beforeEach(() => { + service.handleSendPostfachMailIsDone = jest.fn(); + }); - beforeEach(() => { - service.handleSendPostfachMailIsDone = jest.fn(); + it('should call handleSendPostfachMailIsDone', () => { + const commandStateResource: StateResource<CommandResource> = createStateResource( + createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), + ); - commandService.createCommand.mockReturnValue(of(createStateResource(createCommandResource()))); - vorgangService.getPendingSendPostfachMailCommand.mockReturnValue(of(createStateResource(createCommandResource()))); - }) + service.commandIsDone(commandStateResource); - it('should call vorgang service and set command on loading', () => { - service.resendMail(postfachMailResource); + expect(service.handleSendPostfachMailIsDone).toHaveBeenCalledWith(commandStateResource); + }); - expect(vorgangService.setPendingSendPostfachMailSingleCommandLoading).toHaveBeenCalled(); - }) + describe('on command is done', () => { + it('should call snackbar service', () => { + const commandStateResource: StateResource<CommandResource> = createStateResource({ + ...createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), + errorMessage: null, + }); - it('should call command service', () => { - service.resendMail(postfachMailResource); + service.commandIsDone(commandStateResource); - expect(commandService.createCommand).toHaveBeenCalled(); - }) + expect(snackbarService.show).toHaveBeenCalledWith( + commandStateResource.resource, + PostfachMessages.SEND_SUCCESSFUL, + ); + }); + }); - it('should call vorgang service and get command', () => { - service.resendMail(postfachMailResource); + describe('on command is done with error', () => { + it('should call snackbar service', () => { + const commandStateResource: StateResource<CommandResource> = createStateResource( + createCommandErrorResource([CommandLinkRel.EFFECTED_RESOURCE]), + ); - expect(vorgangService.getPendingSendPostfachMailCommand).toHaveBeenCalled(); - }) + service.commandIsDone(commandStateResource); - it('should NOT call handleSendPostfachMailIsDone if command is pending', () => { - commandService.createCommand.mockReturnValue(of(createStateResource(createCommandResource([CommandLinkRel.UPDATE])))); - service.resendMail(postfachMailResource); + expect(snackbarService.showError).toHaveBeenCalledWith(PostfachMessages.SEND_FAILED); + }); + }); + }); - expect(service.handleSendPostfachMailIsDone).not.toHaveBeenCalled(); - }) + describe('listenToNavigation', () => { + it('should call usnsubcribeToNavigation', () => { + service.listenToNavigation(); - it('should call handleSendPostfachMailIsDone if command is done', () => { - const commandResponse: StateResource<CommandResource> = createStateResource(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE])); - commandService.createCommand.mockReturnValue(of(commandResponse)); + expect(navigationService.urlChanged).toHaveBeenCalled(); + }); - service.resendMail(postfachMailResource); + it('should call navigation service', () => { + service.unsubscribeToNavigation = jest.fn(); - expect(service.handleSendPostfachMailIsDone).toHaveBeenCalledWith(commandResponse); - }) - }) + service.listenToNavigation(); - describe('handleSendNachrichtCommand', () => { + expect(service.unsubscribeToNavigation).toHaveBeenCalled(); + }); - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); + it('should call onNavigation', () => { + service.onNavigation = jest.fn(); - beforeEach(() => { - service.commandIsDone = jest.fn(); - }) + service.listenToNavigation(); - it('should call vorgang service', () => { - service.handleSendNachrichtCommand(commandStateResource); + expect(service.onNavigation).toHaveBeenCalledWith(urlChangedParams); + }); + }); - expect(vorgangService.setPendingSendPostfachMailCommand).toHaveBeenCalledWith(commandStateResource); - }) + describe('onNavigation', () => { + describe('to vorgang list', () => { + beforeEach(() => { + service.setPollingFalse = jest.fn(); + service.clearPostfachMailList = jest.fn(); + service.unsubscribe = jest.fn(); + }); - it('should call commandIsDone', () => { - service.handleSendNachrichtCommand(commandStateResource); + it('should set polling false', () => { + service.onNavigation({}); - expect(service.commandIsDone).toHaveBeenCalledWith(commandStateResource); - }) - }) + expect(service.setPollingFalse).toHaveBeenCalled(); + }); - describe('commandIsDone', () => { + it('should call clearPostfachMailList', () => { + service.onNavigation({}); - beforeEach(() => { - service.handleSendPostfachMailIsDone = jest.fn(); - }) + expect(service.clearPostfachMailList).toHaveBeenCalled(); + }); - it('should call handleSendPostfachMailIsDone', () => { - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE])); + it('should call closeOpenDialogs', () => { + service.onNavigation({}); - service.commandIsDone(commandStateResource); + expect(dialog.closeAll).toHaveBeenCalled(); + }); - expect(service.handleSendPostfachMailIsDone).toHaveBeenCalledWith(commandStateResource); - }) + it('should call unsubscribe', () => { + service.onNavigation({}); - describe('on command is done', () => { + expect(service.unsubscribe).toHaveBeenCalled(); + }); + }); - it('should call snackbar service', () => { - const commandStateResource: StateResource<CommandResource> = createStateResource({ ...createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), errorMessage: null }); + describe('to vorgang detail page', () => { + it('should set postfach nachrichten list to reload', () => { + service.postfachMailList$.next(createEmptyStateResource()); - service.commandIsDone(commandStateResource); + service.onNavigation({ vorgangWithEingangUrl: 'X' }); - expect(snackbarService.show).toHaveBeenCalledWith(commandStateResource.resource, PostfachMessages.SEND_SUCCESSFUL); - }) + expect(service.postfachMailList$.value.reload).toEqual(true); + }); + }); - }) + describe('to postfach page', () => { + beforeEach(() => { + service.resetHasNewPostfachNachrichten = jest.fn(); + navigationService.isPostfachPage.mockReturnValue(true); + }); - describe('on command is done with error', () => { + it('should call navigationService', () => { + service.onNavigation({}); - it('should call snackbar service', () => { - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandErrorResource([CommandLinkRel.EFFECTED_RESOURCE])); + expect(navigationService.isPostfachPage).toHaveBeenCalled(); + }); - service.commandIsDone(commandStateResource); + it('should reset hasNewPostfachNachrichten', () => { + navigationService.isPostfachPage.mockReturnValue(true); - expect(snackbarService.showError).toHaveBeenCalledWith(PostfachMessages.SEND_FAILED); - }) - }) - }) + service.onNavigation({}); - describe('listenToNavigation', () => { + expect(service.resetHasNewPostfachNachrichten).toHaveBeenCalled(); + }); + }); + }); - it('should call usnsubcribeToNavigation', () => { - service.listenToNavigation(); + describe('getPendingSendPostfachMailCommand', () => { + beforeEach(() => { + service.unsubscribe = jest.fn(); + service.pollSendPostfachMailCommand = jest.fn(); - expect(navigationService.urlChanged).toHaveBeenCalled(); - }) + commandService.pollCommand.mockReturnValue(of(createStateResource(createCommandResource()))); + vorgangService.getPendingSendPostfachMailCommand.mockReturnValue( + of(createStateResource(createCommandResource())), + ); + }); - it('should call navigation service', () => { - service.unsubscribeToNavigation = jest.fn(); + it('should call navigation service', () => { + service.getPendingSendPostfachMailCommand(); - service.listenToNavigation(); + expect(navigationService.urlChanged).toHaveBeenCalled(); + }); + }); - expect(service.unsubscribeToNavigation).toHaveBeenCalled(); - }) + describe('resetHasNewPostfachNachrichten', () => { + const postfachListNachrichtenResource: PostfachMailListResource = + createPostfachMailListResource(); - it('should call onNavigation', () => { - service.onNavigation = jest.fn(); + it('should call doResetHasNewPostfachNachrichten', () => { + service.getPostfachMailListByVorgang = jest.fn(); + service.doResetHasNewPostfachNachrichten = jest.fn(); + (<any>service.getPostfachMailListByVorgang).mockReturnValue( + of(postfachListNachrichtenResource), + ); - service.listenToNavigation(); + service.resetHasNewPostfachNachrichten(); - expect(service.onNavigation).toHaveBeenCalledWith(urlChangedParams); - }) - }) + expect(service.doResetHasNewPostfachNachrichten).toHaveBeenCalled(); + }); + }); - describe('onNavigation', () => { + describe('doResetHasNewPostfachNachrichten', () => { + describe('on existing link', () => { + const postfachNachrichtenListResource: PostfachMailListResource = + createPostfachMailListResource([PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT]); - describe('to vorgang list', () => { + beforeEach(() => { + service.postfachMailList$.next(createStateResource(postfachNachrichtenListResource)); + repository.resetHasNewPostfachNachrichten.mockReturnValue( + of(postfachNachrichtenListResource), + ); + }); - beforeEach(() => { - service.setPollingFalse = jest.fn(); - service.clearPostfachMailList = jest.fn(); - service.unsubscribe = jest.fn(); - }) + it('should call repository if link exists', () => { + service.doResetHasNewPostfachNachrichten(); - it('should set polling false', () => { - service.onNavigation({}); + expect(repository.resetHasNewPostfachNachrichten).toHaveBeenCalledWith( + postfachNachrichtenListResource, + ); + }); + }); - expect(service.setPollingFalse).toHaveBeenCalled(); - }) + it('should NOT call repository if link not exists', () => { + const postfachNachrichtenListResource: PostfachMailListResource = + createPostfachMailListResource(); + service.postfachMailList$.next(createStateResource(postfachNachrichtenListResource)); - it('should call clearPostfachMailList', () => { - service.onNavigation({}); + service.doResetHasNewPostfachNachrichten(); - expect(service.clearPostfachMailList).toHaveBeenCalled(); - }) + expect(repository.resetHasNewPostfachNachrichten).not.toHaveBeenCalled(); + }); + }); - it('should call closeOpenDialogs', () => { - service.onNavigation({}); + describe('getPostfachMailListByVorgang', () => { + const postfachMailList: PostfachMailListResource = createPostfachMailListResource(); - expect(dialog.closeAll).toHaveBeenCalled(); - }) + beforeEach(() => { + repository.loadPostfachMailList.mockReturnValue(of(postfachMailList)); + service.setPostfachMailListLoading = jest.fn(); + service.setPostfachMailList = jest.fn(); + vorgangService.getVorgangWithEingang.mockReturnValue( + of(createStateResource(createVorgangWithEingangResource())), + ); + service.postfachMailList$.next(createEmptyStateResource()); + }); - it('should call unsubscribe', () => { - service.onNavigation({}); + it('should set loading to true', () => { + service.getPostfachMailListByVorgang(); - expect(service.unsubscribe).toHaveBeenCalled(); - }) - }) + expect(service.setPostfachMailListLoading).toHaveBeenCalled(); + }); - describe('to vorgang detail page', () => { + it('should call vorgang service', () => { + service.getPostfachMailListByVorgang(); - it('should set postfach nachrichten list to reload', () => { - service.postfachMailList$.next(createEmptyStateResource()); + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); - service.onNavigation({ 'vorgangWithEingangUrl': 'X' }); + it('should call repository', () => { + service.getPostfachMailListByVorgang().subscribe(); + + expect(repository.loadPostfachMailList).toHaveBeenCalled(); + }); + + it('should set loading to false', () => { + service.getPostfachMailListByVorgang(); + + expect(service.setPostfachMailList).toHaveBeenCalled(); + }); + }); + + describe('handleSendPostfachMailIsDone', () => { + const stateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + + beforeEach(() => { + service.setPollingFalse = jest.fn(); + service.setPostfachMailList = jest.fn(); + + commandService.getEffectedResource.mockReturnValue(of(createCommandResource())); + }); + + it('should call command service to get effected resource', () => { + service.handleSendPostfachMailIsDone(stateResource); + + expect(commandService.getEffectedResource).toHaveBeenCalledWith(stateResource.resource); + }); - expect(service.postfachMailList$.value.reload).toEqual(true); - }) - }); + it('should set postfachMailList', () => { + service.handleSendPostfachMailIsDone(stateResource); - describe('to postfach page', () => { + expect(service.setPostfachMailList).toHaveBeenCalled(); + }); - beforeEach(() => { - service.resetHasNewPostfachNachrichten = jest.fn(); - navigationService.isPostfachPage.mockReturnValue(true); - }) + it('should set polling to false', () => { + service.handleSendPostfachMailIsDone(stateResource); - it('should call navigationService', () => { - service.onNavigation({}); + expect(service.setPollingFalse).toHaveBeenCalled(); + }); + }); - expect(navigationService.isPostfachPage).toHaveBeenCalled(); - }) + describe('loadAttachments', () => { + const postfachNachricht: PostfachMailResource = createPostfachMailResource(); + const fileListStateResource: StateResource<BinaryFileListResource> = createStateResource( + createBinaryFileListResource(), + ); + + beforeEach(() => { + binaryFileService.getFiles.mockReturnValue(of(fileListStateResource)); + }); - it('should reset hasNewPostfachNachrichten', () => { - navigationService.isPostfachPage.mockReturnValue(true); + it('should call binaryFile service with resource', () => { + service.loadAttachments(postfachNachricht); + + expect(binaryFileService.getFiles).toHaveBeenCalledWith( + postfachNachricht, + PostfachMailLinkRel.ATTACHMENTS, + ); + }); + }); + + describe('isDownloadPdfInProgress', () => { + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + it('should call facade to download pdf', (done) => { + vorgangService.getVorgangWithEingang.mockReturnValue(of(createStateResource(vorgang))); + postfachFacade.isDownloadPdfInProgress.mockReturnValue(of(true)); + + service.isDownloadPdfInProgress().subscribe(() => { + expect(postfachFacade.downloadPdf).toHaveBeenCalledWith(vorgang); + done(); + }); + }); + + describe('combine latest', () => { + beforeEach(() => { + vorgangService.getVorgangWithEingang.mockReturnValue(of(vorgang)); + postfachFacade.isDownloadPdfInProgress = jest.fn().mockReturnValue(true); + }); + + it('should call facade to get isDownloadPdfInProgress', () => { + service.isDownloadPdfInProgress(); + + expect(postfachFacade.isDownloadPdfInProgress).toHaveBeenCalled(); + }); - service.onNavigation({}); + it('should call vorgang service to get vorgang', () => { + service.isDownloadPdfInProgress(); - expect(service.resetHasNewPostfachNachrichten).toHaveBeenCalled(); - }) - }) - }) - - describe('getPendingSendPostfachMailCommand', () => { - - beforeEach(() => { - service.unsubscribe = jest.fn(); - service.pollSendPostfachMailCommand = jest.fn(); - - commandService.pollCommand.mockReturnValue(of(createStateResource(createCommandResource()))); - vorgangService.getPendingSendPostfachMailCommand.mockReturnValue(of(createStateResource(createCommandResource()))); - }) - - it('should call navigation service', () => { - service.getPendingSendPostfachMailCommand(); - - expect(navigationService.urlChanged).toHaveBeenCalled(); - }) - }) - - describe('resetHasNewPostfachNachrichten', () => { - - const postfachListNachrichtenResource: PostfachMailListResource = createPostfachMailListResource(); - - it('should call doResetHasNewPostfachNachrichten', () => { - service.getPostfachMailListByVorgang = jest.fn(); - service.doResetHasNewPostfachNachrichten = jest.fn(); - (<any>service.getPostfachMailListByVorgang).mockReturnValue(of(postfachListNachrichtenResource)); - - service.resetHasNewPostfachNachrichten(); - - expect(service.doResetHasNewPostfachNachrichten).toHaveBeenCalled(); - }) - }) - - describe('doResetHasNewPostfachNachrichten', () => { - - describe('on existing link', () => { - - const postfachNachrichtenListResource: PostfachMailListResource = createPostfachMailListResource([PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT]); - - beforeEach(() => { - service.postfachMailList$.next(createStateResource(postfachNachrichtenListResource)); - repository.resetHasNewPostfachNachrichten.mockReturnValue(of(postfachNachrichtenListResource)); - }) - - it('should call repository if link exists', () => { - service.doResetHasNewPostfachNachrichten(); - - expect(repository.resetHasNewPostfachNachrichten).toHaveBeenCalledWith(postfachNachrichtenListResource); - }) - }) - - it('should NOT call repository if link not exists', () => { - const postfachNachrichtenListResource: PostfachMailListResource = createPostfachMailListResource(); - service.postfachMailList$.next(createStateResource(postfachNachrichtenListResource)); - - service.doResetHasNewPostfachNachrichten(); - - expect(repository.resetHasNewPostfachNachrichten).not.toHaveBeenCalled(); - }) - }) - - describe('getPostfachMailListByVorgang', () => { - - const postfachMailList: PostfachMailListResource = createPostfachMailListResource(); - - beforeEach(() => { - repository.loadPostfachMailList.mockReturnValue(of(postfachMailList)); - service.setPostfachMailListLoading = jest.fn(); - service.setPostfachMailList = jest.fn(); - vorgangService.getVorgangWithEingang.mockReturnValue(of(createStateResource(createVorgangWithEingangResource()))); - service.postfachMailList$.next(createEmptyStateResource()); - }) - - it('should set loading to true', () => { - service.getPostfachMailListByVorgang(); - - expect(service.setPostfachMailListLoading).toHaveBeenCalled(); - }) - - it('should call vorgang service', () => { - service.getPostfachMailListByVorgang(); - - expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); - }) - - it('should call repository', () => { - service.getPostfachMailListByVorgang().subscribe(); - - expect(repository.loadPostfachMailList).toHaveBeenCalled(); - }) - - it('should set loading to false', () => { - service.getPostfachMailListByVorgang(); - - expect(service.setPostfachMailList).toHaveBeenCalled(); - }) - }) - - describe('handleSendPostfachMailIsDone', () => { - - const stateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); - - beforeEach(() => { - service.setPollingFalse = jest.fn(); - service.setPostfachMailList = jest.fn(); - - commandService.getEffectedResource.mockReturnValue(of(createCommandResource())); - }) - - it('should call command service to get effected resource', () => { - service.handleSendPostfachMailIsDone(stateResource); - - expect(commandService.getEffectedResource).toHaveBeenCalledWith(stateResource.resource); - }) - - it('should set postfachMailList', () => { - service.handleSendPostfachMailIsDone(stateResource); - - expect(service.setPostfachMailList).toHaveBeenCalled(); - }) - - it('should set polling to false', () => { - service.handleSendPostfachMailIsDone(stateResource); - - expect(service.setPollingFalse).toHaveBeenCalled(); - }) - }) - - describe('loadAttachments', () => { - - const postfachNachricht: PostfachMailResource = createPostfachMailResource(); - const fileListStateResource: StateResource<BinaryFileListResource> = createStateResource(createBinaryFileListResource()) - - beforeEach(() => { - binaryFileService.getFiles.mockReturnValue(of(fileListStateResource)); - }) - - it('should call binaryFile service with resource', () => { - service.loadAttachments(postfachNachricht); - - expect(binaryFileService.getFiles).toHaveBeenCalledWith(postfachNachricht, PostfachMailLinkRel.ATTACHMENTS); - }) - }) - - describe('isDownloadPdfInProgress', () => { - - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - it('should call facade to download pdf', (done) => { - vorgangService.getVorgangWithEingang.mockReturnValue(of(createStateResource(vorgang))); - postfachFacade.isDownloadPdfInProgress.mockReturnValue(of(true)); - - service.isDownloadPdfInProgress().subscribe(() => { - expect(postfachFacade.downloadPdf).toHaveBeenCalledWith(vorgang); - done(); - }); - }); - - describe('combine latest', () => { - - beforeEach(() => { - vorgangService.getVorgangWithEingang.mockReturnValue(of(vorgang)); - postfachFacade.isDownloadPdfInProgress = jest.fn().mockReturnValue((true)); - }) - - it('should call facade to get isDownloadPdfInProgress', () => { - service.isDownloadPdfInProgress(); - - expect(postfachFacade.isDownloadPdfInProgress).toHaveBeenCalled(); - }) - - it('should call vorgang service to get vorgang', () => { - service.isDownloadPdfInProgress(); - - expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); - }) - }) - }) - - describe('downloadPdf', () => { - - it('should call facade', () => { - service.downloadPdf(); - - expect(postfachFacade.startDownloadPdf).toHaveBeenCalled(); - }) - }) - - describe('getAttachments', () => { - - const postfachNachricht: PostfachMailResource = createPostfachMailResource(); - const binaryFileResource: BinaryFileResource = createBinaryFileResource(); - const BinaryFileListResource: BinaryFileListResource = createBinaryFileListResource([binaryFileResource]); - - beforeEach(() => { - postfachFacade.getAttachmentList.mockReturnValue(of(createStateResource(BinaryFileListResource))); - }) - - it('should get attachments', () => { - service.getAttachments(postfachNachricht); - - expect(postfachFacade.getAttachmentList).toHaveBeenCalled(); - }) - - it('should load attachments if loading is required', () => { - postfachFacade.getAttachmentList.mockReturnValue(of(createEmptyStateResource())); - - service.getAttachments(postfachNachricht).subscribe(); - - expect(postfachFacade.loadAttachmentList).toHaveBeenCalledWith(postfachNachricht); - }) - - it('should return value', (done) => { - service.getAttachments(postfachNachricht).subscribe((attachments: BinaryFileResource[]) => { - expect(attachments).toEqual([binaryFileResource]); - done(); - }) - }) - }) - - describe('clearAttachmentList', () => { - - it('should call facade', () => { - service.clearAttachmentList(); - - expect(postfachFacade.clearAttachmentList).toHaveBeenCalled(); - }) - }) - - describe('getFeatures', () => { - - it('should return features by list stateResource', (done) => { - service.postfachMailList$ = new BehaviorSubject(createStateResource(createPostfachMailListResource())); - - service.getFeatures().subscribe(features => { - expect(features).toEqual({ reply: true }); - done(); - }); - }) - }) -}); \ No newline at end of file + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); + }); + }); + + describe('downloadPdf', () => { + it('should call facade', () => { + service.downloadPdf(); + + expect(postfachFacade.startDownloadPdf).toHaveBeenCalled(); + }); + }); + + describe('getAttachments', () => { + const postfachNachricht: PostfachMailResource = createPostfachMailResource(); + const binaryFileResource: BinaryFileResource = createBinaryFileResource(); + const BinaryFileListResource: BinaryFileListResource = createBinaryFileListResource([ + binaryFileResource, + ]); + + beforeEach(() => { + postfachFacade.getAttachmentList.mockReturnValue( + of(createStateResource(BinaryFileListResource)), + ); + }); + + it('should get attachments', () => { + service.getAttachments(postfachNachricht); + + expect(postfachFacade.getAttachmentList).toHaveBeenCalled(); + }); + + it('should load attachments if loading is required', () => { + postfachFacade.getAttachmentList.mockReturnValue(of(createEmptyStateResource())); + + service.getAttachments(postfachNachricht).subscribe(); + + expect(postfachFacade.loadAttachmentList).toHaveBeenCalledWith(postfachNachricht); + }); + + it('should return value', (done) => { + service.getAttachments(postfachNachricht).subscribe((attachments: BinaryFileResource[]) => { + expect(attachments).toEqual([binaryFileResource]); + done(); + }); + }); + }); + + describe('clearAttachmentList', () => { + it('should call facade', () => { + service.clearAttachmentList(); + + expect(postfachFacade.clearAttachmentList).toHaveBeenCalled(); + }); + }); + + describe('getFeatures', () => { + it('should return features by list stateResource', (done) => { + service.postfachMailList$ = new BehaviorSubject( + createStateResource(createPostfachMailListResource()), + ); + + service.getFeatures().subscribe((features) => { + expect(features).toEqual({ reply: true }); + done(); + }); + }); + }); +}); diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts index d6edc47998c4cb378e6da5bdd87448b9819a851a..11fbbb1192c2ce1dc78f5dab641bcd950c83c521 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.service.ts @@ -24,10 +24,29 @@ import { Injectable } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; import { Params } from '@angular/router'; -import { BinaryFileListResource, BinaryFileResource, BinaryFileService, getBinaryFiles } from '@alfa-client/binary-file-shared'; -import { CommandResource, CommandService, doIfCommandIsDone, hasError, isDone, isPending } from '@alfa-client/command-shared'; +import { + BinaryFileListResource, + BinaryFileResource, + BinaryFileService, + getBinaryFiles, +} from '@alfa-client/binary-file-shared'; +import { + CommandResource, + CommandService, + doIfCommandIsDone, + hasError, + isDone, + isPending, +} from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { StateResource, createEmptyStateResource, createStateResource, doIfLoadingRequired, isNotNull, isNotUndefined } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createStateResource, + doIfLoadingRequired, + isNotNull, + isNotUndefined, +} from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; import { VorgangResource, VorgangService } from '@alfa-client/vorgang-shared'; import { Resource, hasLink } from '@ngxp/rest'; @@ -37,249 +56,328 @@ import { first, map, take, tap } from 'rxjs/operators'; import { PostfachFacade } from './+state/postfach.facade'; import { PostfachMailLinkRel, PostfachMailListLinkRel } from './postfach.linkrel'; import { PostfachMessages } from './postfach.message'; -import { CreatePostfachMailCommand, Features, PostfachMail, PostfachMailListResource, PostfachMailResource } from './postfach.model'; +import { + CreatePostfachMailCommand, + Features, + PostfachMail, + PostfachMailListResource, + PostfachMailResource, +} from './postfach.model'; import { PostfachRepository } from './postfach.repository'; import { createResendPostfachMailCommand, createSendPostfachMailCommand } from './postfach.util'; @Injectable({ providedIn: 'root' }) export class PostfachService { - - private readonly isPollSendPostachMail: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false); - postfachMailList$: BehaviorSubject<StateResource<PostfachMailListResource>> = new BehaviorSubject<StateResource<PostfachMailListResource>>(createEmptyStateResource<PostfachMailListResource>()); - - private navigationSubscription: Subscription; - - private sendPostfachMailSubscription: Subscription; - private loadPostfachMailSubscription: Subscription; - private vorgangSubscription: Subscription; - private postfachNachrichtenListSubscription: Subscription; - - constructor( - private repository: PostfachRepository, - private commandService: CommandService, - private navigationService: NavigationService, - private vorgangService: VorgangService, - private snackbarService: SnackBarService, - private dialog: MatDialog, - private binaryFileService: BinaryFileService, - private postfachFacade: PostfachFacade - ) { - this.listenToNavigation(); - } - - public sendMail(postfachMail: PostfachMail): Observable<StateResource<CommandResource>> { - return this.doSendNachricht(this.postfachMailList$.value.resource, PostfachMailListLinkRel.SEND_POSTFACH_MAIL, createSendPostfachMailCommand(postfachMail)); - } - - public sendExistingMail(postfachMailResource: PostfachMailResource, postfachMail: PostfachMail): Observable<StateResource<CommandResource>> { - return this.doSendNachricht(postfachMailResource, PostfachMailLinkRel.SEND, createSendPostfachMailCommand(postfachMail)); - } - - public resendMail(postfachMailResource: PostfachMailResource): Observable<StateResource<CommandResource>> { - return this.doSendNachricht(postfachMailResource, PostfachMailLinkRel.RESEND_POSTFACH_MAIL, createResendPostfachMailCommand()); - } - - doSendNachricht(resource: Resource, linkRel: string, command: CreatePostfachMailCommand): Observable<StateResource<CommandResource>> { - this.vorgangService.setPendingSendPostfachMailSingleCommandLoading(); - - this.commandService.createCommand(resource, linkRel, command).pipe(first()).subscribe(createdCommand => this.handleSendNachrichtCommand(createdCommand)); - - return this.getPendingSendPostfachMailCommand(); - } - - handleSendNachrichtCommand(commandStateResource: StateResource<CommandResource>): void { - this.vorgangService.setPendingSendPostfachMailCommand(commandStateResource); - this.commandIsDone(commandStateResource); - } - - commandIsDone(commandStateResource: StateResource<CommandResource>): void { - doIfCommandIsDone(commandStateResource.resource, () => { - this.showSnackbar(commandStateResource.resource) - this.handleSendPostfachMailIsDone(commandStateResource); - }) - } - - private showSnackbar(commandResource: CommandResource): void { - if (hasError(commandResource)) { - this.snackbarService.showError(PostfachMessages.SEND_FAILED); - } else { - this.snackbarService.show(commandResource, PostfachMessages.SEND_SUCCESSFUL); - } - } - - public getPendingSendPostfachMailCommand(): Observable<StateResource<CommandResource>> { - return this.vorgangService.getPendingSendPostfachMailCommand().pipe( - map(pendingCommand => this.pollSendPostfachMailCommand(pendingCommand))); - } - - listenToNavigation(): void { - this.unsubscribeToNavigation(); - this.navigationSubscription = this.navigationService.urlChanged().subscribe(params => this.onNavigation(params)); - } - - unsubscribeToNavigation(): void { - if (!isNil(this.navigationSubscription)) this.navigationSubscription.unsubscribe(); - } - - onNavigation(params: Params): void { - if (NavigationService.isVorgangListPage(params)) { - this.setPollingFalse(); - this.clearPostfachMailList(); - this.closeOpenDialogs(); - this.unsubscribe(); - } - if (NavigationService.isVorgangDetailPage(params, VorgangService.VORGANG_WITH_EINGANG_URL)) { - this.setPostfachMailOnReload(); - } - if (this.navigationService.isPostfachPage()) { - this.resetHasNewPostfachNachrichten(); - } - } - - setPollingFalse(): void { - this.isPollSendPostachMail.next(false); - } - - clearPostfachMailList(): void { - this.postfachMailList$.next(createEmptyStateResource<PostfachMailListResource>()); - } - - closeOpenDialogs(): void { - this.dialog.closeAll(); - } - - unsubscribe(): void { - if (isNotUndefined(this.sendPostfachMailSubscription)) this.sendPostfachMailSubscription.unsubscribe(); - if (isNotUndefined(this.loadPostfachMailSubscription)) this.loadPostfachMailSubscription.unsubscribe(); - if (isNotUndefined(this.vorgangSubscription)) this.vorgangSubscription.unsubscribe(); - } - - setPostfachMailOnReload(): void { - this.postfachMailList$.next({ ...this.postfachMailList$.value, reload: true }); - } - - resetHasNewPostfachNachrichten(): void { - this.postfachNachrichtenListSubscription = this.getPostfachMailListByVorgang().subscribe(postfachNachrichtenList => { - if (isNotNull(postfachNachrichtenList.resource)) { - setTimeout(() => this.postfachNachrichtenListSubscription.unsubscribe(), 0); - this.doResetHasNewPostfachNachrichten(); - } - }) - } - - doResetHasNewPostfachNachrichten(): void { - if (hasLink(this.postfachMailList$.value.resource, PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT)) { - this.repository.resetHasNewPostfachNachrichten(this.postfachMailList$.value.resource).pipe(take(1)).subscribe(); - } - } - - pollSendPostfachMailCommand(command: StateResource<CommandResource>): StateResource<CommandResource> { - if (this.shouldPoll(command)) { - this.setPollingTrue(); - this.sendPostfachMailSubscription = this.commandService.pollCommand(command.resource).subscribe(updatedStateResource => { - this.vorgangService.setPendingSendPostfachMailCommand(updatedStateResource); - - if (isDone(updatedStateResource.resource)) { - this.handleSendPostfachMailIsDone(updatedStateResource); - setTimeout(() => this.sendPostfachMailSubscription.unsubscribe(), 0); - } - }) - } - return command; - } - - private shouldPoll(command: StateResource<CommandResource>): boolean { - return command.loaded && isPending(command.resource) && !this.isPollSendPostachMail.value; - } - - setPollingTrue(): void { - this.isPollSendPostachMail.next(true); - } - - handleSendPostfachMailIsDone(updatedStateResource: StateResource<CommandResource>): void { - this.refreshPostfachMailList(updatedStateResource); - this.setPollingFalse(); - } - - refreshPostfachMailList(updatedStateResource: StateResource<CommandResource>): void { - this.setPostfachMailListLoading(); - this.getEffectedResource(updatedStateResource).pipe(first()).subscribe(effectedResource => { - this.setPostfachMailList(effectedResource); - }) - } - - getEffectedResource(updatedStateResource: StateResource<CommandResource>): Observable<PostfachMailListResource> { - return this.commandService.getEffectedResource<PostfachMailListResource>(updatedStateResource.resource); - } - - public getPostfachMailListByGivenVorgang(vorgang: VorgangResource): Observable<StateResource<PostfachMailListResource>> { - doIfLoadingRequired(this.postfachMailList$.value, () => { - this.setPostfachMailListLoading(); - this.loadPostfachMailsByVorgang(vorgang); - }) - return this.postfachMailList$.asObservable(); - } - - public getPostfachMailListByVorgang(): Observable<StateResource<PostfachMailListResource>> { - doIfLoadingRequired(this.postfachMailList$.value, () => { - this.setPostfachMailListLoading(); - this.vorgangSubscription = this.vorgangService.getVorgangWithEingang().subscribe(vorgangWithEingangStateResource => { - if (vorgangWithEingangStateResource.resource) { - this.loadPostfachMailsByVorgang(vorgangWithEingangStateResource.resource); - setTimeout(() => this.vorgangSubscription.unsubscribe(), 0); - } - }) - }); - return this.postfachMailList$.asObservable(); - } - - setPostfachMailListLoading(): void { - this.postfachMailList$.next({ ...this.postfachMailList$.value, loading: true }); - } - - public loadPostfachMailsByVorgang(vorgang: VorgangResource): void { - this.loadPostfachMailSubscription = this.repository.loadPostfachMailList(vorgang).subscribe(postfachMaiList => { - if (!isNull(postfachMaiList)) { - this.setPostfachMailList(postfachMaiList); - setTimeout(() => this.loadPostfachMailSubscription.unsubscribe(), 0); - } - }); - } - - setPostfachMailList(postfachMailList: PostfachMailListResource): void { - this.postfachMailList$.next(createStateResource(postfachMailList)); - } - - public loadAttachments(postfachNachricht: PostfachMailResource): Observable<StateResource<BinaryFileListResource>> { - return this.binaryFileService.getFiles(postfachNachricht, PostfachMailLinkRel.ATTACHMENTS); - } - - public isDownloadPdfInProgress(): Observable<boolean> { - return combineLatest([this.vorgangService.getVorgangWithEingang(), this.postfachFacade.isDownloadPdfInProgress()]).pipe( - tap(([vorgang, isDownloadInProgress]) => { - if (isDownloadInProgress && vorgang.resource) { - this.postfachFacade.downloadPdf(vorgang.resource); - } - }), - map(([, isDownloadInProgress]) => isDownloadInProgress)); - } - - public downloadPdf(): void { - this.postfachFacade.startDownloadPdf(); - } - - public getAttachments(postfachNachricht: PostfachMailResource): Observable<BinaryFileResource[]> { - return this.postfachFacade.getAttachmentList().pipe( - tap(attachmentList => doIfLoadingRequired(attachmentList, () => this.postfachFacade.loadAttachmentList(postfachNachricht))), - map(getBinaryFiles) - ); - } - - public clearAttachmentList(): void { - this.postfachFacade.clearAttachmentList(); - } - - public getFeatures(): Observable<Features> { - return this.getPostfachMailListByVorgang().pipe(map((listStateResource: StateResource<PostfachMailListResource>) => listStateResource.resource.features)); - } -} \ No newline at end of file + private readonly isPollSendPostachMail: BehaviorSubject<boolean> = new BehaviorSubject<boolean>( + false, + ); + postfachMailList$: BehaviorSubject<StateResource<PostfachMailListResource>> = new BehaviorSubject< + StateResource<PostfachMailListResource> + >(createEmptyStateResource<PostfachMailListResource>()); + + private navigationSubscription: Subscription; + + private sendPostfachMailSubscription: Subscription; + private loadPostfachMailSubscription: Subscription; + private vorgangSubscription: Subscription; + private postfachNachrichtenListSubscription: Subscription; + + constructor( + private repository: PostfachRepository, + private commandService: CommandService, + private navigationService: NavigationService, + private vorgangService: VorgangService, + private snackbarService: SnackBarService, + private dialog: MatDialog, + private binaryFileService: BinaryFileService, + private postfachFacade: PostfachFacade, + ) { + this.listenToNavigation(); + } + + public sendMail(postfachMail: PostfachMail): Observable<StateResource<CommandResource>> { + return this.doSendNachricht( + this.postfachMailList$.value.resource, + PostfachMailListLinkRel.SEND_POSTFACH_MAIL, + createSendPostfachMailCommand(postfachMail), + ); + } + + public sendExistingMail( + postfachMailResource: PostfachMailResource, + postfachMail: PostfachMail, + ): Observable<StateResource<CommandResource>> { + return this.doSendNachricht( + postfachMailResource, + PostfachMailLinkRel.SEND, + createSendPostfachMailCommand(postfachMail), + ); + } + + public resendMail( + postfachMailResource: PostfachMailResource, + ): Observable<StateResource<CommandResource>> { + return this.doSendNachricht( + postfachMailResource, + PostfachMailLinkRel.RESEND_POSTFACH_MAIL, + createResendPostfachMailCommand(), + ); + } + + doSendNachricht( + resource: Resource, + linkRel: string, + command: CreatePostfachMailCommand, + ): Observable<StateResource<CommandResource>> { + this.vorgangService.setPendingSendPostfachMailSingleCommandLoading(); + + this.commandService + .createCommand(resource, linkRel, command) + .pipe(first()) + .subscribe((createdCommand) => this.handleSendNachrichtCommand(createdCommand)); + + return this.getPendingSendPostfachMailCommand(); + } + + handleSendNachrichtCommand(commandStateResource: StateResource<CommandResource>): void { + this.vorgangService.setPendingSendPostfachMailCommand(commandStateResource); + this.commandIsDone(commandStateResource); + } + + commandIsDone(commandStateResource: StateResource<CommandResource>): void { + doIfCommandIsDone(commandStateResource.resource, () => { + this.showSnackbar(commandStateResource.resource); + this.handleSendPostfachMailIsDone(commandStateResource); + }); + } + + private showSnackbar(commandResource: CommandResource): void { + if (hasError(commandResource)) { + this.snackbarService.showError(PostfachMessages.SEND_FAILED); + } else { + this.snackbarService.show(commandResource, PostfachMessages.SEND_SUCCESSFUL); + } + } + + public getPendingSendPostfachMailCommand(): Observable<StateResource<CommandResource>> { + return this.vorgangService + .getPendingSendPostfachMailCommand() + .pipe(map((pendingCommand) => this.pollSendPostfachMailCommand(pendingCommand))); + } + + listenToNavigation(): void { + this.unsubscribeToNavigation(); + this.navigationSubscription = this.navigationService + .urlChanged() + .subscribe((params) => this.onNavigation(params)); + } + + unsubscribeToNavigation(): void { + if (!isNil(this.navigationSubscription)) this.navigationSubscription.unsubscribe(); + } + + onNavigation(params: Params): void { + if (NavigationService.isVorgangListPage(params)) { + this.setPollingFalse(); + this.clearPostfachMailList(); + this.closeOpenDialogs(); + this.unsubscribe(); + } + if (NavigationService.isVorgangDetailPage(params, VorgangService.VORGANG_WITH_EINGANG_URL)) { + this.setPostfachMailOnReload(); + } + if (this.navigationService.isPostfachPage()) { + this.resetHasNewPostfachNachrichten(); + } + } + + setPollingFalse(): void { + this.isPollSendPostachMail.next(false); + } + + clearPostfachMailList(): void { + this.postfachMailList$.next(createEmptyStateResource<PostfachMailListResource>()); + } + + closeOpenDialogs(): void { + this.dialog.closeAll(); + } + + unsubscribe(): void { + if (isNotUndefined(this.sendPostfachMailSubscription)) + this.sendPostfachMailSubscription.unsubscribe(); + if (isNotUndefined(this.loadPostfachMailSubscription)) + this.loadPostfachMailSubscription.unsubscribe(); + if (isNotUndefined(this.vorgangSubscription)) this.vorgangSubscription.unsubscribe(); + } + + setPostfachMailOnReload(): void { + this.postfachMailList$.next({ ...this.postfachMailList$.value, reload: true }); + } + + resetHasNewPostfachNachrichten(): void { + this.postfachNachrichtenListSubscription = this.getPostfachMailListByVorgang().subscribe( + (postfachNachrichtenList) => { + if (isNotNull(postfachNachrichtenList.resource)) { + setTimeout(() => this.postfachNachrichtenListSubscription.unsubscribe(), 0); + this.doResetHasNewPostfachNachrichten(); + } + }, + ); + } + + doResetHasNewPostfachNachrichten(): void { + if ( + hasLink( + this.postfachMailList$.value.resource, + PostfachMailListLinkRel.RESET_HAS_NEW_POSTFACH_NACHRICHT, + ) + ) { + this.repository + .resetHasNewPostfachNachrichten(this.postfachMailList$.value.resource) + .pipe(take(1)) + .subscribe(); + } + } + + pollSendPostfachMailCommand( + command: StateResource<CommandResource>, + ): StateResource<CommandResource> { + if (this.shouldPoll(command)) { + this.setPollingTrue(); + this.sendPostfachMailSubscription = this.commandService + .pollCommand(command.resource) + .subscribe((updatedStateResource) => { + this.vorgangService.setPendingSendPostfachMailCommand(updatedStateResource); + + if (isDone(updatedStateResource.resource)) { + this.handleSendPostfachMailIsDone(updatedStateResource); + setTimeout(() => this.sendPostfachMailSubscription.unsubscribe(), 0); + } + }); + } + return command; + } + + private shouldPoll(command: StateResource<CommandResource>): boolean { + return command.loaded && isPending(command.resource) && !this.isPollSendPostachMail.value; + } + + setPollingTrue(): void { + this.isPollSendPostachMail.next(true); + } + + handleSendPostfachMailIsDone(updatedStateResource: StateResource<CommandResource>): void { + this.refreshPostfachMailList(updatedStateResource); + this.setPollingFalse(); + } + + refreshPostfachMailList(updatedStateResource: StateResource<CommandResource>): void { + this.setPostfachMailListLoading(); + this.getEffectedResource(updatedStateResource) + .pipe(first()) + .subscribe((effectedResource) => { + this.setPostfachMailList(effectedResource); + }); + } + + getEffectedResource( + updatedStateResource: StateResource<CommandResource>, + ): Observable<PostfachMailListResource> { + return this.commandService.getEffectedResource<PostfachMailListResource>( + updatedStateResource.resource, + ); + } + + public getPostfachMailListByGivenVorgang( + vorgang: VorgangResource, + ): Observable<StateResource<PostfachMailListResource>> { + doIfLoadingRequired(this.postfachMailList$.value, () => { + this.setPostfachMailListLoading(); + this.loadPostfachMailsByVorgang(vorgang); + }); + return this.postfachMailList$.asObservable(); + } + + public getPostfachMailListByVorgang(): Observable<StateResource<PostfachMailListResource>> { + doIfLoadingRequired(this.postfachMailList$.value, () => { + this.setPostfachMailListLoading(); + this.vorgangSubscription = this.vorgangService + .getVorgangWithEingang() + .subscribe((vorgangWithEingangStateResource) => { + if (vorgangWithEingangStateResource.resource) { + this.loadPostfachMailsByVorgang(vorgangWithEingangStateResource.resource); + setTimeout(() => this.vorgangSubscription.unsubscribe(), 0); + } + }); + }); + return this.postfachMailList$.asObservable(); + } + + setPostfachMailListLoading(): void { + this.postfachMailList$.next({ ...this.postfachMailList$.value, loading: true }); + } + + public loadPostfachMailsByVorgang(vorgang: VorgangResource): void { + this.loadPostfachMailSubscription = this.repository + .loadPostfachMailList(vorgang) + .subscribe((postfachMaiList) => { + if (!isNull(postfachMaiList)) { + this.setPostfachMailList(postfachMaiList); + setTimeout(() => this.loadPostfachMailSubscription.unsubscribe(), 0); + } + }); + } + + setPostfachMailList(postfachMailList: PostfachMailListResource): void { + this.postfachMailList$.next(createStateResource(postfachMailList)); + } + + public loadAttachments( + postfachNachricht: PostfachMailResource, + ): Observable<StateResource<BinaryFileListResource>> { + return this.binaryFileService.getFiles(postfachNachricht, PostfachMailLinkRel.ATTACHMENTS); + } + + public isDownloadPdfInProgress(): Observable<boolean> { + return combineLatest([ + this.vorgangService.getVorgangWithEingang(), + this.postfachFacade.isDownloadPdfInProgress(), + ]).pipe( + tap(([vorgang, isDownloadInProgress]) => { + if (isDownloadInProgress && vorgang.resource) { + this.postfachFacade.downloadPdf(vorgang.resource); + } + }), + map(([, isDownloadInProgress]) => isDownloadInProgress), + ); + } + + public downloadPdf(): void { + this.postfachFacade.startDownloadPdf(); + } + + public getAttachments(postfachNachricht: PostfachMailResource): Observable<BinaryFileResource[]> { + return this.postfachFacade.getAttachmentList().pipe( + tap((attachmentList) => + doIfLoadingRequired(attachmentList, () => + this.postfachFacade.loadAttachmentList(postfachNachricht), + ), + ), + map(getBinaryFiles), + ); + } + + public clearAttachmentList(): void { + this.postfachFacade.clearAttachmentList(); + } + + public getFeatures(): Observable<Features> { + return this.getPostfachMailListByVorgang().pipe( + map( + (listStateResource: StateResource<PostfachMailListResource>) => + listStateResource.resource.features, + ), + ); + } +} diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.tokens.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.tokens.ts index b840d191c328da6165d51f5155779271d3d4c95b..d1659c9fe8afbbd470c436f901a57a09d2545575 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.tokens.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.tokens.ts @@ -23,4 +23,4 @@ */ import { InjectionToken } from '@angular/core'; -export const ON_PAGE = new InjectionToken<boolean>('ON_PAGE'); \ No newline at end of file +export const ON_PAGE = new InjectionToken<boolean>('ON_PAGE'); diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.util.spec.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.util.spec.ts index ebfa08187d0f4c29a0479fec402d3ed7d74ac7e2..eda2f5a8457a672f23b86a2e159afd535bdc5d63 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.util.spec.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.util.spec.ts @@ -21,130 +21,161 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { createPostfachMail, createPostfachMailListResource, createPostfachMailResource } from 'libs/postfach-shared/test/postfach'; +import { + createPostfachMail, + createPostfachMailListResource, + createPostfachMailResource, +} from 'libs/postfach-shared/test/postfach'; import { toResource } from 'libs/tech-shared/test/resource'; import { PostfachMailListLinkRel } from './postfach.linkrel'; import { PostfachNachrichtMessageCode } from './postfach.message-code'; -import { CreatePostfachMailCommand, Direction, PostfachMail, PostfachMailListResource, PostfachMailResource, PostfachNachrichtenCount, PostfachOrder } from './postfach.model'; -import { createResendPostfachMailCommand, createSendPostfachMailCommand, getMessageCodeMessage, getPostfachNachrichtenCount, isIncomingMail } from './postfach.util'; +import { + CreatePostfachMailCommand, + Direction, + PostfachMail, + PostfachMailListResource, + PostfachMailResource, + PostfachNachrichtenCount, + PostfachOrder, +} from './postfach.model'; +import { + createResendPostfachMailCommand, + createSendPostfachMailCommand, + getMessageCodeMessage, + getPostfachNachrichtenCount, + isIncomingMail, +} from './postfach.util'; describe('PostfachUtil', () => { + describe('createSendPostfachMailCommand', () => { + const postfachMail: PostfachMail = createPostfachMail(); - describe('createSendPostfachMailCommand', () => { + it('should have order', () => { + const command: CreatePostfachMailCommand = createSendPostfachMailCommand(postfachMail); - const postfachMail: PostfachMail = createPostfachMail(); + expect(command.order).toEqual(PostfachOrder.SEND_POSTFACH_NACHRICHT); + }); - it('should have order', () => { - const command: CreatePostfachMailCommand = createSendPostfachMailCommand(postfachMail); + it('should have body', () => { + const command: CreatePostfachMailCommand = createSendPostfachMailCommand(postfachMail); - expect(command.order).toEqual(PostfachOrder.SEND_POSTFACH_NACHRICHT); - }) + expect(command.body).toEqual(postfachMail); + }); + }); - it('should have body', () => { - const command: CreatePostfachMailCommand = createSendPostfachMailCommand(postfachMail); + describe('createResendPostfachMailCommand', () => { + it('should have order', () => { + const command: CreatePostfachMailCommand = createResendPostfachMailCommand(); - expect(command.body).toEqual(postfachMail); - }) - }) + expect(command.order).toEqual(PostfachOrder.RESEND_POSTFACH_MAIL); + }); - describe('createResendPostfachMailCommand', () => { + it('should have body', () => { + const command: CreatePostfachMailCommand = createResendPostfachMailCommand(); - it('should have order', () => { - const command: CreatePostfachMailCommand = createResendPostfachMailCommand(); + expect(command.body).toEqual(null); + }); + }); - expect(command.order).toEqual(PostfachOrder.RESEND_POSTFACH_MAIL); - }) + describe('isIncomingMail', () => { + it('should be false on direction OUT', () => { + var result = isIncomingMail({ ...createPostfachMailResource(), direction: Direction.OUT }); - it('should have body', () => { - const command: CreatePostfachMailCommand = createResendPostfachMailCommand(); + expect(result).toBeFalsy(); + }); - expect(command.body).toEqual(null); - }) - }) + it('should be true on direction IN', () => { + var result = isIncomingMail({ ...createPostfachMailResource(), direction: Direction.IN }); - describe('isIncomingMail', () => { + expect(result).toBeTruthy(); + }); + }); - it('should be false on direction OUT', () => { - var result = isIncomingMail({ ...createPostfachMailResource(), direction: Direction.OUT }); + describe('getMessageCodeMessage', () => { + it( + 'should return message for messageCode ' + PostfachNachrichtMessageCode.CONNECTION_FAILED, + () => { + var result = getMessageCodeMessage({ + ...createPostfachMailResource(), + messageCode: PostfachNachrichtMessageCode.CONNECTION_FAILED, + }); - expect(result).toBeFalsy(); - }) + expect(result).toEqual( + 'Verbindungsfehler: Die Verbindung zum Zielserver des Osi-Postfachs ist nicht zustandegekommen.', + ); + }, + ); - it('should be true on direction IN', () => { - var result = isIncomingMail({ ...createPostfachMailResource(), direction: Direction.IN }); + it( + 'should return message for messageCode ' + PostfachNachrichtMessageCode.PROCESSING_FAILED, + () => { + var result = getMessageCodeMessage({ + ...createPostfachMailResource(), + messageCode: PostfachNachrichtMessageCode.PROCESSING_FAILED, + }); - expect(result).toBeTruthy(); - }) - }) + expect(result).toEqual( + 'Fehlerhafte Verarbeitung: Die Nachricht wurde an das Osi-Postfach geschickt, konnte dort aber nicht richtig verarbeitet werden.', + ); + }, + ); + }); - describe('getMessageCodeMessage', () => { + describe('getPostfacNachrichtenCount', () => { + describe('return NONE', () => { + it('on null listResource', () => { + var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(null); - it('should return message for messageCode ' + PostfachNachrichtMessageCode.CONNECTION_FAILED, () => { - var result = getMessageCodeMessage({ ...createPostfachMailResource(), messageCode: PostfachNachrichtMessageCode.CONNECTION_FAILED }); + expect(count).toBe(PostfachNachrichtenCount.NONE); + }); - expect(result).toEqual('Verbindungsfehler: Die Verbindung zum Zielserver des Osi-Postfachs ist nicht zustandegekommen.'); - }) + it('on undefined listResource', () => { + var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(undefined); - it('should return message for messageCode ' + PostfachNachrichtMessageCode.PROCESSING_FAILED, () => { - var result = getMessageCodeMessage({ ...createPostfachMailResource(), messageCode: PostfachNachrichtMessageCode.PROCESSING_FAILED }); + expect(count).toBe(PostfachNachrichtenCount.NONE); + }); - expect(result).toEqual('Fehlerhafte Verarbeitung: Die Nachricht wurde an das Osi-Postfach geschickt, konnte dort aber nicht richtig verarbeitet werden.'); - }) - }) + it('should return NONE on empty resource list', () => { + var listResource: PostfachMailListResource = createListResource([]); - describe('getPostfacNachrichtenCount', () => { + var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource); - describe('return NONE', () => { + expect(count).toBe(PostfachNachrichtenCount.NONE); + }); - it('on null listResource', () => { - var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(null); + it('should return NONE on non existing resources', () => { + var listResource: PostfachMailListResource = toResource({}, [], {}); - expect(count).toBe(PostfachNachrichtenCount.NONE); - }) + var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource); - it('on undefined listResource', () => { - var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(undefined); + expect(count).toBe(PostfachNachrichtenCount.NONE); + }); + }); - expect(count).toBe(PostfachNachrichtenCount.NONE); - }) + it('should return SINGLE on one existing resources', () => { + var listResource: PostfachMailListResource = createListResource([ + createPostfachMailResource(), + ]); - it('should return NONE on empty resource list', () => { - var listResource: PostfachMailListResource = createListResource([]); + var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource); - var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource); + expect(count).toBe(PostfachNachrichtenCount.SINGLE); + }); - expect(count).toBe(PostfachNachrichtenCount.NONE); - }) + it('should return MULTIPLE on multiple existing resources', () => { + var listResource: PostfachMailListResource = createPostfachMailListResource(); - it('should return NONE on non existing resources', () => { - var listResource: PostfachMailListResource = toResource({}, [], {}); + var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource); - var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource); + expect(count).toBe(PostfachNachrichtenCount.MULTIPLE); + }); - expect(count).toBe(PostfachNachrichtenCount.NONE); - }) - }) - - it('should return SINGLE on one existing resources', () => { - var listResource: PostfachMailListResource = createListResource([createPostfachMailResource()]); - - var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource); - - expect(count).toBe(PostfachNachrichtenCount.SINGLE); - }) - - it('should return MULTIPLE on multiple existing resources', () => { - var listResource: PostfachMailListResource = createPostfachMailListResource(); - - var count: PostfachNachrichtenCount = getPostfachNachrichtenCount(listResource); - - expect(count).toBe(PostfachNachrichtenCount.MULTIPLE); - }) - - function createListResource(postfachMailResources: PostfachMailResource[]): PostfachMailListResource { - return toResource({}, [], { - [PostfachMailListLinkRel.POSTFACH_MAIL_LIST]: postfachMailResources - }); - } - }) -}) + function createListResource( + postfachMailResources: PostfachMailResource[], + ): PostfachMailListResource { + return toResource({}, [], { + [PostfachMailListLinkRel.POSTFACH_MAIL_LIST]: postfachMailResources, + }); + } + }); +}); diff --git a/alfa-client/libs/postfach-shared/src/lib/postfach.util.ts b/alfa-client/libs/postfach-shared/src/lib/postfach.util.ts index 343acdc7d0fabfb59b904068cfe5d5d5b2f8f10f..8b8507d5e77ccbe0074810da1d3a47a93b1aa10d 100644 --- a/alfa-client/libs/postfach-shared/src/lib/postfach.util.ts +++ b/alfa-client/libs/postfach-shared/src/lib/postfach.util.ts @@ -26,40 +26,64 @@ import { getEmbeddedResource } from '@ngxp/rest'; import { isNil } from 'lodash-es'; import { PostfachMailListLinkRel } from './postfach.linkrel'; import { postfachNachrichtMessageCodeMessages } from './postfach.message-code'; -import { CreatePostfachMailCommand, Direction, PostfachMail, PostfachMailListResource, PostfachMailResource, PostfachNachrichtenCount, PostfachOrder, ReplyOption } from './postfach.model'; +import { + CreatePostfachMailCommand, + Direction, + PostfachMail, + PostfachMailListResource, + PostfachMailResource, + PostfachNachrichtenCount, + PostfachOrder, + ReplyOption, +} from './postfach.model'; -export function createSendPostfachMailCommand(postfachMail: PostfachMail): CreatePostfachMailCommand { - return { order: PostfachOrder.SEND_POSTFACH_NACHRICHT, body: postfachMail }; +export function createSendPostfachMailCommand( + postfachMail: PostfachMail, +): CreatePostfachMailCommand { + return { order: PostfachOrder.SEND_POSTFACH_NACHRICHT, body: postfachMail }; } export function createResendPostfachMailCommand(): CreatePostfachMailCommand { - return { order: PostfachOrder.RESEND_POSTFACH_MAIL, body: null }; + return { order: PostfachOrder.RESEND_POSTFACH_MAIL, body: null }; } export function isIncomingMail(postfachMail: PostfachMailResource): boolean { - return postfachMail.direction == Direction.IN; + return postfachMail.direction == Direction.IN; } export function getMessageCodeMessage(postfachMail: PostfachMailResource): string { - return postfachNachrichtMessageCodeMessages[postfachMail.messageCode]; + return postfachNachrichtMessageCodeMessages[postfachMail.messageCode]; } -export function getPostfachNachrichtenCount(postfachMailListResource: PostfachMailListResource): PostfachNachrichtenCount { - if (isNil(postfachMailListResource)) { - return PostfachNachrichtenCount.NONE; - } +export function getPostfachNachrichtenCount( + postfachMailListResource: PostfachMailListResource, +): PostfachNachrichtenCount { + if (isNil(postfachMailListResource)) { + return PostfachNachrichtenCount.NONE; + } - const resources: PostfachMailResource[] = getEmbeddedResource<PostfachMailResource[]>(postfachMailListResource, PostfachMailListLinkRel.POSTFACH_MAIL_LIST); - if (isNil(resources) || resources.length == 0) { - return PostfachNachrichtenCount.NONE; - } - if (resources.length == 1) { - return PostfachNachrichtenCount.SINGLE; - } - if (resources.length > 1) { - return PostfachNachrichtenCount.MULTIPLE; - } + const resources: PostfachMailResource[] = getEmbeddedResource<PostfachMailResource[]>( + postfachMailListResource, + PostfachMailListLinkRel.POSTFACH_MAIL_LIST, + ); + if (isNil(resources) || resources.length == 0) { + return PostfachNachrichtenCount.NONE; + } + if (resources.length == 1) { + return PostfachNachrichtenCount.SINGLE; + } + if (resources.length > 1) { + return PostfachNachrichtenCount.MULTIPLE; + } } -export const FORBIDDEN_REPLY_OPTION_ITEM: EnumEditorItem = { type: ReplyOption.FORBIDDEN, svgIcon: 'no_reply', text: 'Antworten unterbinden' }; -export const POSSIBLE_REPLY_OPTION_ITEM: EnumEditorItem = { type: ReplyOption.POSSIBLE, icon: 'reply', text: 'Antworten erlauben' } \ No newline at end of file +export const FORBIDDEN_REPLY_OPTION_ITEM: EnumEditorItem = { + type: ReplyOption.FORBIDDEN, + svgIcon: 'no_reply', + text: 'Antworten unterbinden', +}; +export const POSSIBLE_REPLY_OPTION_ITEM: EnumEditorItem = { + type: ReplyOption.POSSIBLE, + icon: 'reply', + text: 'Antworten erlauben', +}; diff --git a/alfa-client/libs/postfach-shared/src/test-setup.ts b/alfa-client/libs/postfach-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/postfach-shared/src/test-setup.ts +++ b/alfa-client/libs/postfach-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/postfach-shared/test/postfach.ts b/alfa-client/libs/postfach-shared/test/postfach.ts index e70640f712011ab8b44047d6765feeb8b536f8d9..fb0fa71451c5d4409d18ba8c879e592eae198030 100644 --- a/alfa-client/libs/postfach-shared/test/postfach.ts +++ b/alfa-client/libs/postfach-shared/test/postfach.ts @@ -28,68 +28,80 @@ import { toResource } from 'libs/tech-shared/test/resource'; import { times } from 'lodash-es'; import { PostfachMailListLinkRel } from '../src/lib/postfach.linkrel'; import { PostfachNachrichtMessageCode } from '../src/lib/postfach.message-code'; -import { Direction, PostfachMail, PostfachMailFormDialogData, PostfachMailListResource, PostfachMailResource, ReplyOption } from '../src/lib/postfach.model'; +import { + Direction, + PostfachMail, + PostfachMailFormDialogData, + PostfachMailListResource, + PostfachMailResource, + ReplyOption, +} from '../src/lib/postfach.model'; export function createPostfachMail(): PostfachMail { - return { - subject: faker.random.words(3), - createdAt: faker.date.past(), - direction: Direction.OUT, - mailBody: faker.random.words(30), - replyOption: ReplyOption.POSSIBLE, - sentAt: faker.date.past(), - sentSuccessful: false, - messageCode: PostfachNachrichtMessageCode.CONNECTION_FAILED, - attachments: faker.datatype.uuid() - } + return { + subject: faker.random.words(3), + createdAt: faker.date.past(), + direction: Direction.OUT, + mailBody: faker.random.words(30), + replyOption: ReplyOption.POSSIBLE, + sentAt: faker.date.past(), + sentSuccessful: false, + messageCode: PostfachNachrichtMessageCode.CONNECTION_FAILED, + attachments: faker.datatype.uuid(), + }; } export function createPostfachMailResource(linkRelations: string[] = []): PostfachMailResource { - return toResource(createPostfachMail(), linkRelations); + return toResource(createPostfachMail(), linkRelations); } export function createPostfachMailResources(linkRelations: string[] = []): PostfachMailResource[] { - return times(10, () => toResource(createPostfachMailResource(), [...linkRelations])); + return times(10, () => toResource(createPostfachMailResource(), [...linkRelations])); } -export function createPostfachMailListResource(linkRelations: string[] = []): PostfachMailListResource { - return toResource(createPostfachMailListWithAllowedReplyFeature(), [...linkRelations], { - [PostfachMailListLinkRel.POSTFACH_MAIL_LIST]: createPostfachMailResources() - }); +export function createPostfachMailListResource( + linkRelations: string[] = [], +): PostfachMailListResource { + return toResource(createPostfachMailListWithAllowedReplyFeature(), [...linkRelations], { + [PostfachMailListLinkRel.POSTFACH_MAIL_LIST]: createPostfachMailResources(), + }); } function createPostfachMailListWithAllowedReplyFeature(): Resource { - return toResource({ features: { reply: true } }, ['sendPostfachMail']); + return toResource({ features: { reply: true } }, ['sendPostfachMail']); } - export class PostfachTestFactory { + public static POSTFACH_NACHRICHT: PostfachMail = { + subject: faker.random.words(3), + createdAt: faker.date.past(), + direction: Direction.OUT, + mailBody: faker.random.words(30), + replyOption: ReplyOption.POSSIBLE, + sentAt: faker.date.past(), + sentSuccessful: false, + messageCode: PostfachNachrichtMessageCode.CONNECTION_FAILED, + attachments: faker.datatype.uuid(), + }; - public static POSTFACH_NACHRICHT: PostfachMail = { - subject: faker.random.words(3), - createdAt: faker.date.past(), - direction: Direction.OUT, - mailBody: faker.random.words(30), - replyOption: ReplyOption.POSSIBLE, - sentAt: faker.date.past(), - sentSuccessful: false, - messageCode: PostfachNachrichtMessageCode.CONNECTION_FAILED, - attachments: faker.datatype.uuid() - } - - public static POSTFACH_NACHRICHT_RESOURCE: PostfachMailResource = toResource(PostfachTestFactory.POSTFACH_NACHRICHT, EMPTY_ARRAY); - public static POSTFACH_NACHRICHT_LIST_RESOURCE = createPostfachMailListResource(); - public static POSTFACH_NACHRICHT_LIST_STATE_RESOURCE = createStateResource(PostfachTestFactory.POSTFACH_NACHRICHT_LIST_RESOURCE); + public static POSTFACH_NACHRICHT_RESOURCE: PostfachMailResource = toResource( + PostfachTestFactory.POSTFACH_NACHRICHT, + EMPTY_ARRAY, + ); + public static POSTFACH_NACHRICHT_LIST_RESOURCE = createPostfachMailListResource(); + public static POSTFACH_NACHRICHT_LIST_STATE_RESOURCE = createStateResource( + PostfachTestFactory.POSTFACH_NACHRICHT_LIST_RESOURCE, + ); - public static POSTFACH_MAIL_FORM_DIALOG_DATA_TITLE: string = ''; - public static POSTFACH_MAIL_FORM_DIALOG_DATA_EMPFAENGER: string = ''; - public static POSTFACH_MAIL_FORM_DIALOG_DATA_COMPONENT = null; + public static POSTFACH_MAIL_FORM_DIALOG_DATA_TITLE: string = ''; + public static POSTFACH_MAIL_FORM_DIALOG_DATA_EMPFAENGER: string = ''; + public static POSTFACH_MAIL_FORM_DIALOG_DATA_COMPONENT = null; - public static POSTFACH_MAIL_FORM_DIALOG_DATA: PostfachMailFormDialogData = { - postfachNachricht: PostfachTestFactory.POSTFACH_NACHRICHT_RESOURCE, - empfaenger: PostfachTestFactory.POSTFACH_MAIL_FORM_DIALOG_DATA_EMPFAENGER, - component: PostfachTestFactory.POSTFACH_MAIL_FORM_DIALOG_DATA_COMPONENT, - postfachMailListStateResource: PostfachTestFactory.POSTFACH_NACHRICHT_LIST_STATE_RESOURCE, - title:PostfachTestFactory. POSTFACH_MAIL_FORM_DIALOG_DATA_TITLE - } -} \ No newline at end of file + public static POSTFACH_MAIL_FORM_DIALOG_DATA: PostfachMailFormDialogData = { + postfachNachricht: PostfachTestFactory.POSTFACH_NACHRICHT_RESOURCE, + empfaenger: PostfachTestFactory.POSTFACH_MAIL_FORM_DIALOG_DATA_EMPFAENGER, + component: PostfachTestFactory.POSTFACH_MAIL_FORM_DIALOG_DATA_COMPONENT, + postfachMailListStateResource: PostfachTestFactory.POSTFACH_NACHRICHT_LIST_STATE_RESOURCE, + title: PostfachTestFactory.POSTFACH_MAIL_FORM_DIALOG_DATA_TITLE, + }; +} diff --git a/alfa-client/libs/postfach-shared/tsconfig.json b/alfa-client/libs/postfach-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/postfach-shared/tsconfig.json +++ b/alfa-client/libs/postfach-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/postfach-shared/tsconfig.lib.json b/alfa-client/libs/postfach-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/postfach-shared/tsconfig.lib.json +++ b/alfa-client/libs/postfach-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/postfach-shared/tsconfig.spec.json b/alfa-client/libs/postfach-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/postfach-shared/tsconfig.spec.json +++ b/alfa-client/libs/postfach-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/postfach/.eslintrc.json b/alfa-client/libs/postfach/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/postfach/.eslintrc.json +++ b/alfa-client/libs/postfach/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/postfach/jest.config.ts b/alfa-client/libs/postfach/jest.config.ts index 76ac2eaf262b8da5d0a1fff77def0568a15ff59c..35371dc1afcfc5f2fedca6400979cc1bc265e8ef 100644 --- a/alfa-client/libs/postfach/jest.config.ts +++ b/alfa-client/libs/postfach/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'postfach', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/postfach', - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'postfach', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/postfach', + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/postfach/project.json b/alfa-client/libs/postfach/project.json index d332486a03f963c4923ad02fd6cee437d344d707..d54e17df338dcf259d31ae12cba189b2a0752d55 100644 --- a/alfa-client/libs/postfach/project.json +++ b/alfa-client/libs/postfach/project.json @@ -1,29 +1,26 @@ { - "name": "postfach", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/postfach/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/postfach"], - "options": { - "tsConfig": "libs/postfach/tsconfig.spec.json", - "jestConfig": "libs/postfach/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/postfach/src/**/*.ts", - "libs/postfach/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [] + "name": "postfach", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/postfach/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/postfach"], + "options": { + "tsConfig": "libs/postfach/tsconfig.spec.json", + "jestConfig": "libs/postfach/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/postfach/src/**/*.ts", "libs/postfach/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [] } diff --git a/alfa-client/libs/postfach/src/index.ts b/alfa-client/libs/postfach/src/index.ts index 363920981cff36de768522c488bee083e34db4c5..ebb1b71a43521439c322323652b1b4fdc2e6ef2f 100644 --- a/alfa-client/libs/postfach/src/index.ts +++ b/alfa-client/libs/postfach/src/index.ts @@ -25,4 +25,3 @@ export * from './lib/postfach-mail-button-container/postfach-mail-button-contain export * from './lib/postfach-mail-form/postfach-mail-form.component'; export * from './lib/postfach-mail-list-container/postfach-mail-list-container.component'; export * from './lib/postfach.module'; - diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.html index 121b644720e5e7392732433d20d2b8efc9a49c66..34c88ecb773f65451e4d83e767a42acd569e753d 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.html @@ -24,14 +24,16 @@ --> <ng-container *ngIf="postfachMailListStateResource$ | async as postfachMailListStateResource"> - - <alfa-postfach-mail-button *ngIf="postfachMailListStateResource.resource | hasLink: postfachMailListLinkRel.SEND_POSTFACH_MAIL" - [pendingSendPostfachMailCommand]="pendingSendPostfachMailCommand$ | async" - [postfachMailListStateResource]="postfachMailListStateResource" - [showAsIconButton]="showAsIconButton" - [toolTip]="toolTip" - [text]="text" - (openPostfachNachrichtenDialog)="openPostfachMailDialog(postfachMailListStateResource)"> - </alfa-postfach-mail-button> - -</ng-container> \ No newline at end of file + <alfa-postfach-mail-button + *ngIf=" + postfachMailListStateResource.resource | hasLink: postfachMailListLinkRel.SEND_POSTFACH_MAIL + " + [pendingSendPostfachMailCommand]="pendingSendPostfachMailCommand$ | async" + [postfachMailListStateResource]="postfachMailListStateResource" + [showAsIconButton]="showAsIconButton" + [toolTip]="toolTip" + [text]="text" + (openPostfachNachrichtenDialog)="openPostfachMailDialog(postfachMailListStateResource)" + > + </alfa-postfach-mail-button> +</ng-container> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.spec.ts index b824b7b7a5617f96e162b0ab9dc2cb88f9015f13..81dbf91bfdc2657a53bbcdbc6e10089f0ffa4f24 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.spec.ts @@ -23,7 +23,12 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { PostfachMailListResource, PostfachService } from '@alfa-client/postfach-shared'; -import { HasLinkPipe, StateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + HasLinkPipe, + StateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; import { DialogService } from '@alfa-client/ui'; import { VorgangHeaderLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @@ -37,141 +42,144 @@ import { PostfachMailButtonContainerComponent } from './postfach-mail-button-con import { PostfachMailButtonComponent } from './postfach-mail-button/postfach-mail-button.component'; describe('PostfachMailButtonContainerComponent', () => { - let component: PostfachMailButtonContainerComponent; - let fixture: ComponentFixture<PostfachMailButtonContainerComponent>; + let component: PostfachMailButtonContainerComponent; + let fixture: ComponentFixture<PostfachMailButtonContainerComponent>; + + const postfachService = mock(PostfachService); + const dialogService = mock(DialogService); + + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachMailButtonContainerComponent, + HasLinkPipe, + MockComponent(PostfachMailButtonComponent), + ], + providers: [ + { + provide: DialogService, + useValue: dialogService, + }, + { + provide: PostfachService, + useValue: postfachService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachMailButtonContainerComponent); + component = fixture.componentInstance; + component.vorgang = vorgang; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('vorgang changes', () => { + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangHeaderLinkRel.POSTFACH_MAILS, + ]); + + beforeEach(() => { + component.loadPendingSendPostfachMailCommand = jest.fn(); + component.loadPostfachMailListStateResource = jest.fn(); + }); + + it('should call loadPendingSendPostfachMailCommand', () => { + component.vorgang = vorgang; + + expect(component.loadPendingSendPostfachMailCommand).toHaveBeenCalled(); + }); + + it('should call loadPostfachMailListStateResource', () => { + component.vorgang = vorgang; + + expect(component.loadPostfachMailListStateResource).toHaveBeenCalled(); + }); + }); + + describe('loadPendingSendPostfachMailCommand', () => { + beforeEach(() => { + component.closeDialog = jest.fn(); + postfachService.getPendingSendPostfachMailCommand.mockReturnValue( + of(createStateResource(createCommandResource())), + ); + }); + + it('should call postfach service', () => { + component.loadPendingSendPostfachMailCommand(); + + expect(postfachService.getPendingSendPostfachMailCommand).toHaveBeenCalled(); + }); + + it('should call closeDialog', () => { + component.loadPendingSendPostfachMailCommand(); + + expect(postfachService.getPendingSendPostfachMailCommand).toHaveBeenCalled(); + }); + }); + + describe('loadPostfachMailListStateResource', () => { + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangHeaderLinkRel.POSTFACH_MAILS, + ]); + + beforeEach(() => { + postfachService.getPostfachMailListByGivenVorgang.mockReturnValue(of({})); + }); + + it('should call postfach service', () => { + component.vorgang = vorgang; + + component.loadPostfachMailListStateResource(); + + expect(postfachService.getPostfachMailListByGivenVorgang).toHaveBeenCalledWith(vorgang); + }); + }); + + describe('open postfach mail dialog', () => { + const postfachMailListStateResource: StateResource<PostfachMailListResource> = + createStateResource(createPostfachMailListResource()); + + it('should open new dialog with given data', () => { + component.openPostfachMailDialog(postfachMailListStateResource); + + expect(dialogService.openFixed).toHaveBeenCalled(); + }); + }); + + describe('closeDialog', () => { + it('should be called if command has no error and dialogRef is not undefined and resource is loaded', () => { + component.dialogRef = <any>{}; + + component.closeDialog(createStateResource(createCommandResource())); + + expect(dialogService.closeAll).toHaveBeenCalled(); + }); + + it('should not be called if command is not loaded', () => { + dialogService.closeAll.mockClear(); + component.dialogRef = <any>{}; - const postfachService = mock(PostfachService); - const dialogService = mock(DialogService); + component.closeDialog(createErrorStateResource(createApiError())); - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); + expect(dialogService.closeAll).not.toHaveBeenCalled(); + }); + }); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachMailButtonContainerComponent, - HasLinkPipe, - MockComponent(PostfachMailButtonComponent) - ], - providers: [ - { - provide: DialogService, - useValue: dialogService - }, - { - provide: PostfachService, - useValue: postfachService - } - ] - }).compileComponents(); - }); + describe('getEmpfaenger', () => { + it('should return antragsteller name', () => { + const antragsteller = component.getEmpfaenger(); - beforeEach(() => { - fixture = TestBed.createComponent(PostfachMailButtonContainerComponent); - component = fixture.componentInstance; - component.vorgang = vorgang; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('vorgang changes', () => { - - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangHeaderLinkRel.POSTFACH_MAILS]); - - beforeEach(() => { - component.loadPendingSendPostfachMailCommand = jest.fn(); - component.loadPostfachMailListStateResource = jest.fn(); - }) - - it('should call loadPendingSendPostfachMailCommand', () => { - component.vorgang = vorgang; - - expect(component.loadPendingSendPostfachMailCommand).toHaveBeenCalled(); - }); - - it('should call loadPostfachMailListStateResource', () => { - component.vorgang = vorgang; - - expect(component.loadPostfachMailListStateResource).toHaveBeenCalled(); - }) - }) - - describe('loadPendingSendPostfachMailCommand', () => { - - beforeEach(() => { - component.closeDialog = jest.fn(); - postfachService.getPendingSendPostfachMailCommand.mockReturnValue(of(createStateResource(createCommandResource()))); - }) - - it('should call postfach service', () => { - component.loadPendingSendPostfachMailCommand(); - - expect(postfachService.getPendingSendPostfachMailCommand).toHaveBeenCalled(); - }) - - it('should call closeDialog', () => { - component.loadPendingSendPostfachMailCommand(); - - expect(postfachService.getPendingSendPostfachMailCommand).toHaveBeenCalled(); - }) - }) - - describe('loadPostfachMailListStateResource', () => { - - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangHeaderLinkRel.POSTFACH_MAILS]); - - beforeEach(() => { - postfachService.getPostfachMailListByGivenVorgang.mockReturnValue(of({})); - }) - - it('should call postfach service', () => { - component.vorgang = vorgang; - - component.loadPostfachMailListStateResource(); - - expect(postfachService.getPostfachMailListByGivenVorgang).toHaveBeenCalledWith(vorgang); - }) - }) - - describe('open postfach mail dialog', () => { - - const postfachMailListStateResource: StateResource<PostfachMailListResource> = createStateResource(createPostfachMailListResource()); - - it('should open new dialog with given data', () => { - component.openPostfachMailDialog(postfachMailListStateResource); - - expect(dialogService.openFixed).toHaveBeenCalled(); - }) - }) - - describe('closeDialog', () => { - - it('should be called if command has no error and dialogRef is not undefined and resource is loaded', () => { - component.dialogRef = <any>{}; - - component.closeDialog(createStateResource(createCommandResource())); - - expect(dialogService.closeAll).toHaveBeenCalled(); - }) - - it('should not be called if command is not loaded', () => { - dialogService.closeAll.mockClear(); - component.dialogRef = <any>{}; - - component.closeDialog(createErrorStateResource(createApiError())); - - expect(dialogService.closeAll).not.toHaveBeenCalled(); - }) - }) - - describe('getEmpfaenger', () => { - - it('should return antragsteller name', () => { - const antragsteller = component.getEmpfaenger(); - - expect(antragsteller).toEqual(`${vorgang.eingang.antragsteller.vorname} ${vorgang.eingang.antragsteller.nachname}`) - }); - }) + expect(antragsteller).toEqual( + `${vorgang.eingang.antragsteller.vorname} ${vorgang.eingang.antragsteller.nachname}`, + ); + }); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.ts index 2663df4d0cec55c140a3f711d32783d0665acb23..dde104c79cf00b344d836312072bf0963f96bbf1 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button-container.component.ts @@ -24,8 +24,19 @@ import { Component, Input } from '@angular/core'; import { MatDialogRef } from '@angular/material/dialog'; import { CommandResource } from '@alfa-client/command-shared'; -import { PostfachMailFormDialogData, PostfachMailListLinkRel, PostfachMailListResource, PostfachService } from '@alfa-client/postfach-shared'; -import { EMPTY_STRING, StateResource, hasError, isNotNull, isNotUndefined } from '@alfa-client/tech-shared'; +import { + PostfachMailFormDialogData, + PostfachMailListLinkRel, + PostfachMailListResource, + PostfachService, +} from '@alfa-client/postfach-shared'; +import { + EMPTY_STRING, + StateResource, + hasError, + isNotNull, + isNotUndefined, +} from '@alfa-client/tech-shared'; import { DialogService, FixedDialogComponent } from '@alfa-client/ui'; import { VorgangHeaderLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { hasLink } from '@ngxp/rest'; @@ -34,71 +45,87 @@ import { tap } from 'rxjs/operators'; import { PostfachMailFormComponent } from '../postfach-mail-form/postfach-mail-form.component'; @Component({ - selector: 'alfa-postfach-mail-button-container', - templateUrl: './postfach-mail-button-container.component.html', - styleUrls: ['./postfach-mail-button-container.component.scss'] + selector: 'alfa-postfach-mail-button-container', + templateUrl: './postfach-mail-button-container.component.html', + styleUrls: ['./postfach-mail-button-container.component.scss'], }) export class PostfachMailButtonContainerComponent { + private _vorgang: VorgangWithEingangResource; + public get vorgang(): VorgangWithEingangResource { + return this._vorgang; + } + @Input() + public set vorgang(value: VorgangWithEingangResource) { + this._vorgang = value; + if (isNotNull(value) && hasLink(value, VorgangHeaderLinkRel.POSTFACH_MAILS)) { + this.loadPostfachMailListStateResource(); + this.loadPendingSendPostfachMailCommand(); + } + } + @Input() showAsIconButton: boolean; + @Input() text: string; + @Input() toolTip: string; - private _vorgang: VorgangWithEingangResource; - public get vorgang(): VorgangWithEingangResource { - return this._vorgang; - } - @Input() - public set vorgang(value: VorgangWithEingangResource) { - this._vorgang = value; - if (isNotNull(value) && hasLink(value, VorgangHeaderLinkRel.POSTFACH_MAILS)) { - this.loadPostfachMailListStateResource(); - this.loadPendingSendPostfachMailCommand(); - } - } - @Input() showAsIconButton: boolean; - @Input() text: string; - @Input() toolTip: string; + pendingSendPostfachMailCommand$: Observable<StateResource<CommandResource>>; + postfachMailListStateResource$: Observable<StateResource<PostfachMailListResource>>; - pendingSendPostfachMailCommand$: Observable<StateResource<CommandResource>>; - postfachMailListStateResource$: Observable<StateResource<PostfachMailListResource>>; + dialogRef: MatDialogRef<FixedDialogComponent>; - dialogRef: MatDialogRef<FixedDialogComponent>; + readonly postfachMailListLinkRel = PostfachMailListLinkRel; - readonly postfachMailListLinkRel = PostfachMailListLinkRel; + constructor( + private dialogService: DialogService, + private postfachService: PostfachService, + ) {} - constructor(private dialogService: DialogService, private postfachService: PostfachService) { } + loadPostfachMailListStateResource(): void { + this.postfachMailListStateResource$ = this.postfachService.getPostfachMailListByGivenVorgang( + this.vorgang, + ); + } - loadPostfachMailListStateResource(): void { - this.postfachMailListStateResource$ = this.postfachService.getPostfachMailListByGivenVorgang(this.vorgang); - } + loadPendingSendPostfachMailCommand(): void { + this.pendingSendPostfachMailCommand$ = this.postfachService + .getPendingSendPostfachMailCommand() + .pipe(tap((commandStateResource) => this.closeDialog(commandStateResource))); + } - loadPendingSendPostfachMailCommand(): void { - this.pendingSendPostfachMailCommand$ = this.postfachService.getPendingSendPostfachMailCommand().pipe( - tap(commandStateResource => this.closeDialog(commandStateResource)) - ); - } + closeDialog(commandStateResource: StateResource<CommandResource>): void { + if ( + !hasError(commandStateResource) && + commandStateResource.loaded && + isNotUndefined(this.dialogRef) + ) { + this.dialogService.closeAll(); + } + } - closeDialog(commandStateResource: StateResource<CommandResource>): void { - if (!hasError(commandStateResource) && commandStateResource.loaded && isNotUndefined(this.dialogRef)) { - this.dialogService.closeAll(); - } - } + public openPostfachMailDialog( + postfachMailListStateResource: StateResource<PostfachMailListResource>, + ): void { + this.dialogRef = this.dialogService.openFixed( + this.buildDialogData(postfachMailListStateResource), + ); + } - public openPostfachMailDialog(postfachMailListStateResource: StateResource<PostfachMailListResource>): void { - this.dialogRef = this.dialogService.openFixed(this.buildDialogData(postfachMailListStateResource)); - } + private buildDialogData( + postfachMailListStateResource: StateResource<PostfachMailListResource>, + ): PostfachMailFormDialogData { + return { + component: PostfachMailFormComponent, + title: 'Neue Nachricht', + empfaenger: this.getEmpfaenger(), + postfachMailListStateResource: postfachMailListStateResource, + }; + } - private buildDialogData(postfachMailListStateResource: StateResource<PostfachMailListResource>): PostfachMailFormDialogData { - return { - component: PostfachMailFormComponent, - title: 'Neue Nachricht', - empfaenger: this.getEmpfaenger(), - postfachMailListStateResource: postfachMailListStateResource - } - } + getEmpfaenger(): string { + return this.existsAntragsteller() ? + `${this.vorgang.eingang.antragsteller.vorname} ${this.vorgang.eingang.antragsteller.nachname}` + : EMPTY_STRING; + } - getEmpfaenger(): string { - return this.existsAntragsteller() ? `${this.vorgang.eingang.antragsteller.vorname} ${this.vorgang.eingang.antragsteller.nachname}` : EMPTY_STRING; - } - - private existsAntragsteller(): boolean { - return !!this.vorgang.eingang.antragsteller; - } -} \ No newline at end of file + private existsAntragsteller(): boolean { + return !!this.vorgang.eingang.antragsteller; + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.html index f7c6609b22c151d9359225d2593f6f092e0de11b..f986125c673e993732a0ef63173068921d0af9ef 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.html @@ -23,29 +23,41 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ng-container *ngIf="postfachMailListStateResource.resource | hasLink: postfachMailListLinkRel.SEND_POSTFACH_MAIL"> - <!-- TODO Aufteilen in 3 einzelne Komponenten --> - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton && text && !toolTip" data-test-id="create-mail-button-with-text" - [showSpinner]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE" - class="create-button" - [text]="text" - icon="add" - (clickEmitter)="openPostfachNachrichtenDialog.emit()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton && !text && toolTip" data-test-id="create-mail-button-without-text" - [showSpinner]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE" - class="create-button" - [toolTip]="toolTip" - icon="add" - (clickEmitter)="openPostfachNachrichtenDialog.emit()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="send-mail-icon-button" - [showSpinner]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE" - icon="mail_outline" - toolTip="Neue Nachricht erstellen" - (clickEmitter)="openPostfachNachrichtenDialog.emit()"> - </ozgcloud-icon-button-with-spinner> - -</ng-container> \ No newline at end of file +<ng-container + *ngIf=" + postfachMailListStateResource.resource | hasLink: postfachMailListLinkRel.SEND_POSTFACH_MAIL + " +> + <!-- TODO Aufteilen in 3 einzelne Komponenten --> + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton && text && !toolTip" + data-test-id="create-mail-button-with-text" + [showSpinner]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE" + class="create-button" + [text]="text" + icon="add" + (clickEmitter)="openPostfachNachrichtenDialog.emit()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton && !text && toolTip" + data-test-id="create-mail-button-without-text" + [showSpinner]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE" + class="create-button" + [toolTip]="toolTip" + icon="add" + (clickEmitter)="openPostfachNachrichtenDialog.emit()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="send-mail-icon-button" + [showSpinner]="pendingSendPostfachMailCommand.resource | hasLink: commandLinkRel.UPDATE" + icon="mail_outline" + toolTip="Neue Nachricht erstellen" + (clickEmitter)="openPostfachNachrichtenDialog.emit()" + > + </ozgcloud-icon-button-with-spinner> +</ng-container> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.spec.ts index d18cc0b4e39fa07ca4d3f0004418138e45840dea..de10ce4ce6160fa782dff5d789f87b167ffde60a 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.spec.ts @@ -25,7 +25,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import faker from '@faker-js/faker'; import { PostfachMailListLinkRel } from '@alfa-client/postfach-shared'; import { EMPTY_STRING, HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { createCommandResource } from 'libs/command-shared/test/command'; import { createPostfachMailListResource } from 'libs/postfach-shared/test/postfach'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -33,122 +36,129 @@ import { MockComponent } from 'ng-mocks'; import { PostfachMailButtonComponent } from './postfach-mail-button.component'; describe('PostfachMailButtonComponent', () => { - let component: PostfachMailButtonComponent; - let fixture: ComponentFixture<PostfachMailButtonComponent>; - - const sendMailButtonWithText: string = getDataTestIdOf('create-mail-button-with-text'); - const sendMailButtonWithoutText: string = getDataTestIdOf('create-mail-button-without-text'); - const sendMailIconButton: string = getDataTestIdOf('send-mail-icon-button'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachMailButtonComponent, - HasLinkPipe, - MockComponent(IconButtonWithSpinnerComponent), - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PostfachMailButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('send mail button', () => { - beforeEach(() => { - component.showAsIconButton = false; - }) - - describe('with text', () => { - - beforeEach(() => { - component.text = faker.word.noun(); - component.toolTip = EMPTY_STRING; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.postfachMailListStateResource = createStateResource(createPostfachMailListResource()); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(sendMailButtonWithText); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.postfachMailListStateResource = createStateResource(createPostfachMailListResource([PostfachMailListLinkRel.SEND_POSTFACH_MAIL])); - component.pendingSendPostfachMailCommand = createStateResource(createCommandResource()); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(sendMailButtonWithText); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) - - describe('without text', () => { - - beforeEach(() => { - component.text = EMPTY_STRING; - component.toolTip = faker.word.noun(); - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.postfachMailListStateResource = createStateResource(createPostfachMailListResource()); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(sendMailButtonWithoutText); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.postfachMailListStateResource = createStateResource(createPostfachMailListResource([PostfachMailListLinkRel.SEND_POSTFACH_MAIL])); - component.pendingSendPostfachMailCommand = createStateResource(createCommandResource()); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(sendMailButtonWithoutText); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) - - }) - - describe('send mail icon button', () => { - - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.postfachMailListStateResource = createStateResource(createPostfachMailListResource()); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(sendMailIconButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.postfachMailListStateResource = createStateResource(createPostfachMailListResource([PostfachMailListLinkRel.SEND_POSTFACH_MAIL])); - component.pendingSendPostfachMailCommand = createStateResource(createCommandResource()); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(sendMailIconButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) + let component: PostfachMailButtonComponent; + let fixture: ComponentFixture<PostfachMailButtonComponent>; + + const sendMailButtonWithText: string = getDataTestIdOf('create-mail-button-with-text'); + const sendMailButtonWithoutText: string = getDataTestIdOf('create-mail-button-without-text'); + const sendMailIconButton: string = getDataTestIdOf('send-mail-icon-button'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachMailButtonComponent, + HasLinkPipe, + MockComponent(IconButtonWithSpinnerComponent), + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachMailButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('send mail button', () => { + beforeEach(() => { + component.showAsIconButton = false; + }); + + describe('with text', () => { + beforeEach(() => { + component.text = faker.word.noun(); + component.toolTip = EMPTY_STRING; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.postfachMailListStateResource = createStateResource( + createPostfachMailListResource(), + ); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(sendMailButtonWithText); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.postfachMailListStateResource = createStateResource( + createPostfachMailListResource([PostfachMailListLinkRel.SEND_POSTFACH_MAIL]), + ); + component.pendingSendPostfachMailCommand = createStateResource(createCommandResource()); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(sendMailButtonWithText); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); + + describe('without text', () => { + beforeEach(() => { + component.text = EMPTY_STRING; + component.toolTip = faker.word.noun(); + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.postfachMailListStateResource = createStateResource( + createPostfachMailListResource(), + ); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(sendMailButtonWithoutText); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.postfachMailListStateResource = createStateResource( + createPostfachMailListResource([PostfachMailListLinkRel.SEND_POSTFACH_MAIL]), + ); + component.pendingSendPostfachMailCommand = createStateResource(createCommandResource()); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(sendMailButtonWithoutText); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); + }); + + describe('send mail icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.postfachMailListStateResource = createStateResource( + createPostfachMailListResource(), + ); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(sendMailIconButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.postfachMailListStateResource = createStateResource( + createPostfachMailListResource([PostfachMailListLinkRel.SEND_POSTFACH_MAIL]), + ); + component.pendingSendPostfachMailCommand = createStateResource(createCommandResource()); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(sendMailIconButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.ts index 14bf7cf63a0f4571ff68f0bff425cd824d36ebe6..060ed15fd552d025f169110f1e87aeb4c88711dd 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-button-container/postfach-mail-button/postfach-mail-button.component.ts @@ -28,20 +28,21 @@ import { createEmptyStateResource, StateResource } from '@alfa-client/tech-share import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; @Component({ - selector: 'alfa-postfach-mail-button', - templateUrl: './postfach-mail-button.component.html', - styleUrls: ['./postfach-mail-button.component.scss'] + selector: 'alfa-postfach-mail-button', + templateUrl: './postfach-mail-button.component.html', + styleUrls: ['./postfach-mail-button.component.scss'], }) export class PostfachMailButtonComponent { + @Input() showAsIconButton: boolean; + @Input() postfachMailListStateResource: StateResource<PostfachMailListResource> = + createEmptyStateResource<PostfachMailListResource>(); + @Input() pendingSendPostfachMailCommand: StateResource<CommandResource> = + createEmptyStateResource<CommandResource>(); + @Input() text: string; + @Input() toolTip: string; - @Input() showAsIconButton: boolean; - @Input() postfachMailListStateResource: StateResource<PostfachMailListResource> = createEmptyStateResource<PostfachMailListResource>(); - @Input() pendingSendPostfachMailCommand: StateResource<CommandResource> = createEmptyStateResource<CommandResource>(); - @Input() text: string; - @Input() toolTip: string; + @Output() openPostfachNachrichtenDialog: EventEmitter<void> = new EventEmitter(); - @Output() openPostfachNachrichtenDialog: EventEmitter<void> = new EventEmitter(); - - readonly commandLinkRel = CommandLinkRel; - readonly postfachMailListLinkRel = PostfachMailListLinkRel; -} \ No newline at end of file + readonly commandLinkRel = CommandLinkRel; + readonly postfachMailListLinkRel = PostfachMailListLinkRel; +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/_postfach-mail-form.theme.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-form/_postfach-mail-form.theme.scss index d1e81f014fa214645439ed2729586bb78ab7b7bc..1824a21a62137c5f868d09cc9f93655271bbe474 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/_postfach-mail-form.theme.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/_postfach-mail-form.theme.scss @@ -22,7 +22,7 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ body.dark alfa-postfach-mail-form { - .receiver { - border-color: rgba(#fff, 0.8); - } + .receiver { + border-color: rgba(#fff, 0.8); + } } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.html index 80d11e50f34943c9fbc36500ae1514c0162c6355..54088d409e922a838fb6f4350c575af9dbd92cc7 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.html @@ -24,34 +24,39 @@ --> <div class="receiver" data-test-id="postfach-empfaenger"> - <label class="label">Empfänger</label> - <div class="value">{{ dialogData.empfaenger }}</div> + <label class="label">Empfänger</label> + <div class="value">{{ dialogData.empfaenger }}</div> </div> <form [formGroup]="formService.form" (ngSubmit)="submit()"> - - <ozgcloud-text-editor [formControlName]="formServiceClass.FIELD_SUBJECT" - label="Betreff" - [autoFocus]="true"> - </ozgcloud-text-editor> - <ozgcloud-textarea-editor [formControlName]="formServiceClass.FIELD_MAIL_BODY" - label="Text" - class="message-editor"> - </ozgcloud-textarea-editor> - - <alfa-postfach-nachricht-attachment-container [postfachNachricht]="dialogData.postfachNachricht"></alfa-postfach-nachricht-attachment-container> - - <div class="button-bar-bottom"> - - <ozgcloud-stroked-button-with-spinner data-test-id="postfach-send-button" - [stateResource]="sendInProgress$ | async" - text="Senden" - icon="send" - type="submit" - class="submit-button"> - </ozgcloud-stroked-button-with-spinner> - - <alfa-postfach-nachricht-reply-editor-container></alfa-postfach-nachricht-reply-editor-container> - </div> - + <ozgcloud-text-editor + [formControlName]="formServiceClass.FIELD_SUBJECT" + label="Betreff" + [autoFocus]="true" + > + </ozgcloud-text-editor> + <ozgcloud-textarea-editor + [formControlName]="formServiceClass.FIELD_MAIL_BODY" + label="Text" + class="message-editor" + > + </ozgcloud-textarea-editor> + + <alfa-postfach-nachricht-attachment-container + [postfachNachricht]="dialogData.postfachNachricht" + ></alfa-postfach-nachricht-attachment-container> + + <div class="button-bar-bottom"> + <ozgcloud-stroked-button-with-spinner + data-test-id="postfach-send-button" + [stateResource]="sendInProgress$ | async" + text="Senden" + icon="send" + type="submit" + class="submit-button" + > + </ozgcloud-stroked-button-with-spinner> + + <alfa-postfach-nachricht-reply-editor-container></alfa-postfach-nachricht-reply-editor-container> + </div> </form> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.scss index 25ec89ce44ffff5a7b2f080631c7b5c58e35c201..e62869c090e63ed5b7bc93aa35b8e4d74f4e6751 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.scss @@ -22,46 +22,46 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - ::ng-deep { - .mat-mdc-form-field { - width: 100%; - } + ::ng-deep { + .mat-mdc-form-field { + width: 100%; + } - textarea { - min-height: 200px; - } - } + textarea { + min-height: 200px; + } + } } .submit-button { - margin-right: 8px; + margin-right: 8px; } .message-editor { - margin-top: -30px; - display: block; + margin-top: -30px; + display: block; - ::ng-deep { - label, - .mat-lable { - visibility: hidden; - } - } + ::ng-deep { + label, + .mat-lable { + visibility: hidden; + } + } } .receiver { - display: flex; - flex-direction: column; - border-bottom: 1px solid rgba(#000, 0.4); - margin-bottom: 4px; + display: flex; + flex-direction: column; + border-bottom: 1px solid rgba(#000, 0.4); + margin-bottom: 4px; - .label { - font-size: 10.5px; - opacity: 0.6; - } + .label { + font-size: 10.5px; + opacity: 0.6; + } - .value { - margin-bottom: 4px; - min-height: 20px; - } + .value { + margin-bottom: 4px; + min-height: 20px; + } } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.spec.ts index 8cfbde1051ed451d8158fccd2af4ec11f812e866..40d4bc90cda99e87336563376dd405d63298d575 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.spec.ts @@ -30,7 +30,15 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { PostfachService } from '@alfa-client/postfach-shared'; import { createStateResource } from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; -import { DialogService, FileUploadComponent, IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent, SpinnerComponent, TextAreaEditorComponent, TextEditorComponent } from '@alfa-client/ui'; +import { + DialogService, + FileUploadComponent, + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, + SpinnerComponent, + TextAreaEditorComponent, + TextEditorComponent, +} from '@alfa-client/ui'; import { createCommandResource } from 'libs/command-shared/test/command'; import { PostfachTestFactory } from 'libs/postfach-shared/test/postfach'; import { MockComponent } from 'ng-mocks'; @@ -43,130 +51,126 @@ import { PostfachNachrichtReplyEditorContainerComponent } from './postfach-nachr import * as CommandUtil from '../../../../command-shared/src/lib/command.util'; describe('PostfachMailFormComponent', () => { - let component: PostfachMailFormComponent; - let fixture: ComponentFixture<PostfachMailFormComponent>; - - const postfachService: Mock<PostfachService> = mock(PostfachService); - const formService: PostfachMailFormservice = new PostfachMailFormservice(new FormBuilder(), useFromMock(postfachService)); - const dialogService: Mock<DialogService> = mock(DialogService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachMailFormComponent, - MockComponent(TextAreaEditorComponent), - MockComponent(TextEditorComponent), - MockComponent(IconButtonWithSpinnerComponent), - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(PostfachNachrichtReplyEditorContainerComponent), - MockComponent(SpinnerComponent), - MockComponent(FileUploadComponent), - MockComponent(PostfachNachrichtAttachmentContainerComponent) - ], - imports: [ - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule, - BrowserAnimationsModule - ], - providers: [ - { - provide: PostfachMailFormservice, - useValue: formService - }, - { - provide: PostfachService, - useValue: postfachService - }, - { - provide: DialogService, - useValue: dialogService - }, - { - provide: MAT_DIALOG_DATA, - useValue: { ...PostfachTestFactory.POSTFACH_MAIL_FORM_DIALOG_DATA, postfachNachricht: undefined } - } - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PostfachMailFormComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - describe('on existing postfachNachricht', () => { - - beforeEach(() => { - component.dialogData = PostfachTestFactory.POSTFACH_MAIL_FORM_DIALOG_DATA; - component.patchPostfachNachricht = jest.fn(); - }) - - it('should patch', () => { - component.ngOnInit(); - - expect(component.patchPostfachNachricht).toHaveBeenCalled(); - }) - }) - }) - - describe('patchPostfachNachricht', () => { - - it.skip('should do patch', () => { - component.patchPostfachNachricht(); - - expect(formService.patch).toHaveBeenCalled(); - }) - }) - - describe('submit', () => { - - beforeEach(() => { - postfachService.sendMail.mockReturnValue(of(createStateResource(createCommandResource()))); - }) - - it.skip('should submit on form', () => { - formService.submit = jest.fn(); - - component.submit(); - - expect(formService.submit).toHaveBeenCalled(); - }) - - it.skip('should close dialog', () => { - component.closeDialogsOnSuccessfulSubmit = jest.fn(); - - component.sendInProgress$.subscribe(); - component.submit(); - - expect(component.closeDialogsOnSuccessfulSubmit).toHaveBeenCalled(); - }) - }) - - describe('closeDialogsOnSuccessfulSubmit', () => { - - it('should close dialogs on successful done', () => { - jest.spyOn(CommandUtil, 'isSuccessfulDone').mockReturnValue(true); - - component.closeDialogsOnSuccessfulSubmit(createStateResource(createCommandResource())); - - expect(dialogService.closeAll).toHaveBeenCalled(); - }) - - it('should not close dialogs on NOT successful done', () => { - dialogService.closeAll.mockClear(); - jest.spyOn(CommandUtil, 'isSuccessfulDone').mockReturnValue(false); - - component.closeDialogsOnSuccessfulSubmit(createStateResource(createCommandResource())); - - expect(dialogService.closeAll).not.toHaveBeenCalled(); - }) - }) -}); \ No newline at end of file + let component: PostfachMailFormComponent; + let fixture: ComponentFixture<PostfachMailFormComponent>; + + const postfachService: Mock<PostfachService> = mock(PostfachService); + const formService: PostfachMailFormservice = new PostfachMailFormservice( + new FormBuilder(), + useFromMock(postfachService), + ); + const dialogService: Mock<DialogService> = mock(DialogService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachMailFormComponent, + MockComponent(TextAreaEditorComponent), + MockComponent(TextEditorComponent), + MockComponent(IconButtonWithSpinnerComponent), + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(PostfachNachrichtReplyEditorContainerComponent), + MockComponent(SpinnerComponent), + MockComponent(FileUploadComponent), + MockComponent(PostfachNachrichtAttachmentContainerComponent), + ], + imports: [MatFormFieldModule, MatInputModule, ReactiveFormsModule, BrowserAnimationsModule], + providers: [ + { + provide: PostfachMailFormservice, + useValue: formService, + }, + { + provide: PostfachService, + useValue: postfachService, + }, + { + provide: DialogService, + useValue: dialogService, + }, + { + provide: MAT_DIALOG_DATA, + useValue: { + ...PostfachTestFactory.POSTFACH_MAIL_FORM_DIALOG_DATA, + postfachNachricht: undefined, + }, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachMailFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + describe('on existing postfachNachricht', () => { + beforeEach(() => { + component.dialogData = PostfachTestFactory.POSTFACH_MAIL_FORM_DIALOG_DATA; + component.patchPostfachNachricht = jest.fn(); + }); + + it('should patch', () => { + component.ngOnInit(); + + expect(component.patchPostfachNachricht).toHaveBeenCalled(); + }); + }); + }); + + describe('patchPostfachNachricht', () => { + it.skip('should do patch', () => { + component.patchPostfachNachricht(); + + expect(formService.patch).toHaveBeenCalled(); + }); + }); + + describe('submit', () => { + beforeEach(() => { + postfachService.sendMail.mockReturnValue(of(createStateResource(createCommandResource()))); + }); + + it.skip('should submit on form', () => { + formService.submit = jest.fn(); + + component.submit(); + + expect(formService.submit).toHaveBeenCalled(); + }); + + it.skip('should close dialog', () => { + component.closeDialogsOnSuccessfulSubmit = jest.fn(); + + component.sendInProgress$.subscribe(); + component.submit(); + + expect(component.closeDialogsOnSuccessfulSubmit).toHaveBeenCalled(); + }); + }); + + describe('closeDialogsOnSuccessfulSubmit', () => { + it('should close dialogs on successful done', () => { + jest.spyOn(CommandUtil, 'isSuccessfulDone').mockReturnValue(true); + + component.closeDialogsOnSuccessfulSubmit(createStateResource(createCommandResource())); + + expect(dialogService.closeAll).toHaveBeenCalled(); + }); + + it('should not close dialogs on NOT successful done', () => { + dialogService.closeAll.mockClear(); + jest.spyOn(CommandUtil, 'isSuccessfulDone').mockReturnValue(false); + + component.closeDialogsOnSuccessfulSubmit(createStateResource(createCommandResource())); + + expect(dialogService.closeAll).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.ts index 3c8e0a5a68b4baf7aa25b83289130f14aa4e0f83..8082307ffa9c731904c0c93e6f137b87ec3ff5d3 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component.ts @@ -33,36 +33,47 @@ import { PostfachMailFormservice } from './postfach-mail.formservice'; import * as CommandUtil from '../../../../command-shared/src/lib/command.util'; @Component({ - selector: 'alfa-postfach-mail-form', - templateUrl: './postfach-mail-form.component.html', - styleUrls: ['./postfach-mail-form.component.scss'], - providers: [PostfachMailFormservice] + selector: 'alfa-postfach-mail-form', + templateUrl: './postfach-mail-form.component.html', + styleUrls: ['./postfach-mail-form.component.scss'], + providers: [PostfachMailFormservice], }) export class PostfachMailFormComponent implements OnInit { + public readonly formServiceClass = PostfachMailFormservice; - public readonly formServiceClass = PostfachMailFormservice; + public sendInProgress$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - public sendInProgress$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + constructor( + private dialogService: DialogService, + @Inject(MAT_DIALOG_DATA) public dialogData: PostfachMailFormDialogData, + public formService: PostfachMailFormservice, + ) {} - constructor(private dialogService: DialogService, @Inject(MAT_DIALOG_DATA) public dialogData: PostfachMailFormDialogData, public formService: PostfachMailFormservice) { } + ngOnInit(): void { + if (isNotNil(this.dialogData.postfachNachricht)) { + this.patchPostfachNachricht(); + } + } - ngOnInit(): void { - if(isNotNil(this.dialogData.postfachNachricht)){ - this.patchPostfachNachricht(); - } - } + patchPostfachNachricht(): void { + this.formService.patch(this.dialogData.postfachNachricht); + } - patchPostfachNachricht(): void { - this.formService.patch(this.dialogData.postfachNachricht); - } + public submit(): void { + this.sendInProgress$ = this.formService + .submit() + .pipe( + tap((commandStateResource: StateResource<CommandResource>) => + this.closeDialogsOnSuccessfulSubmit(commandStateResource), + ), + ); + } - public submit(): void { - this.sendInProgress$ = this.formService.submit().pipe(tap((commandStateResource: StateResource<CommandResource>) => this.closeDialogsOnSuccessfulSubmit(commandStateResource))); - } - - closeDialogsOnSuccessfulSubmit(commandStateResource: StateResource<CommandResource>): void { - if(CommandUtil.isSuccessfulDone(commandStateResource.resource)){ - this.dialogService.closeAll(); - } - } -} \ No newline at end of file + closeDialogsOnSuccessfulSubmit(commandStateResource: StateResource<CommandResource>): void { + if (CommandUtil.isSuccessfulDone(commandStateResource.resource)) { + this.dialogService.closeAll(); + } + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.spec.ts index 31dee0ef35bb274714ba9d8c2ed940284790393b..0825838a83338418ca10cc5a43bbbd001c23987a 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.spec.ts @@ -32,55 +32,56 @@ import { of } from 'rxjs'; import { PostfachMailFormservice } from './postfach-mail.formservice'; describe('PostfachMailFormservice', () => { - let formService: PostfachMailFormservice; - let service: Mock<any>; + let formService: PostfachMailFormservice; + let service: Mock<any>; - const formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + const formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); - beforeEach(() => { - service = mock(PostfachService); + beforeEach(() => { + service = mock(PostfachService); - formService = new PostfachMailFormservice(formBuilder, useFromMock(service)); - }) + formService = new PostfachMailFormservice(formBuilder, useFromMock(service)); + }); - it('should create', () => { - expect(formService).toBeTruthy(); - }); + it('should create', () => { + expect(formService).toBeTruthy(); + }); - describe('submit', () => { + describe('submit', () => { + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); + beforeEach(() => { + service.doSubmit = jest.fn(); + }); - beforeEach(() => { - service.doSubmit = jest.fn(); - }) + describe('on patch', () => { + beforeEach(() => { + service.sendExistingMail.mockReturnValue(of(commandStateResource)); + }); - describe('on patch', () => { + it('should call service', () => { + formService.source = createPostfachMailResource(); - beforeEach(() => { - service.sendExistingMail.mockReturnValue(of(commandStateResource)); - }) + formService.submit(); - it('should call service', () => { - formService.source = createPostfachMailResource(); + expect(service.sendExistingMail).toHaveBeenCalledWith( + formService.source, + formService.form.value, + ); + }); + }); - formService.submit(); + describe('on new', () => { + beforeEach(() => { + service.sendMail.mockReturnValue(of(commandStateResource)); + }); - expect(service.sendExistingMail).toHaveBeenCalledWith(formService.source, formService.form.value); - }) - }) + it('should call service', () => { + formService.submit(); - describe('on new', () => { - - beforeEach(() => { - service.sendMail.mockReturnValue(of(commandStateResource)); - }) - - it('should call service', () => { - formService.submit(); - - expect(service.sendMail).toHaveBeenCalledWith(formService.form.value); - }) - }) - }) -}) \ No newline at end of file + expect(service.sendMail).toHaveBeenCalledWith(formService.form.value); + }); + }); + }); +}); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.ts index 36b3a90325a9ccf4ba4c1967b3f951fda4787d51..3e7de900cdaa45e7ebfbbdc66994fb9b874ae594 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-mail.formservice.ts @@ -22,7 +22,12 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Injectable } from '@angular/core'; -import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { + UntypedFormArray, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, +} from '@angular/forms'; import { CommandResource } from '@alfa-client/command-shared'; import { PostfachService } from '@alfa-client/postfach-shared'; import { AbstractFormService, StateResource } from '@alfa-client/tech-shared'; @@ -31,36 +36,38 @@ import { Observable } from 'rxjs'; @Injectable() export class PostfachMailFormservice extends AbstractFormService { + static readonly FIELD_PATH_PREFIX = 'command.body'; - static readonly FIELD_PATH_PREFIX = 'command.body'; + static readonly FIELD_SUBJECT = 'subject'; + static readonly FIELD_MAIL_BODY = 'mailBody'; + static readonly FIELD_REPLY_OPTION = 'replyOption'; + static readonly FIELD_ATTACHMENTS = 'attachments'; - static readonly FIELD_SUBJECT = 'subject'; - static readonly FIELD_MAIL_BODY = 'mailBody'; - static readonly FIELD_REPLY_OPTION = 'replyOption'; - static readonly FIELD_ATTACHMENTS = 'attachments'; + constructor( + formBuilder: UntypedFormBuilder, + private postfachService: PostfachService, + ) { + super(formBuilder); + } - constructor(formBuilder: UntypedFormBuilder, private postfachService: PostfachService) { - super(formBuilder); - } + protected initForm(): UntypedFormGroup { + return this.formBuilder.group({ + [PostfachMailFormservice.FIELD_SUBJECT]: new UntypedFormControl(), + [PostfachMailFormservice.FIELD_MAIL_BODY]: new UntypedFormControl(), + [PostfachMailFormservice.FIELD_REPLY_OPTION]: new UntypedFormControl(ReplyOption.POSSIBLE), + [PostfachMailFormservice.FIELD_ATTACHMENTS]: new UntypedFormArray([]), + }); + } - protected initForm(): UntypedFormGroup { - return this.formBuilder.group({ - [PostfachMailFormservice.FIELD_SUBJECT]: new UntypedFormControl(), - [PostfachMailFormservice.FIELD_MAIL_BODY]: new UntypedFormControl(), - [PostfachMailFormservice.FIELD_REPLY_OPTION]: new UntypedFormControl(ReplyOption.POSSIBLE), - [PostfachMailFormservice.FIELD_ATTACHMENTS]: new UntypedFormArray([]), - }) - } + protected getPathPrefix(): string { + return PostfachMailFormservice.FIELD_PATH_PREFIX; + } - protected getPathPrefix(): string { - return PostfachMailFormservice.FIELD_PATH_PREFIX; - } - - protected doSubmit(): Observable<StateResource<CommandResource>> { - if(this.isPatch()){ - return this.postfachService.sendExistingMail(this.source, this.getFormValue()); - } else { - return this.postfachService.sendMail(this.getFormValue()); - } - } -} \ No newline at end of file + protected doSubmit(): Observable<StateResource<CommandResource>> { + if (this.isPatch()) { + return this.postfachService.sendExistingMail(this.source, this.getFormValue()); + } else { + return this.postfachService.sendMail(this.getFormValue()); + } + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.html index af13bbd74122e964ddb415b7d57216b9545d0b9d..e12cc398ff5f3614b4412a0ef67785b923600683 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.html @@ -1,6 +1,7 @@ <alfa-binary-file-attachment-container - [formArrayName]="formServiceClass.FIELD_ATTACHMENTS" - [existFiles]="attachments$ | async" - [uploadStateResource]="postfachNachrichtListStateResource$ | async" - [linkRelUploadAttachment]="postfachMailListLinkRel.UPLOAD_ATTACHMENT"> -</alfa-binary-file-attachment-container> \ No newline at end of file + [formArrayName]="formServiceClass.FIELD_ATTACHMENTS" + [existFiles]="attachments$ | async" + [uploadStateResource]="postfachNachrichtListStateResource$ | async" + [linkRelUploadAttachment]="postfachMailListLinkRel.UPLOAD_ATTACHMENT" +> +</alfa-binary-file-attachment-container> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.spec.ts index 73be76b640673ca4daab0296a6681a777dbc6850..aabdb18eef43734d022c70426237f5af2bf04191 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.spec.ts @@ -1,113 +1,127 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { BinaryFileAttachmentContainerComponent } from '@alfa-client/binary-file'; import { BinaryFileResource } from '@alfa-client/binary-file-shared'; -import { PostfachMailListLinkRel, PostfachMailListResource, PostfachService } from '@alfa-client/postfach-shared'; +import { + PostfachMailListLinkRel, + PostfachMailListResource, + PostfachService, +} from '@alfa-client/postfach-shared'; import { StateResource, createStateResource } from '@alfa-client/tech-shared'; import { Mock, getMockComponent, mock } from '@alfa-client/test-utils'; import { createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file'; -import { PostfachTestFactory, createPostfachMailListResource } from 'libs/postfach-shared/test/postfach'; +import { + PostfachTestFactory, + createPostfachMailListResource, +} from 'libs/postfach-shared/test/postfach'; import { MockComponent } from 'ng-mocks'; import { of } from 'rxjs'; import { PostfachMailFormservice } from '../postfach-mail.formservice'; import { PostfachNachrichtAttachmentContainerComponent } from './postfach-nachricht-attachment-container.component'; describe('PostfachNachrichtAttachmentContainerComponent', () => { - let component: PostfachNachrichtAttachmentContainerComponent; - let fixture: ComponentFixture<PostfachNachrichtAttachmentContainerComponent>; - - const service: Mock<PostfachService> = mock(PostfachService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachNachrichtAttachmentContainerComponent, - MockComponent(BinaryFileAttachmentContainerComponent) - ], - providers: [ - { - provide: PostfachService, - useValue: service - } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(PostfachNachrichtAttachmentContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - beforeEach(() => { - component.initAttachments = jest.fn(); - }) - - it('should get list stateResource', () => { - component.ngOnInit(); - - expect(service.getPostfachMailListByVorgang).toHaveBeenCalled(); - }) - - it('should initAttachments on existing postfachNachricht', () => { - component.postfachNachricht = PostfachTestFactory.POSTFACH_NACHRICHT_RESOURCE; - - component.ngOnInit(); - - expect(component.initAttachments).toHaveBeenCalled(); - }) - - it('should not init attachments on missing postfachNachricht', () => { - component.postfachNachricht = undefined; - - component.ngOnInit(); - - expect(component.initAttachments).not.toHaveBeenCalled(); - }) - }) - - describe('binary file attachment container', () => { - - it('should be called with formArrayName', () => { - const binaryFileAttachmentContainer: BinaryFileAttachmentContainerComponent = getMockComponent(fixture, BinaryFileAttachmentContainerComponent); - expect(binaryFileAttachmentContainer.formArrayName).toBe(PostfachMailFormservice.FIELD_ATTACHMENTS); - }) - - it('should be called with existFiles', () => { - const attachments: BinaryFileResource[] = [createBinaryFileResource()]; - component.attachments$ = of(attachments); - - fixture.detectChanges(); - - const binaryFileAttachmentContainer: BinaryFileAttachmentContainerComponent = getMockComponent(fixture, BinaryFileAttachmentContainerComponent); - expect(binaryFileAttachmentContainer.existFiles).toBe(attachments); - }) - - it('should be called with upload stateResource', () => { - const listStateResource: StateResource<PostfachMailListResource> = createStateResource(createPostfachMailListResource()); - component.postfachNachrichtListStateResource$ = of(listStateResource); - - fixture.detectChanges(); - - const binaryFileAttachmentContainer: BinaryFileAttachmentContainerComponent = getMockComponent(fixture, BinaryFileAttachmentContainerComponent); - expect(binaryFileAttachmentContainer.uploadStateResource).toBe(listStateResource); - }) - - it('should be called with linkRel upload attachment', () => { - const binaryFileAttachmentContainer: BinaryFileAttachmentContainerComponent = getMockComponent(fixture, BinaryFileAttachmentContainerComponent); - expect(binaryFileAttachmentContainer.linkRelUploadAttachment).toBe(PostfachMailListLinkRel.UPLOAD_ATTACHMENT); - }) - }) - - describe('ngOnDestroy', () => { - - it('should clear attachments', () => { - component.ngOnDestroy(); - - expect(service.clearAttachmentList).toHaveBeenCalled(); - }) - }) + let component: PostfachNachrichtAttachmentContainerComponent; + let fixture: ComponentFixture<PostfachNachrichtAttachmentContainerComponent>; + + const service: Mock<PostfachService> = mock(PostfachService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachNachrichtAttachmentContainerComponent, + MockComponent(BinaryFileAttachmentContainerComponent), + ], + providers: [ + { + provide: PostfachService, + useValue: service, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(PostfachNachrichtAttachmentContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + beforeEach(() => { + component.initAttachments = jest.fn(); + }); + + it('should get list stateResource', () => { + component.ngOnInit(); + + expect(service.getPostfachMailListByVorgang).toHaveBeenCalled(); + }); + + it('should initAttachments on existing postfachNachricht', () => { + component.postfachNachricht = PostfachTestFactory.POSTFACH_NACHRICHT_RESOURCE; + + component.ngOnInit(); + + expect(component.initAttachments).toHaveBeenCalled(); + }); + + it('should not init attachments on missing postfachNachricht', () => { + component.postfachNachricht = undefined; + + component.ngOnInit(); + + expect(component.initAttachments).not.toHaveBeenCalled(); + }); + }); + + describe('binary file attachment container', () => { + it('should be called with formArrayName', () => { + const binaryFileAttachmentContainer: BinaryFileAttachmentContainerComponent = + getMockComponent(fixture, BinaryFileAttachmentContainerComponent); + expect(binaryFileAttachmentContainer.formArrayName).toBe( + PostfachMailFormservice.FIELD_ATTACHMENTS, + ); + }); + + it('should be called with existFiles', () => { + const attachments: BinaryFileResource[] = [createBinaryFileResource()]; + component.attachments$ = of(attachments); + + fixture.detectChanges(); + + const binaryFileAttachmentContainer: BinaryFileAttachmentContainerComponent = + getMockComponent(fixture, BinaryFileAttachmentContainerComponent); + expect(binaryFileAttachmentContainer.existFiles).toBe(attachments); + }); + + it('should be called with upload stateResource', () => { + const listStateResource: StateResource<PostfachMailListResource> = createStateResource( + createPostfachMailListResource(), + ); + component.postfachNachrichtListStateResource$ = of(listStateResource); + + fixture.detectChanges(); + + const binaryFileAttachmentContainer: BinaryFileAttachmentContainerComponent = + getMockComponent(fixture, BinaryFileAttachmentContainerComponent); + expect(binaryFileAttachmentContainer.uploadStateResource).toBe(listStateResource); + }); + + it('should be called with linkRel upload attachment', () => { + const binaryFileAttachmentContainer: BinaryFileAttachmentContainerComponent = + getMockComponent(fixture, BinaryFileAttachmentContainerComponent); + expect(binaryFileAttachmentContainer.linkRelUploadAttachment).toBe( + PostfachMailListLinkRel.UPLOAD_ATTACHMENT, + ); + }); + }); + + describe('ngOnDestroy', () => { + it('should clear attachments', () => { + component.ngOnDestroy(); + + expect(service.clearAttachmentList).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.ts index 25cb4c08a4adf66679c8fc1cc02e2e1c8ed8c82b..425be023fedfa084dcac1d6ce6e15e9fbc9c753b 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-attachment-container/postfach-nachricht-attachment-container.component.ts @@ -1,44 +1,49 @@ import { Component, Input, OnDestroy } from '@angular/core'; import { BinaryFileResource } from '@alfa-client/binary-file-shared'; -import { PostfachMailLinkRel, PostfachMailListLinkRel, PostfachMailListResource, PostfachMailResource, PostfachService } from '@alfa-client/postfach-shared'; +import { + PostfachMailLinkRel, + PostfachMailListLinkRel, + PostfachMailListResource, + PostfachMailResource, + PostfachService, +} from '@alfa-client/postfach-shared'; import { EMPTY_ARRAY, FormProvider, StateResource, isNotNil } from '@alfa-client/tech-shared'; import { hasLink } from '@ngxp/rest'; import { Observable, of } from 'rxjs'; import { PostfachMailFormservice } from '../postfach-mail.formservice'; @Component({ - selector: 'alfa-postfach-nachricht-attachment-container', - templateUrl: './postfach-nachricht-attachment-container.component.html', - styleUrls: ['./postfach-nachricht-attachment-container.component.scss'], - viewProviders: [FormProvider] + selector: 'alfa-postfach-nachricht-attachment-container', + templateUrl: './postfach-nachricht-attachment-container.component.html', + styleUrls: ['./postfach-nachricht-attachment-container.component.scss'], + viewProviders: [FormProvider], }) export class PostfachNachrichtAttachmentContainerComponent implements OnDestroy { + @Input() postfachNachricht: PostfachMailResource; - @Input() postfachNachricht: PostfachMailResource; + postfachNachrichtListStateResource$: Observable<StateResource<PostfachMailListResource>>; + attachments$: Observable<BinaryFileResource[]> = of<BinaryFileResource[]>(EMPTY_ARRAY); - postfachNachrichtListStateResource$: Observable<StateResource<PostfachMailListResource>>; - attachments$: Observable<BinaryFileResource[]> = of<BinaryFileResource[]>(EMPTY_ARRAY); + public readonly postfachMailListLinkRel = PostfachMailListLinkRel; + public readonly formServiceClass = PostfachMailFormservice; - public readonly postfachMailListLinkRel = PostfachMailListLinkRel; - public readonly formServiceClass = PostfachMailFormservice; + constructor(private postfachService: PostfachService) {} - constructor(private postfachService: PostfachService) { } + ngOnInit(): void { + this.postfachNachrichtListStateResource$ = this.postfachService.getPostfachMailListByVorgang(); - ngOnInit(): void { - this.postfachNachrichtListStateResource$ = this.postfachService.getPostfachMailListByVorgang(); + if (isNotNil(this.postfachNachricht)) { + this.initAttachments(); + } + } - if(isNotNil(this.postfachNachricht)){ - this.initAttachments(); - } - } + initAttachments(): void { + if (hasLink(this.postfachNachricht, PostfachMailLinkRel.ATTACHMENTS)) { + this.attachments$ = this.postfachService.getAttachments(this.postfachNachricht); + } + } - initAttachments(): void { - if(hasLink(this.postfachNachricht, PostfachMailLinkRel.ATTACHMENTS)){ - this.attachments$ = this.postfachService.getAttachments(this.postfachNachricht); - } - } - - ngOnDestroy(): void { - this.postfachService.clearAttachmentList(); - } + ngOnDestroy(): void { + this.postfachService.clearAttachmentList(); + } } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.html index 26472767b9aa2f0dd9b3b3e99dd2821014697088..4d6b60475269f0c8fea1aadf4917c03875d01581 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.html @@ -1,9 +1,10 @@ <ng-container *ngIf="postfachFeatures$ | async as postfachFeatures"> - - <ozgcloud-enum-editor *ngIf="postfachFeatures.reply" data-test-id="postfach-reply-option" - [formControlName]="formServiceClass.FIELD_REPLY_OPTION" - [defaultItem]="defaultItem" - [itemList]="itemList"> - </ozgcloud-enum-editor> - -</ng-container> \ No newline at end of file + <ozgcloud-enum-editor + *ngIf="postfachFeatures.reply" + data-test-id="postfach-reply-option" + [formControlName]="formServiceClass.FIELD_REPLY_OPTION" + [defaultItem]="defaultItem" + [itemList]="itemList" + > + </ozgcloud-enum-editor> +</ng-container> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.spec.ts index e96b776c54ab99473903cc3da70b640a683b07f3..ef6570a027fa28d5536b40d0474788aba82608a3 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.spec.ts @@ -1,8 +1,18 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { FormControl, FormGroup, FormGroupDirective, ReactiveFormsModule } from '@angular/forms'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { FORBIDDEN_REPLY_OPTION_ITEM, POSSIBLE_REPLY_OPTION_ITEM, PostfachService } from '@alfa-client/postfach-shared'; -import { Mock, existsAsHtmlElement, getMockComponent, mock, notExistsAsHtmlElement } from '@alfa-client/test-utils'; +import { + FORBIDDEN_REPLY_OPTION_ITEM, + POSSIBLE_REPLY_OPTION_ITEM, + PostfachService, +} from '@alfa-client/postfach-shared'; +import { + Mock, + existsAsHtmlElement, + getMockComponent, + mock, + notExistsAsHtmlElement, +} from '@alfa-client/test-utils'; import { EnumEditorComponent } from '@alfa-client/ui'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent } from 'ng-mocks'; @@ -11,106 +21,103 @@ import { PostfachMailFormservice } from '../postfach-mail.formservice'; import { PostfachNachrichtReplyEditorContainerComponent } from './postfach-nachricht-reply-editor-container.component'; describe('PostfachNachrichtReplyEditorContainerComponent', () => { - let component: PostfachNachrichtReplyEditorContainerComponent; - let fixture: ComponentFixture<PostfachNachrichtReplyEditorContainerComponent>; - - const replyOptionEditor: string = getDataTestIdOf('postfach-reply-option'); - - const service: Mock<PostfachService> = mock(PostfachService); - - const formGroupDirective: FormGroupDirective = new FormGroupDirective([], []); - const formGroup: FormGroup = new FormGroup({ [PostfachMailFormservice.FIELD_REPLY_OPTION]: new FormControl('') }); - - beforeEach(async () => { - formGroupDirective.form = formGroup; - - await TestBed.configureTestingModule({ - declarations: [ - PostfachNachrichtReplyEditorContainerComponent, - MockComponent(EnumEditorComponent) - ], - providers: [ - { - provide: PostfachService, - useValue: service - }, - { - provide: FormGroupDirective, - useValue: formGroupDirective - } - ], - imports: [ - ReactiveFormsModule, - BrowserAnimationsModule - ], - }).compileComponents(); - - fixture = TestBed.createComponent(PostfachNachrichtReplyEditorContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should get list stateResource', () => { - component.ngOnInit(); - - expect(service.getFeatures).toHaveBeenCalled(); - }) - }) - - describe('replyOptionEditor', () => { - - describe('on available feature', () => { - - beforeEach(() => { - component.postfachFeatures$ = of({ reply: true }); - }) - - it('should be visible', () => { - fixture.detectChanges(); - - existsAsHtmlElement(fixture, replyOptionEditor); - }) - - it.skip('should be called with formControlName', () => { - fixture.detectChanges(); - - const enumEditor: EnumEditorComponent = getMockComponent(fixture, EnumEditorComponent); - expect(enumEditor.control).toBe(PostfachMailFormservice.FIELD_REPLY_OPTION); - }) - - it('should be called with defaultItem', () => { - fixture.detectChanges(); - - const enumEditor: EnumEditorComponent = getMockComponent(fixture, EnumEditorComponent); - expect(enumEditor.defaultItem).toBe(POSSIBLE_REPLY_OPTION_ITEM); - }) - - it('should be called wirh itemList', () => { - fixture.detectChanges(); - - const enumEditor: EnumEditorComponent = getMockComponent(fixture, EnumEditorComponent); - expect(enumEditor.itemList).toEqual([POSSIBLE_REPLY_OPTION_ITEM, FORBIDDEN_REPLY_OPTION_ITEM]); - }) - }) - - describe('on unavailable feature', () => { - - beforeEach(() => { - component.postfachFeatures$ = of({ reply: false }); - }) - - it('should be hidden', () => { - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, replyOptionEditor); - }) - }) - }) + let component: PostfachNachrichtReplyEditorContainerComponent; + let fixture: ComponentFixture<PostfachNachrichtReplyEditorContainerComponent>; + + const replyOptionEditor: string = getDataTestIdOf('postfach-reply-option'); + + const service: Mock<PostfachService> = mock(PostfachService); + + const formGroupDirective: FormGroupDirective = new FormGroupDirective([], []); + const formGroup: FormGroup = new FormGroup({ + [PostfachMailFormservice.FIELD_REPLY_OPTION]: new FormControl(''), + }); + + beforeEach(async () => { + formGroupDirective.form = formGroup; + + await TestBed.configureTestingModule({ + declarations: [ + PostfachNachrichtReplyEditorContainerComponent, + MockComponent(EnumEditorComponent), + ], + providers: [ + { + provide: PostfachService, + useValue: service, + }, + { + provide: FormGroupDirective, + useValue: formGroupDirective, + }, + ], + imports: [ReactiveFormsModule, BrowserAnimationsModule], + }).compileComponents(); + + fixture = TestBed.createComponent(PostfachNachrichtReplyEditorContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should get list stateResource', () => { + component.ngOnInit(); + + expect(service.getFeatures).toHaveBeenCalled(); + }); + }); + + describe('replyOptionEditor', () => { + describe('on available feature', () => { + beforeEach(() => { + component.postfachFeatures$ = of({ reply: true }); + }); + + it('should be visible', () => { + fixture.detectChanges(); + + existsAsHtmlElement(fixture, replyOptionEditor); + }); + + it.skip('should be called with formControlName', () => { + fixture.detectChanges(); + + const enumEditor: EnumEditorComponent = getMockComponent(fixture, EnumEditorComponent); + expect(enumEditor.control).toBe(PostfachMailFormservice.FIELD_REPLY_OPTION); + }); + + it('should be called with defaultItem', () => { + fixture.detectChanges(); + + const enumEditor: EnumEditorComponent = getMockComponent(fixture, EnumEditorComponent); + expect(enumEditor.defaultItem).toBe(POSSIBLE_REPLY_OPTION_ITEM); + }); + + it('should be called wirh itemList', () => { + fixture.detectChanges(); + + const enumEditor: EnumEditorComponent = getMockComponent(fixture, EnumEditorComponent); + expect(enumEditor.itemList).toEqual([ + POSSIBLE_REPLY_OPTION_ITEM, + FORBIDDEN_REPLY_OPTION_ITEM, + ]); + }); + }); + + describe('on unavailable feature', () => { + beforeEach(() => { + component.postfachFeatures$ = of({ reply: false }); + }); + + it('should be hidden', () => { + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, replyOptionEditor); + }); + }); + }); }); - diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.ts index 90679a45d09def076e7798998102c8b27ff06c46..dff70f9872dcaf71b52d57f44894a9a443f6c15d 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-form/postfach-nachricht-reply-editor-container/postfach-nachricht-reply-editor-container.component.ts @@ -1,28 +1,35 @@ import { Component, OnInit } from '@angular/core'; -import { FORBIDDEN_REPLY_OPTION_ITEM, Features, POSSIBLE_REPLY_OPTION_ITEM, PostfachService } from '@alfa-client/postfach-shared'; +import { + FORBIDDEN_REPLY_OPTION_ITEM, + Features, + POSSIBLE_REPLY_OPTION_ITEM, + PostfachService, +} from '@alfa-client/postfach-shared'; import { FormProvider } from '@alfa-client/tech-shared'; import { EnumEditorItem } from '@alfa-client/ui'; import { Observable } from 'rxjs'; import { PostfachMailFormservice } from '../postfach-mail.formservice'; @Component({ - selector: 'alfa-postfach-nachricht-reply-editor-container', - templateUrl: './postfach-nachricht-reply-editor-container.component.html', - styleUrls: ['./postfach-nachricht-reply-editor-container.component.scss'], - viewProviders: [FormProvider] + selector: 'alfa-postfach-nachricht-reply-editor-container', + templateUrl: './postfach-nachricht-reply-editor-container.component.html', + styleUrls: ['./postfach-nachricht-reply-editor-container.component.scss'], + viewProviders: [FormProvider], }) export class PostfachNachrichtReplyEditorContainerComponent implements OnInit { + public readonly itemList: EnumEditorItem[] = [ + POSSIBLE_REPLY_OPTION_ITEM, + FORBIDDEN_REPLY_OPTION_ITEM, + ]; + public readonly defaultItem: EnumEditorItem = POSSIBLE_REPLY_OPTION_ITEM; - public readonly itemList: EnumEditorItem[] = [POSSIBLE_REPLY_OPTION_ITEM, FORBIDDEN_REPLY_OPTION_ITEM]; - public readonly defaultItem: EnumEditorItem = POSSIBLE_REPLY_OPTION_ITEM; + public readonly formServiceClass = PostfachMailFormservice; - public readonly formServiceClass = PostfachMailFormservice; + public postfachFeatures$: Observable<Features>; - public postfachFeatures$: Observable<Features>; + constructor(private postfachService: PostfachService) {} - constructor(private postfachService: PostfachService){ } - - ngOnInit(): void { - this.postfachFeatures$ = this.postfachService.getFeatures(); - } + ngOnInit(): void { + this.postfachFeatures$ = this.postfachService.getFeatures(); + } } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.html index 5672f4242a78f0f080d7e913778044f4af0669aa..85355bc0ddf3c30e94bc296fa48aef74e95eb8b8 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.html @@ -23,7 +23,9 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-postfach-mail-list data-test-id="postfach-mail-list" - [vorgangStateResource]="vorgangStateResource" - [postfachMailListStateResource]="postfachMailListStateResource$ | async"> +<alfa-postfach-mail-list + data-test-id="postfach-mail-list" + [vorgangStateResource]="vorgangStateResource" + [postfachMailListStateResource]="postfachMailListStateResource$ | async" +> </alfa-postfach-mail-list> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.scss index 88952b6dcc743f7e2b415cf7ed71ed65ecf2369b..4c975e56d6cc7bf48f123ac81683536dc58e2ff6 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.scss @@ -23,5 +23,5 @@ */ :host { - overflow: hidden; -} \ No newline at end of file + overflow: hidden; +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts index 2f5f62b2578b32a61945f2fe1c8da2d5a7cfcddb..da10dd26a0af75077b0f2eadd6de558367ad250d 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.spec.ts @@ -32,78 +32,83 @@ import { PostfachMailListComponent } from './postfach-mail-list/postfach-mail-li import { createStateResource, StateResource } from '@alfa-client/tech-shared'; describe('PostfachMailListContainerComponent', () => { - let component: PostfachMailListContainerComponent; - let fixture: ComponentFixture<PostfachMailListContainerComponent>; - - const vorgangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(createVorgangWithEingangResource()); - - const postfachService = mock(PostfachService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachMailListContainerComponent, - MockComponent(PostfachMailListComponent) - ], - providers: [ - { - provide: PostfachService, - useValue: postfachService - } - ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PostfachMailListContainerComponent); - component = fixture.componentInstance; - component.vorgangStateResource = vorgangStateResource; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnChanges', () => { - - it('should call postfach service', () => { - component.ngOnChanges(); - - expect(postfachService.getPostfachMailListByGivenVorgang).toHaveBeenCalledWith(vorgangStateResource.resource); - }) - - it('should call reloadPostfachMailListOnVorgangReload', () => { - const reloadPostfachMailListOnVorgangReload = jest.spyOn(component, 'reloadPostfachMailListOnVorgangReload').mockReturnThis(); - - component.ngOnChanges(); - - expect(reloadPostfachMailListOnVorgangReload).toHaveBeenCalled(); - }); - }) - - describe('reloadPostfachMailListOnVorgangReload', () => { - - beforeEach(() => { - postfachService.setPostfachMailOnReload.mockClear(); - }); - - it('should call postfachService', () => { - component.vorgangStateResource = { ...createStateResource(createVorgangWithEingangResource()), reload: true }; - - component.reloadPostfachMailListOnVorgangReload(); - - expect(postfachService.setPostfachMailOnReload).toBeCalled(); - }); - - it('should not call postfachService', () => { - component.vorgangStateResource = { ...createStateResource(createVorgangWithEingangResource()), reload: false }; - - component.reloadPostfachMailListOnVorgangReload(); - - expect(postfachService.setPostfachMailOnReload).not.toBeCalled(); - }); - - }); + let component: PostfachMailListContainerComponent; + let fixture: ComponentFixture<PostfachMailListContainerComponent>; + + const vorgangStateResource: StateResource<VorgangWithEingangResource> = createStateResource( + createVorgangWithEingangResource(), + ); + + const postfachService = mock(PostfachService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PostfachMailListContainerComponent, MockComponent(PostfachMailListComponent)], + providers: [ + { + provide: PostfachService, + useValue: postfachService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachMailListContainerComponent); + component = fixture.componentInstance; + component.vorgangStateResource = vorgangStateResource; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnChanges', () => { + it('should call postfach service', () => { + component.ngOnChanges(); + + expect(postfachService.getPostfachMailListByGivenVorgang).toHaveBeenCalledWith( + vorgangStateResource.resource, + ); + }); + + it('should call reloadPostfachMailListOnVorgangReload', () => { + const reloadPostfachMailListOnVorgangReload = jest + .spyOn(component, 'reloadPostfachMailListOnVorgangReload') + .mockReturnThis(); + + component.ngOnChanges(); + + expect(reloadPostfachMailListOnVorgangReload).toHaveBeenCalled(); + }); + }); + + describe('reloadPostfachMailListOnVorgangReload', () => { + beforeEach(() => { + postfachService.setPostfachMailOnReload.mockClear(); + }); + + it('should call postfachService', () => { + component.vorgangStateResource = { + ...createStateResource(createVorgangWithEingangResource()), + reload: true, + }; + + component.reloadPostfachMailListOnVorgangReload(); + + expect(postfachService.setPostfachMailOnReload).toBeCalled(); + }); + + it('should not call postfachService', () => { + component.vorgangStateResource = { + ...createStateResource(createVorgangWithEingangResource()), + reload: false, + }; + + component.reloadPostfachMailListOnVorgangReload(); + + expect(postfachService.setPostfachMailOnReload).not.toBeCalled(); + }); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.ts index 67799bfd4211548c1ece82e53ab4ab8ec887fd8b..8063ec6a27b91b611f14bcafc7e8018d28eb03c1 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list-container.component.ts @@ -28,29 +28,30 @@ import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-postfach-mail-list-container', - templateUrl: './postfach-mail-list-container.component.html', - styleUrls: ['./postfach-mail-list-container.component.scss'], - providers: [{ provide: ON_PAGE, useValue: false }] + selector: 'alfa-postfach-mail-list-container', + templateUrl: './postfach-mail-list-container.component.html', + styleUrls: ['./postfach-mail-list-container.component.scss'], + providers: [{ provide: ON_PAGE, useValue: false }], }) export class PostfachMailListContainerComponent implements OnChanges { + @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; - @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; + postfachMailListStateResource$: Observable<StateResource<PostfachMailListResource>>; - postfachMailListStateResource$: Observable<StateResource<PostfachMailListResource>>; + constructor(private postfachService: PostfachService) {} - constructor(private postfachService: PostfachService) { } + ngOnChanges() { + if (isNotNull(this.vorgangStateResource)) { + this.reloadPostfachMailListOnVorgangReload(); + this.postfachMailListStateResource$ = this.postfachService.getPostfachMailListByGivenVorgang( + this.vorgangStateResource.resource, + ); + } + } - ngOnChanges() { - if (isNotNull(this.vorgangStateResource)) { - this.reloadPostfachMailListOnVorgangReload(); - this.postfachMailListStateResource$ = this.postfachService.getPostfachMailListByGivenVorgang(this.vorgangStateResource.resource); - } - } - - reloadPostfachMailListOnVorgangReload(): void { - if (this.vorgangStateResource.reload) { - this.postfachService.setPostfachMailOnReload(); - } - } + reloadPostfachMailListOnVorgangReload(): void { + if (this.vorgangStateResource.reload) { + this.postfachService.setPostfachMailOnReload(); + } + } } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.html index f3cb419aea172a6c922d89ef31231b06dce01ad7..b86ec4be3a241bf19f841bc3c5503a0e7bcac68a 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.html @@ -24,27 +24,52 @@ --> <div class="nachrichten-header"> - <h3 class="nachrichten">Nachrichten</h3> - <alfa-postfach-mail-pdf-button-container [postfachMailListResource]="postfachMailListStateResource.resource"></alfa-postfach-mail-pdf-button-container> - <ng-container *ngIf="postfachMailListStateResource.resource | hasLink: postfachMailListLinkRel.SEND_POSTFACH_MAIL"> - <alfa-postfach-mail-button-container toolTip="Neue Nachricht erstellen" [vorgang]="vorgangStateResource.resource" data-test-id="postfach-mail-button-container-no-label"></alfa-postfach-mail-button-container> - </ng-container> + <h3 class="nachrichten">Nachrichten</h3> + <alfa-postfach-mail-pdf-button-container + [postfachMailListResource]="postfachMailListStateResource.resource" + ></alfa-postfach-mail-pdf-button-container> + <ng-container + *ngIf=" + postfachMailListStateResource.resource | hasLink: postfachMailListLinkRel.SEND_POSTFACH_MAIL + " + > + <alfa-postfach-mail-button-container + toolTip="Neue Nachricht erstellen" + [vorgang]="vorgangStateResource.resource" + data-test-id="postfach-mail-button-container-no-label" + ></alfa-postfach-mail-button-container> + </ng-container> </div> <ozgcloud-spinner [stateResource]="postfachMailListStateResource"> - - <alfa-postfach-mail *ngFor="let postfachMail of postfachMailListStateResource.resource | toEmbeddedResources: postfachMailListLinkRel.POSTFACH_MAIL_LIST" - class="postfach" - [vorgangStateResource]="vorgangStateResource" - [postfachMail]="postfachMail" - [attr.data-test-id]="(postfachMail.subject | convertForDataTest) + '-item'"> - </alfa-postfach-mail> + <alfa-postfach-mail + *ngFor=" + let postfachMail of postfachMailListStateResource.resource + | toEmbeddedResources: postfachMailListLinkRel.POSTFACH_MAIL_LIST + " + class="postfach" + [vorgangStateResource]="vorgangStateResource" + [postfachMail]="postfachMail" + [attr.data-test-id]="(postfachMail.subject | convertForDataTest) + '-item'" + > + </alfa-postfach-mail> </ozgcloud-spinner> -<ng-container *ngIf="postfachMailListStateResource.resource | hasLink: postfachMailListLinkRel.SEND_POSTFACH_MAIL; else noPostfach"> - <alfa-postfach-mail-button-container text="Nachricht" [vorgang]="vorgangStateResource.resource" data-test-id="postfach-mail-button-container"></alfa-postfach-mail-button-container> +<ng-container + *ngIf=" + postfachMailListStateResource.resource | hasLink: postfachMailListLinkRel.SEND_POSTFACH_MAIL; + else noPostfach + " +> + <alfa-postfach-mail-button-container + text="Nachricht" + [vorgang]="vorgangStateResource.resource" + data-test-id="postfach-mail-button-container" + ></alfa-postfach-mail-button-container> </ng-container> <ng-template #noPostfach> - <span class="no-postfach-text" data-test-id="no-postfach-text">Dieser Vorgang ist nicht mit einem Postfach verknüpft.</span> + <span class="no-postfach-text" data-test-id="no-postfach-text" + >Dieser Vorgang ist nicht mit einem Postfach verknüpft.</span + > </ng-template> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.scss index 9151a8d5270294ff927c42cc0551ae71e43ccb96..e7c0e3c521afebcdbeaccf3dc6cd01b96456386d 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.scss @@ -22,41 +22,41 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - margin-right: 8px; - display: block; + margin-right: 8px; + display: block; } .postfach { - text-decoration: none; - display: block; - color: inherit; - margin: -4px -8px 8px -8px; - padding: 4px 8px; - border-radius: 8px; - outline: 0; + text-decoration: none; + display: block; + color: inherit; + margin: -4px -8px 8px -8px; + padding: 4px 8px; + border-radius: 8px; + outline: 0; - ::ng-deep { - .message { - opacity: 0.6; - } - } + ::ng-deep { + .message { + opacity: 0.6; + } + } } .nachrichten-header { - border-top: 1px solid rgba(0, 0, 0, 0.08); - margin-top: 16px; - padding-top: 16px; - display: flex; - width: 100%; - justify-content: space-between; - align-items: center; + border-top: 1px solid rgba(0, 0, 0, 0.08); + margin-top: 16px; + padding-top: 16px; + display: flex; + width: 100%; + justify-content: space-between; + align-items: center; - h3 { - font-weight: 500; - flex-grow: 2; - } + h3 { + font-weight: 500; + flex-grow: 2; + } - alfa-postfach-mail-pdf-button-container { - margin: 0 0.75rem; - } -} \ No newline at end of file + alfa-postfach-mail-pdf-button-container { + margin: 0 0.75rem; + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.spec.ts index abbf8b7e7a0b4ffbc232aeb9c1ea5aab9e3f441c..eabe5e991cdfd8dba9d71777bb6915d5dc02c534 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.spec.ts @@ -23,7 +23,13 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { PostfachMailListLinkRel } from '@alfa-client/postfach-shared'; -import { ConvertForDataTestPipe, HasLinkPipe, StateResource, ToEmbeddedResourcesPipe, createStateResource } from '@alfa-client/tech-shared'; +import { + ConvertForDataTestPipe, + HasLinkPipe, + StateResource, + ToEmbeddedResourcesPipe, + createStateResource, +} from '@alfa-client/tech-shared'; import { getElementFromFixture, getMockComponent } from '@alfa-client/test-utils'; import { ExpansionPanelComponent, SpinnerComponent } from '@alfa-client/ui'; import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @@ -37,89 +43,95 @@ import { PostfachMailListComponent } from './postfach-mail-list.component'; import { PostfachMailComponent } from './postfach-mail/postfach-mail.component'; describe('PostfachMailListComponent', () => { - let component: PostfachMailListComponent; - let fixture: ComponentFixture<PostfachMailListComponent>; - - const postfachMailButton: string = getDataTestIdOf('postfach-mail-button-container'); - const noPostfachText: string = getDataTestIdOf('no-postfach-text'); - - const vorgangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(createVorgangWithEingangResource()); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachMailListComponent, - ToEmbeddedResourcesPipe, - ConvertForDataTestPipe, - HasLinkPipe, - MockComponent(ExpansionPanelComponent), - MockComponent(PostfachMailComponent), - MockComponent(SpinnerComponent), - MockComponent(PostfachMailButtonContainerComponent), - MockComponent(PostfachMailPdfButtonContainerComponent) - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PostfachMailListComponent); - component = fixture.componentInstance; - component.postfachMailListStateResource = createStateResource(createPostfachMailListResource()); - component.vorgangStateResource = vorgangStateResource; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('postfach exists', () => { - - beforeEach(() => { - component.postfachMailListStateResource = createStateResource(createPostfachMailListResource([PostfachMailListLinkRel.SEND_POSTFACH_MAIL])); - component.vorgangStateResource = createStateResource(createVorgangWithEingangResource()); - fixture.detectChanges(); - }) - - it('should show button', () => { - const button = getElementFromFixture(fixture, postfachMailButton); - - expect(button).toBeInstanceOf(HTMLElement); - }) - - it('should hide text', () => { - const button = getElementFromFixture(fixture, noPostfachText); - - expect(button).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('postfach does not exists', () => { - - beforeEach(() => { - component.postfachMailListStateResource = createStateResource(createPostfachMailListResource()); - fixture.detectChanges(); - }) - - it('should hide button', () => { - const button = getElementFromFixture(fixture, postfachMailButton); - - expect(button).not.toBeInstanceOf(HTMLElement); - }) - - it('should show text', () => { - const button = getElementFromFixture(fixture, noPostfachText); - - expect(button).toBeInstanceOf(HTMLElement); - }) - }) - - describe('postfachMail component', () => { - - it('should have been called with vorgangStateResource', () => { - const postfachMailComponent: PostfachMailComponent = getMockComponent(fixture, PostfachMailComponent); - - expect(postfachMailComponent.vorgangStateResource).toBe(vorgangStateResource); - }) - }) -}) \ No newline at end of file + let component: PostfachMailListComponent; + let fixture: ComponentFixture<PostfachMailListComponent>; + + const postfachMailButton: string = getDataTestIdOf('postfach-mail-button-container'); + const noPostfachText: string = getDataTestIdOf('no-postfach-text'); + + const vorgangStateResource: StateResource<VorgangWithEingangResource> = createStateResource( + createVorgangWithEingangResource(), + ); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachMailListComponent, + ToEmbeddedResourcesPipe, + ConvertForDataTestPipe, + HasLinkPipe, + MockComponent(ExpansionPanelComponent), + MockComponent(PostfachMailComponent), + MockComponent(SpinnerComponent), + MockComponent(PostfachMailButtonContainerComponent), + MockComponent(PostfachMailPdfButtonContainerComponent), + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachMailListComponent); + component = fixture.componentInstance; + component.postfachMailListStateResource = createStateResource(createPostfachMailListResource()); + component.vorgangStateResource = vorgangStateResource; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('postfach exists', () => { + beforeEach(() => { + component.postfachMailListStateResource = createStateResource( + createPostfachMailListResource([PostfachMailListLinkRel.SEND_POSTFACH_MAIL]), + ); + component.vorgangStateResource = createStateResource(createVorgangWithEingangResource()); + fixture.detectChanges(); + }); + + it('should show button', () => { + const button = getElementFromFixture(fixture, postfachMailButton); + + expect(button).toBeInstanceOf(HTMLElement); + }); + + it('should hide text', () => { + const button = getElementFromFixture(fixture, noPostfachText); + + expect(button).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('postfach does not exists', () => { + beforeEach(() => { + component.postfachMailListStateResource = createStateResource( + createPostfachMailListResource(), + ); + fixture.detectChanges(); + }); + + it('should hide button', () => { + const button = getElementFromFixture(fixture, postfachMailButton); + + expect(button).not.toBeInstanceOf(HTMLElement); + }); + + it('should show text', () => { + const button = getElementFromFixture(fixture, noPostfachText); + + expect(button).toBeInstanceOf(HTMLElement); + }); + }); + + describe('postfachMail component', () => { + it('should have been called with vorgangStateResource', () => { + const postfachMailComponent: PostfachMailComponent = getMockComponent( + fixture, + PostfachMailComponent, + ); + + expect(postfachMailComponent.vorgangStateResource).toBe(vorgangStateResource); + }); + }); +}); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.ts index 5faaf9688219dabe8acf58fca1fcae7c0672bde5..27330617e9d1251d139d1815899f6cc74c060dc3 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail-list.component.ts @@ -27,15 +27,14 @@ import { StateResource } from '@alfa-client/tech-shared'; import { VorgangHeaderLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-postfach-mail-list', - templateUrl: './postfach-mail-list.component.html', - styleUrls: ['./postfach-mail-list.component.scss'] + selector: 'alfa-postfach-mail-list', + templateUrl: './postfach-mail-list.component.html', + styleUrls: ['./postfach-mail-list.component.scss'], }) export class PostfachMailListComponent { + @Input() postfachMailListStateResource: StateResource<PostfachMailListResource>; + @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; - @Input() postfachMailListStateResource: StateResource<PostfachMailListResource>; - @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; - - readonly postfachMailListLinkRel = PostfachMailListLinkRel; - readonly vorgangHeaderLinkRel = VorgangHeaderLinkRel; + readonly postfachMailListLinkRel = PostfachMailListLinkRel; + readonly vorgangHeaderLinkRel = VorgangHeaderLinkRel; } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.html index 0085ce94a2a46da5de136eed0af55712d1058e17..ee0ceee08de251495474cffd6d610dfe9a1a1e4e 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.html @@ -24,15 +24,21 @@ --> <a routerLink="postfach"> - <div class="mail-head"> - <div class="subject" data-test-id="mail-subject"> - <mat-icon data-test-id="reply-icon">reply</mat-icon> - <span class="overflow">{{ postfachMail.subject }}</span> - </div> - <alfa-postfach-mail-date class="date" [postfachMail]="postfachMail"></alfa-postfach-mail-date> - </div> - <div class="second-row"> - <div class="message overflow" data-test-id="mail-text">{{ postfachMail.mailBody }}</div> - <mat-icon *ngIf="(postfachMail | hasLink: postfachNachrichtLinkRel.ATTACHMENTS) && !onPage" data-test-id="postfach-nachricht-attachment-icon">attach_file</mat-icon> - </div> + <div class="mail-head"> + <div class="subject" data-test-id="mail-subject"> + <mat-icon data-test-id="reply-icon">reply</mat-icon> + <span class="overflow">{{ postfachMail.subject }}</span> + </div> + <alfa-postfach-mail-date class="date" [postfachMail]="postfachMail"></alfa-postfach-mail-date> + </div> + <div class="second-row"> + <div class="message overflow" data-test-id="mail-text"> + {{ postfachMail.mailBody }} + </div> + <mat-icon + *ngIf="(postfachMail | hasLink: postfachNachrichtLinkRel.ATTACHMENTS) && !onPage" + data-test-id="postfach-nachricht-attachment-icon" + >attach_file</mat-icon + > + </div> </a> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.scss index 46857dbd1082e80a0d48b8563d29f86c23797541..d1b40c8ec9ff1f9612526cd5ebb986cef5dd1791 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.scss @@ -22,50 +22,49 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } a { - text-decoration: none; - color: inherit; + text-decoration: none; + color: inherit; - :host-context(.postfach-links-disabled) { - pointer-events: none; - } + :host-context(.postfach-links-disabled) { + pointer-events: none; + } } .subject { - display: flex; - align-items: center; - overflow: hidden; - margin-right: 0.12rem; + display: flex; + align-items: center; + overflow: hidden; + margin-right: 0.12rem; - .mat-icon { - transform: scale(0.8); - margin-left: -4px; - } + .mat-icon { + transform: scale(0.8); + margin-left: -4px; + } } .overflow { - display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } - .mail-head { - display: flex; - white-space: nowrap; - align-items: center; - justify-content: space-between; - width: 100%; + display: flex; + white-space: nowrap; + align-items: center; + justify-content: space-between; + width: 100%; } .second-row { - display: flex; - white-space: nowrap; - justify-content: space-between; - width: 100%; + display: flex; + white-space: nowrap; + justify-content: space-between; + width: 100%; } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.spec.ts index f8a4e6f3cff1676b0eb4a1512d79316e6228467a..235b8960aa5df952824e9b8a148fe60ce67ea503 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.spec.ts @@ -36,51 +36,50 @@ import { IncommingMailComponent } from './incomming-mail.component'; registerLocaleData(localeDe); describe('IncommingMailComponent', () => { - let component: IncommingMailComponent; - let fixture: ComponentFixture<IncommingMailComponent>; + let component: IncommingMailComponent; + let fixture: ComponentFixture<IncommingMailComponent>; - const attachmentIcon: string = '[data-test-id="postfach-nachricht-attachment-icon"]'; + const attachmentIcon: string = '[data-test-id="postfach-nachricht-attachment-icon"]'; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - IncommingMailComponent, - MatIcon, - FormatDateWithTimePipe, - MockComponent(PostfachMailDateComponent), - HasLinkPipe, - MatIcon, - ], - providers: [ - { - provide: ON_PAGE, - useValue: undefined - } - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + IncommingMailComponent, + MatIcon, + FormatDateWithTimePipe, + MockComponent(PostfachMailDateComponent), + HasLinkPipe, + MatIcon, + ], + providers: [ + { + provide: ON_PAGE, + useValue: undefined, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(IncommingMailComponent); - component = fixture.componentInstance; - component.postfachMail = createPostfachMailResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(IncommingMailComponent); + component = fixture.componentInstance; + component.postfachMail = createPostfachMailResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('attachments', () => { + describe('attachments', () => { + it('should only show attachment icon on detail', () => { + component.onPage = false; + component.postfachMail = createPostfachMailResource([PostfachMailLinkRel.ATTACHMENTS]); + fixture.detectChanges(); - it('should only show attachment icon on detail', () => { - component.onPage = false; - component.postfachMail = createPostfachMailResource([PostfachMailLinkRel.ATTACHMENTS]); - fixture.detectChanges(); + const element = getElementFromFixture(fixture, attachmentIcon); - const element = getElementFromFixture(fixture, attachmentIcon); - - expect(element).toBeInstanceOf(HTMLElement); - }) - }) + expect(element).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.ts index aa428ed099a383c9b5b998562229dcd574177e8e..b57234dcf057f5f9d9a85b9f4fb50e906f22aeab 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/incomming-mail/incomming-mail.component.ts @@ -25,15 +25,14 @@ import { Component, Inject, Input } from '@angular/core'; import { ON_PAGE, PostfachMailLinkRel, PostfachMailResource } from '@alfa-client/postfach-shared'; @Component({ - selector: 'alfa-incomming-mail', - templateUrl: './incomming-mail.component.html', - styleUrls: ['./incomming-mail.component.scss'] + selector: 'alfa-incomming-mail', + templateUrl: './incomming-mail.component.html', + styleUrls: ['./incomming-mail.component.scss'], }) export class IncommingMailComponent { + readonly postfachNachrichtLinkRel = PostfachMailLinkRel; - readonly postfachNachrichtLinkRel = PostfachMailLinkRel; + constructor(@Inject(ON_PAGE) public onPage: boolean) {} - constructor(@Inject(ON_PAGE) public onPage: boolean) {} - - @Input() postfachMail: PostfachMailResource; + @Input() postfachMail: PostfachMailResource; } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.html index c0bae53d17f222af0f357836cd86a3c57344ac04..9e535996d503d2c952ab1403ae9af5822ff3e4af 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.html @@ -23,8 +23,12 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-outgoing-mail-error *ngIf="postfachMailResource | hasLink: postfachMailLinkRel.RESEND_POSTFACH_MAIL" data-test-id="outgoing-mail-error" - [postfachMailResource]="postfachMailResource" [resendPostfachMailStateResource]="resendPostfachMailStateResource$ | async" - (resend)="resendMail()" - class="error"> +<alfa-outgoing-mail-error + *ngIf="postfachMailResource | hasLink: postfachMailLinkRel.RESEND_POSTFACH_MAIL" + data-test-id="outgoing-mail-error" + [postfachMailResource]="postfachMailResource" + [resendPostfachMailStateResource]="resendPostfachMailStateResource$ | async" + (resend)="resendMail()" + class="error" +> </alfa-outgoing-mail-error> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.spec.ts index c58ec36a86621de4785900e28ddd284e2684ca66..e7ebc3b7b009552d37121a60463f38920955de2a 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.spec.ts @@ -32,66 +32,65 @@ import { HasLinkPipe } from '@alfa-client/tech-shared'; import { createPostfachMailResource } from '../../../../../../../../postfach-shared/test/postfach'; describe('OutgoingMailErrorContainerComponent', () => { - let component: OutgoingMailErrorContainerComponent; - let fixture: ComponentFixture<OutgoingMailErrorContainerComponent>; - - const postfachService = mock(PostfachService); - const mailError: string = '[data-test-id="outgoing-mail-error"]'; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - OutgoingMailErrorContainerComponent, - MockComponent(OutgoingMailErrorComponent), - HasLinkPipe - ], - providers: [ - { - provide: PostfachService, - useValue: postfachService - } - ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(OutgoingMailErrorContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('resendMail', () => { - - it('should call postfach service', () => { - component.resendMail(); - - expect(postfachService.resendMail).toHaveBeenCalled(); - }) - }) - - describe('outgoing mail error', () => { - - it('should show', () => { - component.postfachMailResource = createPostfachMailResource([PostfachMailLinkRel.RESEND_POSTFACH_MAIL]); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(mailError); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should hide', () => { - component.postfachMailResource = createPostfachMailResource(); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(mailError); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) + let component: OutgoingMailErrorContainerComponent; + let fixture: ComponentFixture<OutgoingMailErrorContainerComponent>; + + const postfachService = mock(PostfachService); + const mailError: string = '[data-test-id="outgoing-mail-error"]'; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + OutgoingMailErrorContainerComponent, + MockComponent(OutgoingMailErrorComponent), + HasLinkPipe, + ], + providers: [ + { + provide: PostfachService, + useValue: postfachService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(OutgoingMailErrorContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('resendMail', () => { + it('should call postfach service', () => { + component.resendMail(); + + expect(postfachService.resendMail).toHaveBeenCalled(); + }); + }); + + describe('outgoing mail error', () => { + it('should show', () => { + component.postfachMailResource = createPostfachMailResource([ + PostfachMailLinkRel.RESEND_POSTFACH_MAIL, + ]); + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector(mailError); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should hide', () => { + component.postfachMailResource = createPostfachMailResource(); + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector(mailError); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.ts index 28ee1d34c1e83510df17d8c518da5d65bf6455a7..cd07363612c2d377b1dadd166e26211ff818cde5 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error-container.component.ts @@ -25,28 +25,32 @@ import { Component, Input, OnInit } from '@angular/core'; import { StateResource } from '@alfa-client/tech-shared'; import { CommandResource } from '@alfa-client/command-shared'; import { Observable } from 'rxjs'; -import { PostfachMailLinkRel, PostfachMailResource, PostfachService } from '@alfa-client/postfach-shared'; +import { + PostfachMailLinkRel, + PostfachMailResource, + PostfachService, +} from '@alfa-client/postfach-shared'; @Component({ - selector: 'alfa-outgoing-mail-error-container', - templateUrl: './outgoing-mail-error-container.component.html', - styleUrls: ['./outgoing-mail-error-container.component.scss'] + selector: 'alfa-outgoing-mail-error-container', + templateUrl: './outgoing-mail-error-container.component.html', + styleUrls: ['./outgoing-mail-error-container.component.scss'], }) export class OutgoingMailErrorContainerComponent implements OnInit { + @Input() postfachMailResource: PostfachMailResource; - @Input() postfachMailResource: PostfachMailResource; + resendPostfachMailStateResource$: Observable<StateResource<CommandResource>>; - resendPostfachMailStateResource$: Observable<StateResource<CommandResource>>; + readonly postfachMailLinkRel = PostfachMailLinkRel; - readonly postfachMailLinkRel = PostfachMailLinkRel; + constructor(private postfachService: PostfachService) {} - constructor(private postfachService: PostfachService) { } + resendMail() { + this.postfachService.resendMail(this.postfachMailResource); + } - resendMail() { - this.postfachService.resendMail(this.postfachMailResource); - } - - ngOnInit() { - this.resendPostfachMailStateResource$ = this.postfachService.getPendingSendPostfachMailCommand(); - } + ngOnInit() { + this.resendPostfachMailStateResource$ = + this.postfachService.getPendingSendPostfachMailCommand(); + } } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.html index 1f474e48d20612b3006277687c80efcc0882e2da..ba6a2c55856a17a9780c64cbb785fd4ea54f96b8 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.html @@ -23,15 +23,23 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<div *ngIf="postfachMailResource.messageCode" data-test-id="mail-send-error" class="mail-send-error"> - <span data-test-id="mail-send-error-text">{{ message }}</span> - <mat-icon data-test-id="mail-send-error-icon" class="mail-send-error__icon mat-icon-error">error_outline_white</mat-icon> +<div + *ngIf="postfachMailResource.messageCode" + data-test-id="mail-send-error" + class="mail-send-error" +> + <span data-test-id="mail-send-error-text">{{ message }}</span> + <mat-icon data-test-id="mail-send-error-icon" class="mail-send-error__icon mat-icon-error" + >error_outline_white</mat-icon + > </div> <!-- TODO Eigene Component fuer den Button --> -<ozgcloud-stroked-button-with-spinner dataTestId="mail-resend-button" - text="Erneut versuchen" - icon="autorenew" - [stateResource]="resendPostfachMailStateResource" - (clickEmitter)="resend.emit()"> +<ozgcloud-stroked-button-with-spinner + dataTestId="mail-resend-button" + text="Erneut versuchen" + icon="autorenew" + [stateResource]="resendPostfachMailStateResource" + (clickEmitter)="resend.emit()" +> </ozgcloud-stroked-button-with-spinner> -<!-- --> \ No newline at end of file +<!-- --> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.scss index 26a6ba4cebce822a7dd671debd3156d47c59b593..d62fb722598b2db40eaa946e2e79722616ecaf0d 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.scss @@ -25,27 +25,27 @@ @use '@angular/material' as mat; @import 'variables'; -.mat-icon-error{ - color: mat.get-color-from-palette($warnPalette); +.mat-icon-error { + color: mat.get-color-from-palette($warnPalette); } .mail-send-error { - display: flex; - align-items: center; + display: flex; + align-items: center; - span { - margin-right: 8px; - } + span { + margin-right: 8px; + } - margin: 8px 0 16px; + margin: 8px 0 16px; - &__icon { - flex-shrink: 0; - overflow: hidden; - } + &__icon { + flex-shrink: 0; + overflow: hidden; + } } ozgcloud-stroked-button-with-spinner { - display: block; - margin-bottom: 8px; + display: block; + margin-bottom: 8px; } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.spec.ts index 8352dbee402dfb35d2e753c77c3f008f7780c041..608d25f5582f3a6dc109682059111b17511f65f4 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.spec.ts @@ -31,40 +31,39 @@ import { MockComponent } from 'ng-mocks'; import { OutgoingMailErrorComponent } from './outgoing-mail-error.component'; describe('OutgoingMailFailedComponent', () => { - let component: OutgoingMailErrorComponent; - let fixture: ComponentFixture<OutgoingMailErrorComponent>; + let component: OutgoingMailErrorComponent; + let fixture: ComponentFixture<OutgoingMailErrorComponent>; - const mailSendError: string = getDataTestIdOf('mail-send-error'); + const mailSendError: string = getDataTestIdOf('mail-send-error'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - OutgoingMailErrorComponent, - MatIcon, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent) - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + OutgoingMailErrorComponent, + MatIcon, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(OutgoingMailErrorComponent); - component = fixture.componentInstance; - component.postfachMailResource = createPostfachMailResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(OutgoingMailErrorComponent); + component = fixture.componentInstance; + component.postfachMailResource = createPostfachMailResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('mailSendError', () => { + describe('mailSendError', () => { + it('should hide if messageCode does not exists', () => { + component.postfachMailResource = { ...createPostfachMailResource(), messageCode: undefined }; - it('should hide if messageCode does not exists', () => { - component.postfachMailResource = { ...createPostfachMailResource(), messageCode: undefined }; + fixture.detectChanges(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, mailSendError); - }) - }) -}); \ No newline at end of file + notExistsAsHtmlElement(fixture, mailSendError); + }); + }); +}); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.ts index f1e83f13a90bc9376512a1f7009a13cdd8bd7ddc..65c8b892f897722859edfceaa10610d0c19c38c8 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail-error-container/outgoing-mail-error/outgoing-mail-error.component.ts @@ -27,18 +27,17 @@ import { PostfachMailResource, getMessageCodeMessage } from '@alfa-client/postfa import { StateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-outgoing-mail-error', - templateUrl: './outgoing-mail-error.component.html', - styleUrls: ['./outgoing-mail-error.component.scss'] + selector: 'alfa-outgoing-mail-error', + templateUrl: './outgoing-mail-error.component.html', + styleUrls: ['./outgoing-mail-error.component.scss'], }) export class OutgoingMailErrorComponent { + @Input() resendPostfachMailStateResource: StateResource<CommandResource>; + @Input() postfachMailResource: PostfachMailResource; - @Input() resendPostfachMailStateResource: StateResource<CommandResource>; - @Input() postfachMailResource: PostfachMailResource; + @Output() public resend: EventEmitter<void> = new EventEmitter(); - @Output() public resend: EventEmitter<void> = new EventEmitter(); - - get message(): string { - return getMessageCodeMessage(this.postfachMailResource); - } + get message(): string { + return getMessageCodeMessage(this.postfachMailResource); + } } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.html index 54dcde06efe37bc02ed2d6e0974888fd7c710365..a0eae4cd2db4f01c9dcbcb39954962491bffccde 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.html @@ -23,23 +23,43 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<a [ngClass]="{ error: postfachMail | hasLink: postfachNachrichtLinkRel.RESEND_POSTFACH_MAIL }" routerLink="postfach"> - <div class="mail-head"> - <alfa-user-profile-in-postfach-mail-container *ngIf="postfachMail | hasLink: postfachNachrichtLinkRel.CREATED_BY" - [postfachMail]="postfachMail"> - </alfa-user-profile-in-postfach-mail-container> +<a + [ngClass]="{ error: postfachMail | hasLink: postfachNachrichtLinkRel.RESEND_POSTFACH_MAIL }" + routerLink="postfach" +> + <div class="mail-head"> + <alfa-user-profile-in-postfach-mail-container + *ngIf="postfachMail | hasLink: postfachNachrichtLinkRel.CREATED_BY" + [postfachMail]="postfachMail" + > + </alfa-user-profile-in-postfach-mail-container> - <alfa-postfach-mail-date *ngIf="postfachMail.sentAt" [postfachMail]="postfachMail" data-test-id="postfach-outgoing-nachricht-date"></alfa-postfach-mail-date> - </div> + <alfa-postfach-mail-date + *ngIf="postfachMail.sentAt" + [postfachMail]="postfachMail" + data-test-id="postfach-outgoing-nachricht-date" + ></alfa-postfach-mail-date> + </div> - <span class="overflow subject" data-test-id="mail-subject">{{ postfachMail.subject }}</span> - <div class="message overflow" data-test-id="mail-text">{{ postfachMail.mailBody }}</div> + <span class="overflow subject" data-test-id="mail-subject">{{ postfachMail.subject }}</span> + <div class="message overflow" data-test-id="mail-text"> + {{ postfachMail.mailBody }} + </div> - <mat-icon *ngIf="(postfachMail | hasLink: postfachNachrichtLinkRel.ATTACHMENTS) && !onPage" data-test-id="postfach-nachricht-attachment-icon">attach_file</mat-icon> + <mat-icon + *ngIf="(postfachMail | hasLink: postfachNachrichtLinkRel.ATTACHMENTS) && !onPage" + data-test-id="postfach-nachricht-attachment-icon" + >attach_file</mat-icon + > </a> -<alfa-outgoing-mail-error-container [postfachMailResource]="postfachMail"></alfa-outgoing-mail-error-container> -<alfa-postfach-nachricht-edit-button-container *ngIf="(postfachMail | hasLink: postfachNachrichtLinkRel.EDIT) && !onPage" data-test-id="postfach-nachricht-edit-button-container" - [postfachNachricht]="postfachMail" - [vorgangStateResource]="vorgangStateResource"> -</alfa-postfach-nachricht-edit-button-container> \ No newline at end of file +<alfa-outgoing-mail-error-container + [postfachMailResource]="postfachMail" +></alfa-outgoing-mail-error-container> +<alfa-postfach-nachricht-edit-button-container + *ngIf="(postfachMail | hasLink: postfachNachrichtLinkRel.EDIT) && !onPage" + data-test-id="postfach-nachricht-edit-button-container" + [postfachNachricht]="postfachMail" + [vorgangStateResource]="vorgangStateResource" +> +</alfa-postfach-nachricht-edit-button-container> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.scss index cd4c69a1c3b684cc5d7434e8e2da083949c9c83b..96e857eb6c6ecb6594d002ac8171fbedb7375f22 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.scss @@ -22,48 +22,48 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ a { - text-decoration: none; - color: inherit; + text-decoration: none; + color: inherit; - :host-context(.postfach-links-disabled) { - pointer-events: none; - } + :host-context(.postfach-links-disabled) { + pointer-events: none; + } - .message { - margin-bottom: 0.25rem; - } + .message { + margin-bottom: 0.25rem; + } } .overflow { - display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; } .mail-head { - display: flex; - white-space: nowrap; - align-items: center; - overflow: hidden; + display: flex; + white-space: nowrap; + align-items: center; + overflow: hidden; - // TODO Do not use ::ng-deep because it's marked as deprecated. - ::ng-deep { - alfa-user-icon { - transform: scale(0.7); - margin-left: -4px; - } - .user-profile { - overflow: hidden; - flex-shrink: 1; - } - } + // TODO Do not use ::ng-deep because it's marked as deprecated. + ::ng-deep { + alfa-user-icon { + transform: scale(0.7); + margin-left: -4px; + } + .user-profile { + overflow: hidden; + flex-shrink: 1; + } + } } .error { - alfa-user-profile-in-postfach-mail-container, - .message, - .subject { - opacity: 0.4; - } + alfa-user-profile-in-postfach-mail-container, + .message, + .subject { + opacity: 0.4; + } } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.spec.ts index 45295562f8f24f64e1f03f4488cdb77fb3a9257f..3123acec830495d996e2afa59be60515109c606b 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.spec.ts @@ -25,7 +25,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatIcon } from '@angular/material/icon'; import { ON_PAGE, PostfachMailLinkRel, PostfachMailResource } from '@alfa-client/postfach-shared'; import { HasLinkPipe, StateResource, createStateResource } from '@alfa-client/tech-shared'; -import { existsAsHtmlElement, getElementFromFixture, getMockComponent, notExistsAsHtmlElement } from '@alfa-client/test-utils'; +import { + existsAsHtmlElement, + getElementFromFixture, + getMockComponent, + notExistsAsHtmlElement, +} from '@alfa-client/test-utils'; import { UserProfileInPostfachMailContainerComponent } from '@alfa-client/user-profile'; import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -38,140 +43,146 @@ import { OutgoingMailComponent } from './outgoing-mail.component'; import { PostfachNachrichtEditButtonContainerComponent } from './postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component'; describe('OutgoingMailComponent', () => { - let component: OutgoingMailComponent; - let fixture: ComponentFixture<OutgoingMailComponent>; + let component: OutgoingMailComponent; + let fixture: ComponentFixture<OutgoingMailComponent>; + + const attachmentIcon: string = getDataTestIdOf('postfach-nachricht-attachment-icon'); + const postfachEditButton: string = getDataTestIdOf('postfach-nachricht-edit-button-container'); + const postfachOutgoingNachrichtDate: string = getDataTestIdOf('postfach-outgoing-nachricht-date'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + OutgoingMailComponent, + HasLinkPipe, + MatIcon, + MockComponent(OutgoingMailErrorContainerComponent), + MockComponent(PostfachMailDateComponent), + MockComponent(UserProfileInPostfachMailContainerComponent), + MockComponent(PostfachMailDateComponent), + MockComponent(PostfachNachrichtEditButtonContainerComponent), + ], + providers: [ + { + provide: ON_PAGE, + useValue: undefined, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(OutgoingMailComponent); + component = fixture.componentInstance; + component.postfachMail = createPostfachMailResource(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('attachments', () => { + it('should only show attachment icon on detail', () => { + component.onPage = false; + component.postfachMail = createPostfachMailResource([PostfachMailLinkRel.ATTACHMENTS]); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, attachmentIcon); + + expect(element).toBeInstanceOf(HTMLElement); + }); + }); + + describe('edit button container component', () => { + const postfachNachricht: PostfachMailResource = createPostfachMailResource([ + PostfachMailLinkRel.EDIT, + ]); + + describe('on existing edit link', () => { + beforeEach(() => { + component.postfachMail = postfachNachricht; + }); + + it('should be visbile', () => { + fixture.detectChanges(); + + existsAsHtmlElement(fixture, postfachEditButton); + }); + + it('should be called with postfachNachricht', () => { + fixture.detectChanges(); + + const editButtonComponent: PostfachNachrichtEditButtonContainerComponent = getMockComponent( + fixture, + PostfachNachrichtEditButtonContainerComponent, + ); + expect(editButtonComponent.postfachNachricht).toBe(postfachNachricht); + }); + + it('should be called with vorgangStateResource', () => { + const vorgangStateResource: StateResource<VorgangWithEingangResource> = createStateResource( + createVorgangWithEingangResource(), + ); + component.vorgangStateResource = vorgangStateResource; + + fixture.detectChanges(); + + const editButtonComponent: PostfachNachrichtEditButtonContainerComponent = getMockComponent( + fixture, + PostfachNachrichtEditButtonContainerComponent, + ); + expect(editButtonComponent.vorgangStateResource).toBe(vorgangStateResource); + }); + }); + + describe('on missing edit link', () => { + const postfachNachricht: PostfachMailResource = createPostfachMailResource(); + + beforeEach(() => { + component.postfachMail = postfachNachricht; + }); + + it('should not be visible', () => { + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, postfachEditButton); + }); + }); + + describe('in detail context', () => { + const postfachNachricht: PostfachMailResource = createPostfachMailResource([ + PostfachMailLinkRel.EDIT, + ]); + + beforeEach(() => { + component.onPage = true; + component.postfachMail = postfachNachricht; + }); + + it('should not be visible', () => { + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, postfachEditButton); + }); + }); + }); + + describe('date', () => { + it('should be visible if exists', () => { + component.postfachMail = createPostfachMailResource(); + + fixture.detectChanges(); + + existsAsHtmlElement(fixture, postfachOutgoingNachrichtDate); + }); - const attachmentIcon: string = getDataTestIdOf('postfach-nachricht-attachment-icon'); - const postfachEditButton: string = getDataTestIdOf('postfach-nachricht-edit-button-container'); - const postfachOutgoingNachrichtDate: string = getDataTestIdOf('postfach-outgoing-nachricht-date'); + it('should not be visible if not exists', () => { + component.postfachMail = { ...createPostfachMailResource(), sentAt: null }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - OutgoingMailComponent, - HasLinkPipe, - MatIcon, - MockComponent(OutgoingMailErrorContainerComponent), - MockComponent(PostfachMailDateComponent), - MockComponent(UserProfileInPostfachMailContainerComponent), - MockComponent(PostfachMailDateComponent), - MockComponent(PostfachNachrichtEditButtonContainerComponent) - ], - providers: [ - { - provide: ON_PAGE, - useValue: undefined - } - ] - }).compileComponents(); - }); + fixture.detectChanges(); - beforeEach(() => { - fixture = TestBed.createComponent(OutgoingMailComponent); - component = fixture.componentInstance; - component.postfachMail = createPostfachMailResource(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('attachments', () => { - - it('should only show attachment icon on detail', () => { - component.onPage = false; - component.postfachMail = createPostfachMailResource([PostfachMailLinkRel.ATTACHMENTS]); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, attachmentIcon); - - expect(element).toBeInstanceOf(HTMLElement); - }) - }) - - describe('edit button container component', () => { - - const postfachNachricht: PostfachMailResource = createPostfachMailResource([PostfachMailLinkRel.EDIT]); - - describe('on existing edit link', () => { - - beforeEach(() => { - component.postfachMail = postfachNachricht; - }) - - it('should be visbile', () => { - fixture.detectChanges(); - - existsAsHtmlElement(fixture, postfachEditButton); - }) - - it('should be called with postfachNachricht', () => { - fixture.detectChanges(); - - const editButtonComponent: PostfachNachrichtEditButtonContainerComponent = getMockComponent(fixture, PostfachNachrichtEditButtonContainerComponent); - expect(editButtonComponent.postfachNachricht).toBe(postfachNachricht); - }) - - it('should be called with vorgangStateResource', () => { - const vorgangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(createVorgangWithEingangResource()); - component.vorgangStateResource = vorgangStateResource; - - fixture.detectChanges(); - - const editButtonComponent: PostfachNachrichtEditButtonContainerComponent = getMockComponent(fixture, PostfachNachrichtEditButtonContainerComponent); - expect(editButtonComponent.vorgangStateResource).toBe(vorgangStateResource); - }) - }) - - describe('on missing edit link', () => { - - const postfachNachricht: PostfachMailResource = createPostfachMailResource(); - - beforeEach(() => { - component.postfachMail = postfachNachricht; - }) - - it('should not be visible', () => { - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, postfachEditButton); - }) - }) - - describe('in detail context', () => { - - const postfachNachricht: PostfachMailResource = createPostfachMailResource([PostfachMailLinkRel.EDIT]); - - beforeEach(() => { - component.onPage = true; - component.postfachMail = postfachNachricht; - }) - - it('should not be visible', () => { - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, postfachEditButton); - }) - }) - }) - - describe('date', () => { - - it('should be visible if exists', () => { - component.postfachMail = createPostfachMailResource(); - - fixture.detectChanges(); - - existsAsHtmlElement(fixture, postfachOutgoingNachrichtDate); - }) - - it('should not be visible if not exists', () => { - component.postfachMail = { ...createPostfachMailResource(), sentAt: null }; - - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, postfachOutgoingNachrichtDate); - }) - }) + notExistsAsHtmlElement(fixture, postfachOutgoingNachrichtDate); + }); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.ts index 1f9a499efd357691710f274d6193cfab63d3c028..9eb44a2c48f63bd3a8779a830445df2369eb1725 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/outgoing-mail.component.ts @@ -27,16 +27,15 @@ import { StateResource } from '@alfa-client/tech-shared'; import { VorgangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-outgoing-mail', - templateUrl: './outgoing-mail.component.html', - styleUrls: ['./outgoing-mail.component.scss'] + selector: 'alfa-outgoing-mail', + templateUrl: './outgoing-mail.component.html', + styleUrls: ['./outgoing-mail.component.scss'], }) export class OutgoingMailComponent { + @Input() postfachMail: PostfachMailResource; + @Input() vorgangStateResource: StateResource<VorgangResource>; - @Input() postfachMail: PostfachMailResource; - @Input() vorgangStateResource: StateResource<VorgangResource>; + readonly postfachNachrichtLinkRel = PostfachMailLinkRel; - readonly postfachNachrichtLinkRel = PostfachMailLinkRel; - - constructor(@Inject(ON_PAGE) public onPage: boolean) { } + constructor(@Inject(ON_PAGE) public onPage: boolean) {} } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.html index fe8c945fbdb7fd0f2fdfea3da8a60640a083d601..32e4bd6aebb0a4b61f2a87857b93429149499a6a 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.html @@ -1 +1,3 @@ -<ozgcloud-icon data-test-id="postfach-nachricht-edit-button" icon="edit" (click)="edit()">Bearbeiten</ozgcloud-icon> \ No newline at end of file +<ozgcloud-icon data-test-id="postfach-nachricht-edit-button" icon="edit" (click)="edit()" + >Bearbeiten</ozgcloud-icon +> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.scss index 59f95bf4f805c1b62d0fc3065a1ec0ae84a0c299..c9d5b46585a7558f891dcb316eb293fcc4b0b8ea 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.scss @@ -1,12 +1,11 @@ :host { - margin-left: 0.5rem; - cursor: pointer; + margin-left: 0.5rem; + cursor: pointer; - // TODO Do not use ::ng-deep because it's marked as deprecated. - ::ng-deep ozgcloud-icon { - mat-icon { - vertical-align: initial; - } - } + // TODO Do not use ::ng-deep because it's marked as deprecated. + ::ng-deep ozgcloud-icon { + mat-icon { + vertical-align: initial; + } + } } - diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.spec.ts index f4b5720f0b880825ebb63b978f0318615a99d60d..58fb157e90d1021e84023f057cf096017b11d4b4 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.spec.ts @@ -7,140 +7,152 @@ import { Antragsteller, VorgangWithEingangResource } from '@alfa-client/vorgang- import { createPostfachMailResource } from 'libs/postfach-shared/test/postfach'; import { PostfachMailFormComponent } from 'libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; -import { createAntragsteller, createEingang, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; +import { + createAntragsteller, + createEingang, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; import { MockComponent } from 'ng-mocks'; import { PostfachNachrichtEditButtonContainerComponent } from './postfach-nachricht-edit-button-container.component'; describe('PostfachNachrichtEditButtonContainerComponent', () => { - let component: PostfachNachrichtEditButtonContainerComponent; - let fixture: ComponentFixture<PostfachNachrichtEditButtonContainerComponent>; + let component: PostfachNachrichtEditButtonContainerComponent; + let fixture: ComponentFixture<PostfachNachrichtEditButtonContainerComponent>; - const postfachNachrichtEditButton: string = getDataTestIdOf('postfach-nachricht-edit-button'); + const postfachNachrichtEditButton: string = getDataTestIdOf('postfach-nachricht-edit-button'); - const dialogService: Mock<DialogService> = mock(DialogService); + const dialogService: Mock<DialogService> = mock(DialogService); - const postfachNachricht: PostfachMailResource = createPostfachMailResource(); + const postfachNachricht: PostfachMailResource = createPostfachMailResource(); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachNachrichtEditButtonContainerComponent, - MockComponent(OzgcloudIconComponent) - ], - providers:[ - { - provide: DialogService, - useValue: dialogService - } - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachNachrichtEditButtonContainerComponent, + MockComponent(OzgcloudIconComponent), + ], + providers: [ + { + provide: DialogService, + useValue: dialogService, + }, + ], + }).compileComponents(); - fixture = TestBed.createComponent(PostfachNachrichtEditButtonContainerComponent); - component = fixture.componentInstance; - component.postfachNachricht = postfachNachricht; - component.vorgangStateResource = createStateResource(createVorgangWithEingangResource()); - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(PostfachNachrichtEditButtonContainerComponent); + component = fixture.componentInstance; + component.postfachNachricht = postfachNachricht; + component.vorgangStateResource = createStateResource(createVorgangWithEingangResource()); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ozgcloud icon component', () => { + describe('ozgcloud icon component', () => { + it('should be called with icon', () => { + const ozgcloudIconComponent: OzgcloudIconComponent = getMockComponent( + fixture, + OzgcloudIconComponent, + ); - it('should be called with icon', () => { - const ozgcloudIconComponent: OzgcloudIconComponent = getMockComponent(fixture, OzgcloudIconComponent); + expect(ozgcloudIconComponent.icon).toBe('edit'); + }); + }); - expect(ozgcloudIconComponent.icon).toBe('edit'); - }) - }) + describe('on click on button', () => { + it('should call dialogService', () => { + dispatchEventFromFixture(fixture, postfachNachrichtEditButton, 'click'); - describe('on click on button', () => { + expect(dialogService.openFixed).toHaveBeenCalled(); + }); - it('should call dialogService', () => { - dispatchEventFromFixture(fixture, postfachNachrichtEditButton, 'click'); + it('should build dialogData', () => { + component.buildDialogData = jest.fn(); - expect(dialogService.openFixed).toHaveBeenCalled(); - }) + dispatchEventFromFixture(fixture, postfachNachrichtEditButton, 'click'); - it('should build dialogData', () => { - component.buildDialogData = jest.fn(); + expect(component.buildDialogData).toHaveBeenCalled(); + }); + }); - dispatchEventFromFixture(fixture, postfachNachrichtEditButton, 'click'); + describe('buildDialogData', () => { + it('should have title', () => { + const dialogData: PostfachMailFormDialogData = component.buildDialogData(); - expect(component.buildDialogData).toHaveBeenCalled(); - }) - }) + expect(dialogData.title).toBe('Nachricht bearbeiten'); + }); - describe('buildDialogData', () => { + it('should have component', () => { + const dialogData: PostfachMailFormDialogData = component.buildDialogData(); - it('should have title', () => { - const dialogData: PostfachMailFormDialogData = component.buildDialogData(); + expect(dialogData.component).toBe(PostfachMailFormComponent); + }); - expect(dialogData.title).toBe('Nachricht bearbeiten'); - }) + it('should have postfachNachricht', () => { + const dialogData: PostfachMailFormDialogData = component.buildDialogData(); - it('should have component', () => { - const dialogData: PostfachMailFormDialogData = component.buildDialogData(); + expect(dialogData.postfachNachricht).toBe(postfachNachricht); + }); - expect(dialogData.component).toBe(PostfachMailFormComponent); - }) + it('should get Empfaenger', () => { + component.getEmpfaenger = jest.fn(); - it('should have postfachNachricht', () => { - const dialogData: PostfachMailFormDialogData = component.buildDialogData(); + component.buildDialogData(); - expect(dialogData.postfachNachricht).toBe(postfachNachricht); - }) + expect(component.getEmpfaenger).toHaveBeenCalled(); + }); + }); - it('should get Empfaenger', () => { - component.getEmpfaenger = jest.fn(); + describe('getEmpfaenger', () => { + it('should return nachname only if exists', () => { + const antragsteller: Antragsteller = { ...createAntragsteller(), vorname: undefined }; + component.vorgangStateResource = createStateResource(createWithAntragsteller(antragsteller)); - component.buildDialogData(); + const empfaenger: string = component.getEmpfaenger(); - expect(component.getEmpfaenger).toHaveBeenCalled(); - }) - }) + expect(empfaenger).toEqual(antragsteller.nachname); + }); - describe('getEmpfaenger', () => { + it('should return vorname only if exists', () => { + const antragsteller: Antragsteller = { ...createAntragsteller(), nachname: undefined }; + component.vorgangStateResource = createStateResource(createWithAntragsteller(antragsteller)); - it('should return nachname only if exists', () => { - const antragsteller: Antragsteller = { ...createAntragsteller(), vorname: undefined }; - component.vorgangStateResource = createStateResource(createWithAntragsteller(antragsteller)); + const empfaenger: string = component.getEmpfaenger(); - const empfaenger: string = component.getEmpfaenger(); + expect(empfaenger).toEqual(antragsteller.vorname); + }); + + it('should return name and vorname if exists', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + component.vorgangStateResource = createStateResource(vorgangWithEingang); + + const empfaenger: string = component.getEmpfaenger(); - expect(empfaenger).toEqual(antragsteller.nachname); - }) + expect(empfaenger).toEqual( + `${vorgangWithEingang.eingang.antragsteller.vorname} ${vorgangWithEingang.eingang.antragsteller.nachname}`, + ); + }); - it('should return vorname only if exists', ()=> { - const antragsteller: Antragsteller = { ...createAntragsteller(), nachname: undefined }; - component.vorgangStateResource = createStateResource(createWithAntragsteller(antragsteller)); + it('should return empty string if none exists', () => { + const antragsteller: Antragsteller = { + ...createAntragsteller(), + nachname: undefined, + vorname: undefined, + }; + component.vorgangStateResource = createStateResource(createWithAntragsteller(antragsteller)); - const empfaenger: string = component.getEmpfaenger(); + const empfaenger: string = component.getEmpfaenger(); - expect(empfaenger).toEqual(antragsteller.vorname); - }) + expect(empfaenger).toEqual(EMPTY_STRING); + }); - it('should return name and vorname if exists', () => { - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - component.vorgangStateResource = createStateResource(vorgangWithEingang); - - const empfaenger: string = component.getEmpfaenger(); - - expect(empfaenger).toEqual(`${vorgangWithEingang.eingang.antragsteller.vorname} ${vorgangWithEingang.eingang.antragsteller.nachname}`); - }) - - it('should return empty string if none exists', () => { - const antragsteller: Antragsteller = { ...createAntragsteller(), nachname: undefined, vorname: undefined }; - component.vorgangStateResource = createStateResource(createWithAntragsteller(antragsteller)); - - const empfaenger: string = component.getEmpfaenger(); - - expect(empfaenger).toEqual(EMPTY_STRING); - }) - - function createWithAntragsteller(antragsteller: Antragsteller): VorgangWithEingangResource { - return { ...createVorgangWithEingangResource(), eingang: { ...createEingang(), antragsteller } }; - } - }) + function createWithAntragsteller(antragsteller: Antragsteller): VorgangWithEingangResource { + return { + ...createVorgangWithEingangResource(), + eingang: { ...createEingang(), antragsteller }, + }; + } + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.ts index 790c422a40bf0eef9cccf3777805d5ba1bf13b3c..eec257adbcb1e50627936c64d8fe2da8f7c320f4 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/outgoing-mail/postfach-nachricht-edit-button-container/postfach-nachricht-edit-button-container.component.ts @@ -6,43 +6,46 @@ import { Antragsteller, VorgangWithEingang } from '@alfa-client/vorgang-shared'; import { PostfachMailFormComponent } from 'libs/postfach/src/lib/postfach-mail-form/postfach-mail-form.component'; @Component({ - selector: 'alfa-postfach-nachricht-edit-button-container', - templateUrl: './postfach-nachricht-edit-button-container.component.html', - styleUrls: ['./postfach-nachricht-edit-button-container.component.scss'], + selector: 'alfa-postfach-nachricht-edit-button-container', + templateUrl: './postfach-nachricht-edit-button-container.component.html', + styleUrls: ['./postfach-nachricht-edit-button-container.component.scss'], }) export class PostfachNachrichtEditButtonContainerComponent { - - @Input() postfachNachricht: PostfachMailResource; - @Input() vorgangStateResource: StateResource<VorgangWithEingang>; - - constructor(private dialogService: DialogService) { } - - public edit(): void { - this.dialogService.openFixed(this.buildDialogData()); - } - - buildDialogData(): PostfachMailFormDialogData { - return { - title: 'Nachricht bearbeiten', - component: PostfachMailFormComponent, - postfachNachricht: this.postfachNachricht, - empfaenger: this.getEmpfaenger() - } - } - - getEmpfaenger(): string { - return `${this.getVorname()} ${this.getNachname()}`.trim(); - } - - private getVorname(): string { - return isNotNil(this.getAntragsteller()?.vorname) ? this.getAntragsteller().vorname : EMPTY_STRING; - } - - private getNachname(): string { - return isNotNil(this.getAntragsteller()?.nachname) ? this.getAntragsteller().nachname : EMPTY_STRING; - } - - private getAntragsteller(): Antragsteller { - return this.vorgangStateResource.resource.eingang.antragsteller; - } -} \ No newline at end of file + @Input() postfachNachricht: PostfachMailResource; + @Input() vorgangStateResource: StateResource<VorgangWithEingang>; + + constructor(private dialogService: DialogService) {} + + public edit(): void { + this.dialogService.openFixed(this.buildDialogData()); + } + + buildDialogData(): PostfachMailFormDialogData { + return { + title: 'Nachricht bearbeiten', + component: PostfachMailFormComponent, + postfachNachricht: this.postfachNachricht, + empfaenger: this.getEmpfaenger(), + }; + } + + getEmpfaenger(): string { + return `${this.getVorname()} ${this.getNachname()}`.trim(); + } + + private getVorname(): string { + return isNotNil(this.getAntragsteller()?.vorname) ? + this.getAntragsteller().vorname + : EMPTY_STRING; + } + + private getNachname(): string { + return isNotNil(this.getAntragsteller()?.nachname) ? + this.getAntragsteller().nachname + : EMPTY_STRING; + } + + private getAntragsteller(): Antragsteller { + return this.vorgangStateResource.resource.eingang.antragsteller; + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.html index 528dd178402254d881f29f2a548135d73866afc8..05831b3b1608abfbd8d66d39c61a4e4e929e8775 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.html @@ -23,6 +23,5 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-vertical-binary-file-list - [fileListResource]="attachments$ | async"> -</alfa-vertical-binary-file-list> \ No newline at end of file +<alfa-vertical-binary-file-list [fileListResource]="attachments$ | async"> +</alfa-vertical-binary-file-list> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.scss index f3eb0ce42577ae8d6ca8e5b199ebc9d28d8c004f..cf0ecf01761155e1bc2d6c562582a6020c7c0bb9 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.scss @@ -22,10 +22,10 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .files { - display: flex; - flex-wrap: wrap; - margin: 4px -4px; - flex-direction: row; - max-width: 100%; - align-items: flex-start; + display: flex; + flex-wrap: wrap; + margin: 4px -4px; + flex-direction: row; + max-width: 100%; + align-items: flex-start; } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.spec.ts index 2de06eff9df3897e94f3a998d67b425fdd28e42a..ec93d33679633ad2b8188ef3f172da48a540a336 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.spec.ts @@ -39,51 +39,52 @@ import { VerticalBinaryFileListComponent } from '@alfa-client/binary-file'; registerLocaleData(localeDe); describe('PostfachMailAttachmentsComponent', () => { - let component: PostfachMailAttachmentsComponent; - let fixture: ComponentFixture<PostfachMailAttachmentsComponent>; + let component: PostfachMailAttachmentsComponent; + let fixture: ComponentFixture<PostfachMailAttachmentsComponent>; - const postfachNachricht: PostfachMailResource = createPostfachMailResource(); + const postfachNachricht: PostfachMailResource = createPostfachMailResource(); - const postfachService: Mock<PostfachService> = mock(PostfachService); + const postfachService: Mock<PostfachService> = mock(PostfachService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachMailAttachmentsComponent, - ConvertForDataTestPipe, - MockComponent(VerticalBinaryFileListComponent), - MockComponent(SpinnerComponent) - ], - providers: [{ - provide: PostfachService, - useValue: postfachService - }] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachMailAttachmentsComponent, + ConvertForDataTestPipe, + MockComponent(VerticalBinaryFileListComponent), + MockComponent(SpinnerComponent), + ], + providers: [ + { + provide: PostfachService, + useValue: postfachService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(PostfachMailAttachmentsComponent); - component = fixture.componentInstance; - component.postfachNachricht = postfachNachricht; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(PostfachMailAttachmentsComponent); + component = fixture.componentInstance; + component.postfachNachricht = postfachNachricht; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnChanges', () => { + describe('ngOnChanges', () => { + const attachmentList: BinaryFileListResource = createBinaryFileListResource(); - const attachmentList: BinaryFileListResource = createBinaryFileListResource(); + beforeEach(() => { + postfachService.loadAttachments.mockReturnValue(of(createStateResource(attachmentList))); + }); - beforeEach(() => { - postfachService.loadAttachments.mockReturnValue(of(createStateResource(attachmentList))); - }) + it('should call service', () => { + component.ngOnChanges(); - it('should call service', () => { - component.ngOnChanges(); - - expect(postfachService.loadAttachments).toHaveBeenCalledWith(postfachNachricht); - }) - }) -}); \ No newline at end of file + expect(postfachService.loadAttachments).toHaveBeenCalledWith(postfachNachricht); + }); + }); +}); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.ts index 457848707cbbad6ed344237da591c939722ae194..e95e9e548a111d01cb1a1b9bf47206a204eb2d68 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-attachments/postfach-mail-attachments.component.ts @@ -28,19 +28,20 @@ import { createEmptyStateResource, StateResource } from '@alfa-client/tech-share import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-postfach-mail-attachments', - templateUrl: './postfach-mail-attachments.component.html', - styleUrls: ['./postfach-mail-attachments.component.scss'] + selector: 'alfa-postfach-mail-attachments', + templateUrl: './postfach-mail-attachments.component.html', + styleUrls: ['./postfach-mail-attachments.component.scss'], }) export class PostfachMailAttachmentsComponent implements OnChanges { + @Input() postfachNachricht: PostfachMailResource; - @Input() postfachNachricht: PostfachMailResource; + attachments$: Observable<StateResource<BinaryFileListResource>> = of( + createEmptyStateResource<BinaryFileListResource>(), + ); - attachments$: Observable<StateResource<BinaryFileListResource>> = of(createEmptyStateResource<BinaryFileListResource>()); + constructor(private postfachService: PostfachService) {} - constructor(private postfachService: PostfachService) { } - - ngOnChanges(): void { - this.attachments$ = this.postfachService.loadAttachments(this.postfachNachricht); - } -} \ No newline at end of file + ngOnChanges(): void { + this.attachments$ = this.postfachService.loadAttachments(this.postfachNachricht); + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.html index 3a59ea1ed473db5def2c933717f429e2bc75043b..45f379b32f9f4793377c7605e4f66a84ae7c3332 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.html @@ -24,8 +24,12 @@ --> <ng-container *ngIf="isIncomingMail; else sentAt"> - <div class="date" data-test-id="mail-created-at">{{ postfachMail.createdAt | formatDateWithTimePipe: false }}</div> + <div class="date" data-test-id="mail-created-at"> + {{ postfachMail.createdAt | formatDateWithTimePipe: false }} + </div> </ng-container> <ng-template #sentAt> - <div class="date" data-test-id="mail-sent-at">{{ postfachMail.sentAt | formatDateWithTimePipe: false }}</div> + <div class="date" data-test-id="mail-sent-at"> + {{ postfachMail.sentAt | formatDateWithTimePipe: false }} + </div> </ng-template> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.scss index 6174a4e2e83ea99fc58b138cb9bc7ace7e2ed884..68891d3304c26291de9f600fa56848c0313f3974 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.scss @@ -22,6 +22,6 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .date { - font-size: 13px; - white-space: nowrap; -} \ No newline at end of file + font-size: 13px; + white-space: nowrap; +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.spec.ts index b7eef33b3acf1b227b133c084ab6c2643c065950..2a9b7fa043d6905b1ccba46b7d4ef0dee46170e6 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.spec.ts @@ -33,70 +33,64 @@ import { PostfachMailDateComponent } from './postfach-mail-date.component'; registerLocaleData(localeDe); describe('PostfachMailDateComponent', () => { - let component: PostfachMailDateComponent; - let fixture: ComponentFixture<PostfachMailDateComponent>; - - const sentAt: string = '[data-test-id="mail-sent-at"]'; - const createdAt: string = '[data-test-id="mail-created-at"]'; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachMailDateComponent, - HasLinkPipe, - FormatDateWithTimePipe - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PostfachMailDateComponent); - component = fixture.componentInstance; - component.postfachMail = createPostfachMailResource(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('on outgoing mail', () => { - - beforeEach(() => { - component.postfachMail = { ...createPostfachMailResource(), direction: Direction.OUT }; - fixture.detectChanges(); - }) - - it('should show sentAt', () => { - const element = getElementFromFixture(fixture, sentAt); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should hide createdAt', () => { - const element = getElementFromFixture(fixture, createdAt); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('in incoming mail', () => { - - beforeEach(() => { - component.postfachMail = { ...createPostfachMailResource(), direction: Direction.IN }; - fixture.detectChanges(); - }) - - it('should show createdAt', () => { - const element = getElementFromFixture(fixture, createdAt); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should hide sentAt', () => { - const element = getElementFromFixture(fixture, sentAt); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) -}); \ No newline at end of file + let component: PostfachMailDateComponent; + let fixture: ComponentFixture<PostfachMailDateComponent>; + + const sentAt: string = '[data-test-id="mail-sent-at"]'; + const createdAt: string = '[data-test-id="mail-created-at"]'; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PostfachMailDateComponent, HasLinkPipe, FormatDateWithTimePipe], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachMailDateComponent); + component = fixture.componentInstance; + component.postfachMail = createPostfachMailResource(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('on outgoing mail', () => { + beforeEach(() => { + component.postfachMail = { ...createPostfachMailResource(), direction: Direction.OUT }; + fixture.detectChanges(); + }); + + it('should show sentAt', () => { + const element = getElementFromFixture(fixture, sentAt); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should hide createdAt', () => { + const element = getElementFromFixture(fixture, createdAt); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('in incoming mail', () => { + beforeEach(() => { + component.postfachMail = { ...createPostfachMailResource(), direction: Direction.IN }; + fixture.detectChanges(); + }); + + it('should show createdAt', () => { + const element = getElementFromFixture(fixture, createdAt); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should hide sentAt', () => { + const element = getElementFromFixture(fixture, sentAt); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); +}); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.ts index 4084b89c1f52faa8eb2dfcc5cb5a4f1fadd23e46..54c99f9d9b7e698017d4fa47e9329a53b2598b14 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail-date/postfach-mail-date.component.ts @@ -22,20 +22,23 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Component, Input } from '@angular/core'; -import { isIncomingMail, PostfachMailLinkRel, PostfachMailResource } from '@alfa-client/postfach-shared'; +import { + isIncomingMail, + PostfachMailLinkRel, + PostfachMailResource, +} from '@alfa-client/postfach-shared'; @Component({ - selector: 'alfa-postfach-mail-date', - templateUrl: './postfach-mail-date.component.html', - styleUrls: ['./postfach-mail-date.component.scss'] + selector: 'alfa-postfach-mail-date', + templateUrl: './postfach-mail-date.component.html', + styleUrls: ['./postfach-mail-date.component.scss'], }) export class PostfachMailDateComponent { + @Input() postfachMail: PostfachMailResource; - @Input() postfachMail: PostfachMailResource; + readonly postfachMailLinkRel = PostfachMailLinkRel; - readonly postfachMailLinkRel = PostfachMailLinkRel; - - get isIncomingMail(): boolean { - return isIncomingMail(this.postfachMail); - } -} \ No newline at end of file + get isIncomingMail(): boolean { + return isIncomingMail(this.postfachMail); + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.html index 1939f81fb8b438660b214b8b4a824d67d85d83ea..b22f6bc8c1124ef8da7ec8efde81761aeac5c1b1 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.html @@ -23,13 +23,23 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-incomming-mail *ngIf="isIncomingMail" data-test-id="postfach-incoming-nachricht" - [postfachMail]="postfachMail"> +<alfa-incomming-mail + *ngIf="isIncomingMail" + data-test-id="postfach-incoming-nachricht" + [postfachMail]="postfachMail" +> </alfa-incomming-mail> -<alfa-outgoing-mail *ngIf="!isIncomingMail" data-test-id="postfach-outgoing-nachricht" - [postfachMail]="postfachMail" [vorgangStateResource]="vorgangStateResource"> +<alfa-outgoing-mail + *ngIf="!isIncomingMail" + data-test-id="postfach-outgoing-nachricht" + [postfachMail]="postfachMail" + [vorgangStateResource]="vorgangStateResource" +> </alfa-outgoing-mail> -<alfa-postfach-mail-attachments *ngIf="(postfachMail | hasLink: postfachNachrichtLinkRel.ATTACHMENTS) && onPage" data-test-id="postfach-mail-attachments-container" - [postfachNachricht]="postfachMail"> +<alfa-postfach-mail-attachments + *ngIf="(postfachMail | hasLink: postfachNachrichtLinkRel.ATTACHMENTS) && onPage" + data-test-id="postfach-mail-attachments-container" + [postfachNachricht]="postfachMail" +> </alfa-postfach-mail-attachments> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.scss b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.scss index cc4a4bb982220b62720ee5b06547bac874028539..d97406de8835a273095b96b7428e2a9a36f8683c 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.scss @@ -22,24 +22,24 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - flex-direction: column; - margin-bottom: 16px; - color: inherit; + display: flex; + flex-direction: column; + margin-bottom: 16px; + color: inherit; - .line { - display: flex; - justify-content: space-between; - } + .line { + display: flex; + justify-content: space-between; + } - .overflow { - display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } + .overflow { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } - .receiver { - font-weight: 500; - } + .receiver { + font-weight: 500; + } } diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.spec.ts index 353c26f99096690ddd7cfefdcc5ae6e0c468d55e..ae620338fbbb8eba057c0fdc19d005f50e26f29e 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.spec.ts @@ -22,9 +22,18 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { Direction, ON_PAGE, PostfachMailLinkRel, PostfachMailResource } from '@alfa-client/postfach-shared'; +import { + Direction, + ON_PAGE, + PostfachMailLinkRel, + PostfachMailResource, +} from '@alfa-client/postfach-shared'; import { HasLinkPipe, StateResource, createStateResource } from '@alfa-client/tech-shared'; -import { existsAsHtmlElement, getMockComponent, notExistsAsHtmlElement } from '@alfa-client/test-utils'; +import { + existsAsHtmlElement, + getMockComponent, + notExistsAsHtmlElement, +} from '@alfa-client/test-utils'; import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { createPostfachMailResource } from 'libs/postfach-shared/test/postfach'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -36,165 +45,183 @@ import { PostfachMailAttachmentsComponent } from './postfach-mail-attachments/po import { PostfachMailComponent } from './postfach-mail.component'; describe('PostfachMailComponent', () => { - let component: PostfachMailComponent; - let fixture: ComponentFixture<PostfachMailComponent>; - - const postfachIncomingNachricht: string = getDataTestIdOf('postfach-incoming-nachricht'); - const postfachOutgoingNachricht: string = getDataTestIdOf('postfach-outgoing-nachricht'); - const postfachNachrichtAttachments: string = getDataTestIdOf('postfach-mail-attachments-container'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HasLinkPipe, - PostfachMailComponent, - MockComponent(IncommingMailComponent), - MockComponent(OutgoingMailComponent), - MockComponent(PostfachMailAttachmentsComponent) - ], - providers: [ - { - provide: ON_PAGE, - useValue: undefined - } - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(PostfachMailComponent); - component = fixture.componentInstance; - component.postfachMail = createPostfachMailResource(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('attachments component', () => { - - it('should not be visible on missing link', () => { - component.onPage = true; - component.postfachMail = createPostfachMailResource(); - - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, postfachNachrichtAttachments); - }) - - describe('on existing link and page', () => { - - const postfachNachricht: PostfachMailResource = createPostfachMailResource([PostfachMailLinkRel.ATTACHMENTS]); - - beforeEach(() => { - component.onPage = true; - component.postfachMail = postfachNachricht; - }) - - it('should be visible', () => { - fixture.detectChanges(); - - existsAsHtmlElement(fixture, postfachNachrichtAttachments); - }) - - it('should be called with postfachNachricht', () => { - fixture.detectChanges(); - - const postfachAttachmentsComponent: PostfachMailAttachmentsComponent = getMockComponent(fixture, PostfachMailAttachmentsComponent); - - expect(postfachAttachmentsComponent.postfachNachricht).toBe(postfachNachricht); - }) - }) - - }) - - describe('outgoing nachricht component', () => { - - describe('on outgoing nachricht', () => { - - const outgoingPostfachNachricht: PostfachMailResource = { ...createPostfachMailResource(), direction: Direction.OUT }; - const vorgangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(createVorgangWithEingangResource()); - - beforeEach(() => { - component.postfachMail = outgoingPostfachNachricht; - component.vorgangStateResource = vorgangStateResource; - fixture.detectChanges(); - }) - - describe('call', () => { - - it('should be with postfachNachricht', () => { - const outgoingMailComponent: OutgoingMailComponent = getMockComponent(fixture, OutgoingMailComponent); - - expect(outgoingMailComponent.postfachMail).toBe(outgoingPostfachNachricht); - }) - - it('should be with vorgangStateResource', () => { - const outgoingMailComponent: OutgoingMailComponent = getMockComponent(fixture, OutgoingMailComponent); - - expect(outgoingMailComponent.vorgangStateResource).toBe(vorgangStateResource); - }) - }) - - it('should be visible', () => { - existsAsHtmlElement(fixture, postfachOutgoingNachricht); - }) - }) - - - describe('on incoming nachricht', () => { - - const incomingPostfachNachricht: PostfachMailResource = { ...createPostfachMailResource(), direction: Direction.IN }; - - beforeEach(() => { - component.postfachMail = incomingPostfachNachricht; - fixture.detectChanges(); - }) - - it('should not be visible', () => { - notExistsAsHtmlElement(fixture, postfachOutgoingNachricht); - }) - }) - }) - - describe('incoming nachricht component', () => { - - describe('on incoming nachricht', () => { - - const incomingPostfachNachricht: PostfachMailResource = { ...createPostfachMailResource(), direction: Direction.IN }; - - beforeEach(() => { - component.postfachMail = incomingPostfachNachricht; - fixture.detectChanges(); - }) - - describe('call', () => { - - it('should be with postfachNachricht', () => { - const incomingMailComponent: IncommingMailComponent = getMockComponent(fixture, IncommingMailComponent); - - expect(incomingMailComponent.postfachMail).toBe(incomingPostfachNachricht); - }) - }) - - it('should be visible', () => { - existsAsHtmlElement(fixture, postfachIncomingNachricht); - }) - }) - - describe('on outgoing nachricht', () => { - - const outgoingPostfachNachricht: PostfachMailResource = { ...createPostfachMailResource(), direction: Direction.OUT }; - - beforeEach(() => { - component.postfachMail = outgoingPostfachNachricht; - fixture.detectChanges(); - }) - - it('should not be visible', () => { - notExistsAsHtmlElement(fixture, postfachIncomingNachricht); - }) - }) - }) + let component: PostfachMailComponent; + let fixture: ComponentFixture<PostfachMailComponent>; + + const postfachIncomingNachricht: string = getDataTestIdOf('postfach-incoming-nachricht'); + const postfachOutgoingNachricht: string = getDataTestIdOf('postfach-outgoing-nachricht'); + const postfachNachrichtAttachments: string = getDataTestIdOf( + 'postfach-mail-attachments-container', + ); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HasLinkPipe, + PostfachMailComponent, + MockComponent(IncommingMailComponent), + MockComponent(OutgoingMailComponent), + MockComponent(PostfachMailAttachmentsComponent), + ], + providers: [ + { + provide: ON_PAGE, + useValue: undefined, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(PostfachMailComponent); + component = fixture.componentInstance; + component.postfachMail = createPostfachMailResource(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('attachments component', () => { + it('should not be visible on missing link', () => { + component.onPage = true; + component.postfachMail = createPostfachMailResource(); + + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, postfachNachrichtAttachments); + }); + + describe('on existing link and page', () => { + const postfachNachricht: PostfachMailResource = createPostfachMailResource([ + PostfachMailLinkRel.ATTACHMENTS, + ]); + + beforeEach(() => { + component.onPage = true; + component.postfachMail = postfachNachricht; + }); + + it('should be visible', () => { + fixture.detectChanges(); + + existsAsHtmlElement(fixture, postfachNachrichtAttachments); + }); + + it('should be called with postfachNachricht', () => { + fixture.detectChanges(); + + const postfachAttachmentsComponent: PostfachMailAttachmentsComponent = getMockComponent( + fixture, + PostfachMailAttachmentsComponent, + ); + + expect(postfachAttachmentsComponent.postfachNachricht).toBe(postfachNachricht); + }); + }); + }); + + describe('outgoing nachricht component', () => { + describe('on outgoing nachricht', () => { + const outgoingPostfachNachricht: PostfachMailResource = { + ...createPostfachMailResource(), + direction: Direction.OUT, + }; + const vorgangStateResource: StateResource<VorgangWithEingangResource> = createStateResource( + createVorgangWithEingangResource(), + ); + + beforeEach(() => { + component.postfachMail = outgoingPostfachNachricht; + component.vorgangStateResource = vorgangStateResource; + fixture.detectChanges(); + }); + + describe('call', () => { + it('should be with postfachNachricht', () => { + const outgoingMailComponent: OutgoingMailComponent = getMockComponent( + fixture, + OutgoingMailComponent, + ); + + expect(outgoingMailComponent.postfachMail).toBe(outgoingPostfachNachricht); + }); + + it('should be with vorgangStateResource', () => { + const outgoingMailComponent: OutgoingMailComponent = getMockComponent( + fixture, + OutgoingMailComponent, + ); + + expect(outgoingMailComponent.vorgangStateResource).toBe(vorgangStateResource); + }); + }); + + it('should be visible', () => { + existsAsHtmlElement(fixture, postfachOutgoingNachricht); + }); + }); + + describe('on incoming nachricht', () => { + const incomingPostfachNachricht: PostfachMailResource = { + ...createPostfachMailResource(), + direction: Direction.IN, + }; + + beforeEach(() => { + component.postfachMail = incomingPostfachNachricht; + fixture.detectChanges(); + }); + + it('should not be visible', () => { + notExistsAsHtmlElement(fixture, postfachOutgoingNachricht); + }); + }); + }); + + describe('incoming nachricht component', () => { + describe('on incoming nachricht', () => { + const incomingPostfachNachricht: PostfachMailResource = { + ...createPostfachMailResource(), + direction: Direction.IN, + }; + + beforeEach(() => { + component.postfachMail = incomingPostfachNachricht; + fixture.detectChanges(); + }); + + describe('call', () => { + it('should be with postfachNachricht', () => { + const incomingMailComponent: IncommingMailComponent = getMockComponent( + fixture, + IncommingMailComponent, + ); + + expect(incomingMailComponent.postfachMail).toBe(incomingPostfachNachricht); + }); + }); + + it('should be visible', () => { + existsAsHtmlElement(fixture, postfachIncomingNachricht); + }); + }); + + describe('on outgoing nachricht', () => { + const outgoingPostfachNachricht: PostfachMailResource = { + ...createPostfachMailResource(), + direction: Direction.OUT, + }; + + beforeEach(() => { + component.postfachMail = outgoingPostfachNachricht; + fixture.detectChanges(); + }); + + it('should not be visible', () => { + notExistsAsHtmlElement(fixture, postfachIncomingNachricht); + }); + }); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.ts index 97de921473e1dcb26cd58ea803bbd06c38d9de8d..41f9e4879ce3133551800f72fc1eabc05d7966a4 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component.ts @@ -22,25 +22,29 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Component, Inject, Input } from '@angular/core'; -import { ON_PAGE, PostfachMailLinkRel, PostfachMailResource, isIncomingMail } from '@alfa-client/postfach-shared'; +import { + ON_PAGE, + PostfachMailLinkRel, + PostfachMailResource, + isIncomingMail, +} from '@alfa-client/postfach-shared'; import { StateResource } from '@alfa-client/tech-shared'; import { VorgangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-postfach-mail', - templateUrl: './postfach-mail.component.html', - styleUrls: ['./postfach-mail.component.scss'] + selector: 'alfa-postfach-mail', + templateUrl: './postfach-mail.component.html', + styleUrls: ['./postfach-mail.component.scss'], }) export class PostfachMailComponent { + @Input() postfachMail: PostfachMailResource; + @Input() vorgangStateResource: StateResource<VorgangResource>; - @Input() postfachMail: PostfachMailResource; - @Input() vorgangStateResource: StateResource<VorgangResource>; + readonly postfachNachrichtLinkRel = PostfachMailLinkRel; - readonly postfachNachrichtLinkRel = PostfachMailLinkRel; + constructor(@Inject(ON_PAGE) public onPage: boolean) {} - constructor(@Inject(ON_PAGE) public onPage: boolean) { } - - public get isIncomingMail(): boolean { - return isIncomingMail(this.postfachMail); - } -} \ No newline at end of file + public get isIncomingMail(): boolean { + return isIncomingMail(this.postfachMail); + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.html index 92a8242f3cef25f30ea589ba7b21830cb94aa907..e1c3644eefa56d931af315ccdc9ce178067dcbf6 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.html @@ -24,8 +24,9 @@ --> <alfa-postfach-mail-pdf-button - [isDownloadInProgress]="isDownloadPdfInProgress$ | async" - [postfachMailListResource]="postfachMailListResource" - [showButtonWithLabel]="showButtonWithLabel" - (downloadPdf)="downloadPdf()"> -</alfa-postfach-mail-pdf-button> \ No newline at end of file + [isDownloadInProgress]="isDownloadPdfInProgress$ | async" + [postfachMailListResource]="postfachMailListResource" + [showButtonWithLabel]="showButtonWithLabel" + (downloadPdf)="downloadPdf()" +> +</alfa-postfach-mail-pdf-button> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.spec.ts index 0e5a10f6adc7641ddaddb056d1f49360b5bc1439..1e3d5092657ae8b457462be420a2a0d1d1b1a016 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.spec.ts @@ -30,52 +30,48 @@ import { PostfachMailPdfButtonContainerComponent } from './postfach-mail-pdf-but import { PostfachMailPdfButtonComponent } from './postfach-mail-pdf-button/postfach-mail-pdf-button.component'; describe('PostfachMailPdfButtonContainerComponent', () => { - let component: PostfachMailPdfButtonContainerComponent; - let fixture: ComponentFixture<PostfachMailPdfButtonContainerComponent>; + let component: PostfachMailPdfButtonContainerComponent; + let fixture: ComponentFixture<PostfachMailPdfButtonContainerComponent>; - const postfachService: Mock<PostfachService> = mock(PostfachService); + const postfachService: Mock<PostfachService> = mock(PostfachService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachMailPdfButtonContainerComponent, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(PostfachMailPdfButtonComponent) - ], - providers: [ - { - provide: PostfachService, - useValue: postfachService - } - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachMailPdfButtonContainerComponent, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(PostfachMailPdfButtonComponent), + ], + providers: [ + { + provide: PostfachService, + useValue: postfachService, + }, + ], + }).compileComponents(); - fixture = TestBed.createComponent( - PostfachMailPdfButtonContainerComponent - ); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(PostfachMailPdfButtonContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should call postfachService', () => { + component.ngOnInit(); - it('should call postfachService', () => { - component.ngOnInit(); + expect(postfachService.isDownloadPdfInProgress).toHaveBeenCalled(); + }); + }); - expect(postfachService.isDownloadPdfInProgress).toHaveBeenCalled(); - }) - }) + describe('downloadPdf', () => { + it('should call service', () => { + component.downloadPdf(); - describe('downloadPdf', () => { - - it('should call service', () => { - component.downloadPdf(); - - expect(postfachService.downloadPdf).toHaveBeenCalled(); - }) - }) + expect(postfachService.downloadPdf).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.ts index 9bf59bdbe1b3d7b71a705af2717bbce965691fd8..0ef98ea9e9524c31a1ec6d1ecbbd8f540cee5c16 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button-container.component.ts @@ -26,24 +26,23 @@ import { PostfachMailResource, PostfachService } from '@alfa-client/postfach-sha import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-postfach-mail-pdf-button-container', - templateUrl: './postfach-mail-pdf-button-container.component.html', - styleUrls: ['./postfach-mail-pdf-button-container.component.scss'], + selector: 'alfa-postfach-mail-pdf-button-container', + templateUrl: './postfach-mail-pdf-button-container.component.html', + styleUrls: ['./postfach-mail-pdf-button-container.component.scss'], }) export class PostfachMailPdfButtonContainerComponent implements OnInit { + @Input() postfachMailListResource: PostfachMailResource; + @Input() showButtonWithLabel: boolean = false; - @Input() postfachMailListResource: PostfachMailResource; - @Input() showButtonWithLabel: boolean = false + isDownloadPdfInProgress$: Observable<boolean>; - isDownloadPdfInProgress$: Observable<boolean>; + constructor(private postfachService: PostfachService) {} - constructor(private postfachService: PostfachService) { } + ngOnInit(): void { + this.isDownloadPdfInProgress$ = this.postfachService.isDownloadPdfInProgress(); + } - ngOnInit(): void { - this.isDownloadPdfInProgress$ = this.postfachService.isDownloadPdfInProgress(); - } - - downloadPdf(): void { - this.postfachService.downloadPdf(); - } -} \ No newline at end of file + downloadPdf(): void { + this.postfachService.downloadPdf(); + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.html b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.html index ba19cb8fdb7b9ceacd92608f2b705a638fa61438..e4c52402f15485291df55f02840445010dd237f3 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.html @@ -24,22 +24,25 @@ --> <ng-container *ngIf="postfachMailCount != postfachNachrichtenCount.NONE"> - - <ng-container *ngIf="showButtonWithLabel; else showButton"> - <ozgcloud-stroked-button-with-spinner data-test-id="postfach-pdf-export-button" - [showSpinner]="isDownloadInProgress" - svgIcon="pdf_export" - [text]="label" [toolTip]="label" - (clickEmitter)="downloadPdf.emit()"> - </ozgcloud-stroked-button-with-spinner> - </ng-container> - <ng-template #showButton> - <ozgcloud-stroked-button-with-spinner data-test-id="postfach-pdf-export-label-button" - [showSpinner]="isDownloadInProgress" - svgIcon="pdf_export" - [toolTip]="label" - (clickEmitter)="downloadPdf.emit()"> - </ozgcloud-stroked-button-with-spinner> - </ng-template> - -</ng-container> \ No newline at end of file + <ng-container *ngIf="showButtonWithLabel; else showButton"> + <ozgcloud-stroked-button-with-spinner + data-test-id="postfach-pdf-export-button" + [showSpinner]="isDownloadInProgress" + svgIcon="pdf_export" + [text]="label" + [toolTip]="label" + (clickEmitter)="downloadPdf.emit()" + > + </ozgcloud-stroked-button-with-spinner> + </ng-container> + <ng-template #showButton> + <ozgcloud-stroked-button-with-spinner + data-test-id="postfach-pdf-export-label-button" + [showSpinner]="isDownloadInProgress" + svgIcon="pdf_export" + [toolTip]="label" + (clickEmitter)="downloadPdf.emit()" + > + </ozgcloud-stroked-button-with-spinner> + </ng-template> +</ng-container> diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.spec.ts index fabf8a67b1a1b9f5bb81eab2119bbb0d157a5ce5..0ccdf6b65afc7bb13d25b00420a8d19dafca1148 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.spec.ts @@ -31,138 +31,134 @@ import { MockComponent } from 'ng-mocks'; import { PostfachMailPdfButtonComponent } from './postfach-mail-pdf-button.component'; describe('PostfachMailPdfButtonComponent', () => { - let component: PostfachMailPdfButtonComponent; - let fixture: ComponentFixture<PostfachMailPdfButtonComponent>; + let component: PostfachMailPdfButtonComponent; + let fixture: ComponentFixture<PostfachMailPdfButtonComponent>; - const pdfExportButton: string = getDataTestIdOf('postfach-pdf-export-button'); - const pdfExportLabelButton: string = getDataTestIdOf('postfach-pdf-export-label-button'); + const pdfExportButton: string = getDataTestIdOf('postfach-pdf-export-button'); + const pdfExportLabelButton: string = getDataTestIdOf('postfach-pdf-export-label-button'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachMailPdfButtonComponent, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachMailPdfButtonComponent, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(PostfachMailPdfButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(PostfachMailPdfButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('set postfachMailListResource', () => { + describe('set postfachMailListResource', () => { + const postfachMailListResource: PostfachMailListResource = createPostfachMailListResource(); - const postfachMailListResource: PostfachMailListResource = createPostfachMailListResource(); + it('should set label', () => { + component.setLabel = jest.fn(); - it('should set label', () => { - component.setLabel = jest.fn() + component.postfachMailListResource = postfachMailListResource; - component.postfachMailListResource = postfachMailListResource; + expect(component.setLabel).toHaveBeenCalled(); + }); - expect(component.setLabel).toHaveBeenCalled(); - }) + it('should set postfachMailCount', () => { + component.setPostfachMailCount = jest.fn(); - it('should set postfachMailCount', () => { - component.setPostfachMailCount = jest.fn() + component.postfachMailListResource = postfachMailListResource; - component.postfachMailListResource = postfachMailListResource + expect(component.setPostfachMailCount).toHaveBeenCalledWith(postfachMailListResource); + }); + }); - expect(component.setPostfachMailCount).toHaveBeenCalledWith(postfachMailListResource); - }) - }) + describe('setLabel', () => { + it('should not set if no mails exists', () => { + component.postfachMailCount = PostfachNachrichtenCount.NONE; - describe('setLabel', () => { + component.setLabel(); - it('should not set if no mails exists', () => { - component.postfachMailCount = PostfachNachrichtenCount.NONE; + expect(component.label).toBeUndefined(); + }); - component.setLabel(); + it('should set for single mail exists', () => { + component.postfachMailCount = PostfachNachrichtenCount.SINGLE; - expect(component.label).toBeUndefined(); - }) + component.setLabel(); - it('should set for single mail exists', () => { - component.postfachMailCount = PostfachNachrichtenCount.SINGLE; + expect(component.label).toBe('Nachricht exportieren'); + }); - component.setLabel(); + it('should set for multiple mails exists', () => { + component.postfachMailCount = PostfachNachrichtenCount.MULTIPLE; - expect(component.label).toBe('Nachricht exportieren'); - }) + component.setLabel(); - it('should set for multiple mails exists', () => { - component.postfachMailCount = PostfachNachrichtenCount.MULTIPLE; + expect(component.label).toBe('Nachrichten exportieren'); + }); + }); - component.setLabel(); + describe('export button with label', () => { + it('should show on existing emails and showButtoWithLabel true', () => { + component.postfachMailCount = PostfachNachrichtenCount.SINGLE; + component.showButtonWithLabel = true; + fixture.detectChanges(); - expect(component.label).toBe('Nachrichten exportieren'); - }) - }) + const element = getElementFromFixture(fixture, pdfExportButton); - describe('export button with label', () => { + expect(element).toBeInTheDocument(); + }); - it('should show on existing emails and showButtoWithLabel true', () => { - component.postfachMailCount = PostfachNachrichtenCount.SINGLE; - component.showButtonWithLabel = true; - fixture.detectChanges(); + it('should hide on non existing emails', () => { + component.postfachMailCount = PostfachNachrichtenCount.NONE; + fixture.detectChanges(); - const element = getElementFromFixture(fixture, pdfExportButton); + const element = getElementFromFixture(fixture, pdfExportButton); - expect(element).toBeInTheDocument(); - }) + expect(element).not.toBeInTheDocument(); + }); - it('should hide on non existing emails', () => { - component.postfachMailCount = PostfachNachrichtenCount.NONE; - fixture.detectChanges(); + it('should hide showButtonWithLabel false', () => { + component.postfachMailCount = PostfachNachrichtenCount.SINGLE; + component.showButtonWithLabel = false; + fixture.detectChanges(); - const element = getElementFromFixture(fixture, pdfExportButton); + const element = getElementFromFixture(fixture, pdfExportButton); - expect(element).not.toBeInTheDocument(); - }) + expect(element).not.toBeInTheDocument(); + }); + }); - it('should hide showButtonWithLabel false', () => { - component.postfachMailCount = PostfachNachrichtenCount.SINGLE; - component.showButtonWithLabel = false; - fixture.detectChanges(); + describe('export button', () => { + it('should show on existing emails and showButtoWithLabel false', () => { + component.postfachMailCount = PostfachNachrichtenCount.SINGLE; + component.showButtonWithLabel = false; + fixture.detectChanges(); - const element = getElementFromFixture(fixture, pdfExportButton); + const element = getElementFromFixture(fixture, pdfExportLabelButton); - expect(element).not.toBeInTheDocument(); - }) - }) + expect(element).toBeInTheDocument(); + }); - describe('export button', () => { + it('should hide on non existing emails', () => { + component.postfachMailCount = PostfachNachrichtenCount.NONE; + fixture.detectChanges(); - it('should show on existing emails and showButtoWithLabel false', () => { - component.postfachMailCount = PostfachNachrichtenCount.SINGLE; - component.showButtonWithLabel = false; - fixture.detectChanges(); + const element = getElementFromFixture(fixture, pdfExportLabelButton); - const element = getElementFromFixture(fixture, pdfExportLabelButton); + expect(element).not.toBeInTheDocument(); + }); - expect(element).toBeInTheDocument(); - }) + it('should hide showButtonWithLabel true', () => { + component.postfachMailCount = PostfachNachrichtenCount.SINGLE; + component.showButtonWithLabel = true; + fixture.detectChanges(); - it('should hide on non existing emails', () => { - component.postfachMailCount = PostfachNachrichtenCount.NONE; - fixture.detectChanges(); + const element = getElementFromFixture(fixture, pdfExportLabelButton); - const element = getElementFromFixture(fixture, pdfExportLabelButton); - - expect(element).not.toBeInTheDocument(); - }) - - it('should hide showButtonWithLabel true', () => { - component.postfachMailCount = PostfachNachrichtenCount.SINGLE; - component.showButtonWithLabel = true; - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, pdfExportLabelButton); - - expect(element).not.toBeInTheDocument(); - }) - }) -}); \ No newline at end of file + expect(element).not.toBeInTheDocument(); + }); + }); +}); diff --git a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.ts b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.ts index fdfcf5ee21561b2a5db6e6cee26b2e3a337af238..7f36e8c562d11c6274a60025eaad5936bb7a5f09 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-mail-pdf-button-container/postfach-mail-pdf-button/postfach-mail-pdf-button.component.ts @@ -22,36 +22,42 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Component, EventEmitter, Input, Output } from '@angular/core'; -import { getPostfachNachrichtenCount, PostfachMailListResource, PostfachNachrichtenCount } from '@alfa-client/postfach-shared'; +import { + getPostfachNachrichtenCount, + PostfachMailListResource, + PostfachNachrichtenCount, +} from '@alfa-client/postfach-shared'; @Component({ - selector: 'alfa-postfach-mail-pdf-button', - templateUrl: './postfach-mail-pdf-button.component.html', - styleUrls: ['./postfach-mail-pdf-button.component.scss'], + selector: 'alfa-postfach-mail-pdf-button', + templateUrl: './postfach-mail-pdf-button.component.html', + styleUrls: ['./postfach-mail-pdf-button.component.scss'], }) export class PostfachMailPdfButtonComponent { + @Input() isDownloadInProgress: boolean; + @Input() set postfachMailListResource(postfachMailListResource: PostfachMailListResource) { + this.setPostfachMailCount(postfachMailListResource); + this.setLabel(); + } + @Input() showButtonWithLabel: boolean; - @Input() isDownloadInProgress: boolean; - @Input() set postfachMailListResource(postfachMailListResource: PostfachMailListResource) { - this.setPostfachMailCount(postfachMailListResource); - this.setLabel(); - } - @Input() showButtonWithLabel: boolean; + @Output() downloadPdf: EventEmitter<void> = new EventEmitter<void>(); - @Output() downloadPdf: EventEmitter<void> = new EventEmitter<void>(); + postfachMailCount: PostfachNachrichtenCount; + label: string = undefined; - postfachMailCount: PostfachNachrichtenCount; - label: string = undefined; + readonly postfachNachrichtenCount = PostfachNachrichtenCount; - readonly postfachNachrichtenCount = PostfachNachrichtenCount; + setPostfachMailCount(postfachMailListResource: PostfachMailListResource): void { + this.postfachMailCount = getPostfachNachrichtenCount(postfachMailListResource); + } - setPostfachMailCount(postfachMailListResource: PostfachMailListResource): void { - this.postfachMailCount = getPostfachNachrichtenCount(postfachMailListResource) - } - - setLabel(): void { - if (this.postfachMailCount != PostfachNachrichtenCount.NONE) { - this.label = this.postfachMailCount == PostfachNachrichtenCount.SINGLE ? 'Nachricht exportieren' : 'Nachrichten exportieren'; - } - } -} \ No newline at end of file + setLabel(): void { + if (this.postfachMailCount != PostfachNachrichtenCount.NONE) { + this.label = + this.postfachMailCount == PostfachNachrichtenCount.SINGLE ? + 'Nachricht exportieren' + : 'Nachrichten exportieren'; + } + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.html b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.html index ec90058a9d8519fa29a3752506148187408cf786..7b53cceed912316ebdc45263740a9cf156500ecd 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.html @@ -23,4 +23,6 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-postfach-page [postfachMailListStateResource]="postfachMailListStateResource$ | async"></alfa-postfach-page> \ No newline at end of file +<alfa-postfach-page + [postfachMailListStateResource]="postfachMailListStateResource$ | async" +></alfa-postfach-page> diff --git a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.spec.ts index f9275e13cfd40ec5564fe5cd08bac873c384a96a..69639d75c8654ed00787c49ccee95b3a1cbfd82e 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.spec.ts @@ -29,43 +29,38 @@ import { PostfachPageContainerComponent } from './postfach-page-container.compon import { PostfachPageComponent } from './postfach-page/postfach-page.component'; describe('PostfachPageContainerComponent', () => { - let component: PostfachPageContainerComponent; - let fixture: ComponentFixture<PostfachPageContainerComponent>; + let component: PostfachPageContainerComponent; + let fixture: ComponentFixture<PostfachPageContainerComponent>; - const postfachService = mock(PostfachService); + const postfachService = mock(PostfachService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachPageContainerComponent, - MockComponent(PostfachPageComponent) - ], - providers: [ - { - provide: PostfachService, - useValue: postfachService - } - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [PostfachPageContainerComponent, MockComponent(PostfachPageComponent)], + providers: [ + { + provide: PostfachService, + useValue: postfachService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(PostfachPageContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(PostfachPageContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should call postfach service', () => { + component.ngOnInit(); - it('should call postfach service', () => { - component.ngOnInit(); - - expect(postfachService.getPostfachMailListByVorgang).toHaveBeenCalled(); - }) - }) + expect(postfachService.getPostfachMailListByVorgang).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.ts b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.ts index b8713ceb2153e8562474cdb625bb0bb604ca975c..236bba9cebd9b1b5f37f8d14bc8074a17924b0f3 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page-container.component.ts @@ -27,18 +27,17 @@ import { StateResource } from '@alfa-client/tech-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-postfach-page-container', - templateUrl: './postfach-page-container.component.html', - styleUrls: ['./postfach-page-container.component.scss'], - providers: [{ provide: ON_PAGE, useValue: true }] + selector: 'alfa-postfach-page-container', + templateUrl: './postfach-page-container.component.html', + styleUrls: ['./postfach-page-container.component.scss'], + providers: [{ provide: ON_PAGE, useValue: true }], }) export class PostfachPageContainerComponent implements OnInit { + postfachMailListStateResource$: Observable<StateResource<PostfachMailListResource>>; - postfachMailListStateResource$: Observable<StateResource<PostfachMailListResource>>; + constructor(private postfachService: PostfachService) {} - constructor(private postfachService: PostfachService) { } - - ngOnInit() { - this.postfachMailListStateResource$ = this.postfachService.getPostfachMailListByVorgang(); - } -} \ No newline at end of file + ngOnInit() { + this.postfachMailListStateResource$ = this.postfachService.getPostfachMailListByVorgang(); + } +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.html b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.html index 9ac408afd4df6494ab4676a2c14ec72cfd9a9f93..3aac0b25924886e054d181ae7558219d0545e68d 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.html @@ -24,15 +24,20 @@ --> <ozgcloud-spinner *ngIf="postfachMailListStateResource"> - - <alfa-postfach-mail *ngFor="let postfachMail of postfachMailListStateResource.resource | toEmbeddedResources: postfachMailListLinkRel.POSTFACH_MAIL_LIST" [attr.data-test-id]="(postfachMail.subject | convertForDataTest) + '-item'" - class="postfach postfach-links-disabled" - [postfachMail]="postfachMail"> - </alfa-postfach-mail> - - <alfa-postfach-mail-pdf-button-container - [showButtonWithLabel]="true" - [postfachMailListResource]="postfachMailListStateResource.resource"> - </alfa-postfach-mail-pdf-button-container> - + <alfa-postfach-mail + *ngFor=" + let postfachMail of postfachMailListStateResource.resource + | toEmbeddedResources: postfachMailListLinkRel.POSTFACH_MAIL_LIST + " + [attr.data-test-id]="(postfachMail.subject | convertForDataTest) + '-item'" + class="postfach postfach-links-disabled" + [postfachMail]="postfachMail" + > + </alfa-postfach-mail> + + <alfa-postfach-mail-pdf-button-container + [showButtonWithLabel]="true" + [postfachMailListResource]="postfachMailListStateResource.resource" + > + </alfa-postfach-mail-pdf-button-container> </ozgcloud-spinner> diff --git a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.scss b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.scss index 8272616de7ef72b28c4bc972f0ef24b6c03cf7b8..7aa658e02c12f707953b25897c98bbec80c6d55a 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.scss +++ b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.scss @@ -22,52 +22,52 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .postfach { - display: flex; - flex-direction: column; - width: 100%; - border-bottom: 1px solid rgb(0 0 0 / 8%); - padding: 16px 24px 16px 28px; - margin: 0; + display: flex; + flex-direction: column; + width: 100%; + border-bottom: 1px solid rgb(0 0 0 / 8%); + padding: 16px 24px 16px 28px; + margin: 0; - ::ng-deep { - .subject { - display: flex; - align-items: center; - font-size: 16px; - font-weight: 400; - margin: 2px 0; - position: relative; + ::ng-deep { + .subject { + display: flex; + align-items: center; + font-size: 16px; + font-weight: 400; + margin: 2px 0; + position: relative; - .mat-icon { - transform: scale(0.9); - margin: 0 2px 2px -2px; - } - } + .mat-icon { + transform: scale(0.9); + margin: 0 2px 2px -2px; + } + } - .file { - width: 100%; - } + .file { + width: 100%; + } - .body { - margin: 4px 0; - } + .body { + margin: 4px 0; + } - .created-at { - font-size: 13px; - position: absolute; - right: 0; - top: 0; - } + .created-at { + font-size: 13px; + position: absolute; + right: 0; + top: 0; + } - .overflow { - overflow: initial !important; - text-overflow: initial !important; - white-space: pre-wrap !important; - } - } + .overflow { + overflow: initial !important; + text-overflow: initial !important; + white-space: pre-wrap !important; + } + } } alfa-postfach-mail-pdf-button-container { - display: block; - margin: 16px 24px; -} \ No newline at end of file + display: block; + margin: 16px 24px; +} diff --git a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.spec.ts index 7d3cf71513fd90e4f298713b986913b0b0743d75..2b4027b187ce866a6e6b55939b9f4fba43ce3891 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.spec.ts @@ -22,7 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { ConvertForDataTestPipe, HasLinkPipe, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared'; +import { + ConvertForDataTestPipe, + HasLinkPipe, + ToEmbeddedResourcesPipe, +} from '@alfa-client/tech-shared'; import { SpinnerComponent } from '@alfa-client/ui'; import { MockComponent } from 'ng-mocks'; import { PostfachMailComponent } from '../../../postfach-mail-list-container/postfach-mail-list/postfach-mail/postfach-mail.component'; @@ -30,31 +34,30 @@ import { PostfachMailPdfButtonContainerComponent } from '../../../postfach-mail- import { PostfachPageMailListComponent } from './postfach-page-mail-list.component'; describe('PostfachPageMailListComponent', () => { - let component: PostfachPageMailListComponent; - let fixture: ComponentFixture<PostfachPageMailListComponent>; + let component: PostfachPageMailListComponent; + let fixture: ComponentFixture<PostfachPageMailListComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachPageMailListComponent, - ToEmbeddedResourcesPipe, - ConvertForDataTestPipe, - HasLinkPipe, - MockComponent(PostfachMailComponent), - MockComponent(SpinnerComponent), - MockComponent(PostfachMailPdfButtonContainerComponent) - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachPageMailListComponent, + ToEmbeddedResourcesPipe, + ConvertForDataTestPipe, + HasLinkPipe, + MockComponent(PostfachMailComponent), + MockComponent(SpinnerComponent), + MockComponent(PostfachMailPdfButtonContainerComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(PostfachPageMailListComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(PostfachPageMailListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.ts b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.ts index f15117b9ca4973dee5388a62913af252deee35d9..a5ae827cc750dda39320ae6feaadcb8c35803014 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page-mail-list/postfach-page-mail-list.component.ts @@ -26,13 +26,12 @@ import { StateResource } from '@alfa-client/tech-shared'; import { PostfachMailListLinkRel, PostfachMailListResource } from '@alfa-client/postfach-shared'; @Component({ - selector: 'alfa-postfach-page-mail-list', - templateUrl: './postfach-page-mail-list.component.html', - styleUrls: ['./postfach-page-mail-list.component.scss'] + selector: 'alfa-postfach-page-mail-list', + templateUrl: './postfach-page-mail-list.component.html', + styleUrls: ['./postfach-page-mail-list.component.scss'], }) export class PostfachPageMailListComponent { + readonly postfachMailListLinkRel = PostfachMailListLinkRel; - readonly postfachMailListLinkRel = PostfachMailListLinkRel; - - @Input() postfachMailListStateResource: StateResource<PostfachMailListResource> + @Input() postfachMailListStateResource: StateResource<PostfachMailListResource>; } diff --git a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.html b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.html index 8b22869438759fa498839fb4addfe9cfb2dd3356..4d848b64c1635755aaab25f123bb5c3b0635c56a 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.html +++ b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.html @@ -24,10 +24,13 @@ --> <ozgcloud-subnavigation class="mat-app-background"> - <ozgcloud-back-button linkTo="../" label="zurück zur Detailseite"></ozgcloud-back-button> + <ozgcloud-back-button linkTo="../" label="zurück zur Detailseite"></ozgcloud-back-button> </ozgcloud-subnavigation> <div class="l-scroll-area--full"> - <alfa-vorgang-in-postfach-breadcrumb-container></alfa-vorgang-in-postfach-breadcrumb-container> - <alfa-postfach-page-mail-list [postfachMailListStateResource]="postfachMailListStateResource" data-test-id="postfach-mail-list"></alfa-postfach-page-mail-list> + <alfa-vorgang-in-postfach-breadcrumb-container></alfa-vorgang-in-postfach-breadcrumb-container> + <alfa-postfach-page-mail-list + [postfachMailListStateResource]="postfachMailListStateResource" + data-test-id="postfach-mail-list" + ></alfa-postfach-page-mail-list> </div> diff --git a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.spec.ts b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.spec.ts index a38e1e5d1561447d14e3e6539bbf6bbae07ee154..3fa88754e5c94f6717ac4fea2a8d901c3022b6f4 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.spec.ts @@ -30,30 +30,29 @@ import { PostfachPageMailListComponent } from './postfach-page-mail-list/postfac import { PostfachPageComponent } from './postfach-page.component'; describe('PostfachPageComponent', () => { - let component: PostfachPageComponent; - let fixture: ComponentFixture<PostfachPageComponent>; + let component: PostfachPageComponent; + let fixture: ComponentFixture<PostfachPageComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - PostfachPageComponent, - MatIcon, - MockComponent(BackButtonComponent), - MockComponent(SubnavigationComponent), - MockComponent(PostfachPageMailListComponent), - MockComponent(VorgangInPostfachBreadcrumbContainerComponent) - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + PostfachPageComponent, + MatIcon, + MockComponent(BackButtonComponent), + MockComponent(SubnavigationComponent), + MockComponent(PostfachPageMailListComponent), + MockComponent(VorgangInPostfachBreadcrumbContainerComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(PostfachPageComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(PostfachPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.ts b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.ts index 9d5408e4c2a6cb0804ec2bfa9ec7dc05a8fcb897..fbf886678e96eb8e3488b50f45ce7c3b7a829890 100644 --- a/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.ts +++ b/alfa-client/libs/postfach/src/lib/postfach-page-container/postfach-page/postfach-page.component.ts @@ -26,11 +26,10 @@ import { PostfachMailListResource } from '@alfa-client/postfach-shared'; import { StateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-postfach-page', - templateUrl: './postfach-page.component.html', - styleUrls: ['./postfach-page.component.scss'] + selector: 'alfa-postfach-page', + templateUrl: './postfach-page.component.html', + styleUrls: ['./postfach-page.component.scss'], }) export class PostfachPageComponent { - - @Input() postfachMailListStateResource: StateResource<PostfachMailListResource>; + @Input() postfachMailListStateResource: StateResource<PostfachMailListResource>; } diff --git a/alfa-client/libs/postfach/src/lib/postfach.module.spec.ts b/alfa-client/libs/postfach/src/lib/postfach.module.spec.ts index 8802e26f49078a4f7e551368c7bf74d9ca1d3894..0448fedce6344e1bc51188b5467ed7c5894e84a6 100644 --- a/alfa-client/libs/postfach/src/lib/postfach.module.spec.ts +++ b/alfa-client/libs/postfach/src/lib/postfach.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { PostfachModule } from './postfach.module'; describe('PostfachModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [PostfachModule] - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [PostfachModule], + }).compileComponents(); + }); - it('should create', () => { - expect(PostfachModule).toBeDefined(); - }); + it('should create', () => { + expect(PostfachModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/postfach/src/lib/postfach.module.ts b/alfa-client/libs/postfach/src/lib/postfach.module.ts index 6c1517d08c7db4cf17fe76425ae3e6136b3567cc..1b0f9765cb98a7faa8149301820e1841ae20ac4b 100644 --- a/alfa-client/libs/postfach/src/lib/postfach.module.ts +++ b/alfa-client/libs/postfach/src/lib/postfach.module.ts @@ -52,56 +52,56 @@ import { PostfachPageMailListComponent } from './postfach-page-container/postfac import { PostfachPageComponent } from './postfach-page-container/postfach-page/postfach-page.component'; const routes: Routes = [ - { - path: 'postfach', - component: PostfachPageContainerComponent, - title: 'Nachrichten zum Vorgang | Alfa', - }, + { + path: 'postfach', + component: PostfachPageContainerComponent, + title: 'Nachrichten zum Vorgang | Alfa', + }, ]; @NgModule({ - imports: [ - CommonModule, - RouterModule.forChild(routes), - UiModule, - PostfachSharedModule, - UserProfileModule, - VorgangSharedModule, - VorgangSharedUiModule, - BinaryFileModule, - ], - declarations: [ - PostfachMailListContainerComponent, - PostfachMailButtonContainerComponent, - PostfachMailFormComponent, - PostfachMailListComponent, - PostfachMailComponent, - PostfachPageContainerComponent, - IncommingMailComponent, - OutgoingMailComponent, - PostfachPageComponent, - PostfachPageMailListComponent, - OutgoingMailErrorComponent, - PostfachMailDateComponent, - OutgoingMailErrorContainerComponent, - PostfachMailAttachmentsComponent, - PostfachMailButtonComponent, - PostfachMailPdfButtonContainerComponent, - PostfachMailPdfButtonComponent, - PostfachNachrichtEditButtonContainerComponent, - PostfachNachrichtAttachmentContainerComponent, - PostfachNachrichtReplyEditorContainerComponent, - ], - exports: [ - PostfachMailListContainerComponent, - PostfachMailButtonContainerComponent, - PostfachMailFormComponent, - ], - providers: [ - { - provide: ON_PAGE, - useValue: undefined, - }, - ], + imports: [ + CommonModule, + RouterModule.forChild(routes), + UiModule, + PostfachSharedModule, + UserProfileModule, + VorgangSharedModule, + VorgangSharedUiModule, + BinaryFileModule, + ], + declarations: [ + PostfachMailListContainerComponent, + PostfachMailButtonContainerComponent, + PostfachMailFormComponent, + PostfachMailListComponent, + PostfachMailComponent, + PostfachPageContainerComponent, + IncommingMailComponent, + OutgoingMailComponent, + PostfachPageComponent, + PostfachPageMailListComponent, + OutgoingMailErrorComponent, + PostfachMailDateComponent, + OutgoingMailErrorContainerComponent, + PostfachMailAttachmentsComponent, + PostfachMailButtonComponent, + PostfachMailPdfButtonContainerComponent, + PostfachMailPdfButtonComponent, + PostfachNachrichtEditButtonContainerComponent, + PostfachNachrichtAttachmentContainerComponent, + PostfachNachrichtReplyEditorContainerComponent, + ], + exports: [ + PostfachMailListContainerComponent, + PostfachMailButtonContainerComponent, + PostfachMailFormComponent, + ], + providers: [ + { + provide: ON_PAGE, + useValue: undefined, + }, + ], }) export class PostfachModule {} diff --git a/alfa-client/libs/postfach/src/test-setup.ts b/alfa-client/libs/postfach/src/test-setup.ts index 5870fdabb6470fd0f6f3f63be3d4f6b8041b4dd2..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/postfach/src/test-setup.ts +++ b/alfa-client/libs/postfach/src/test-setup.ts @@ -26,17 +26,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/postfach/tsconfig.json b/alfa-client/libs/postfach/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/postfach/tsconfig.json +++ b/alfa-client/libs/postfach/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/postfach/tsconfig.lib.json b/alfa-client/libs/postfach/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/postfach/tsconfig.lib.json +++ b/alfa-client/libs/postfach/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/postfach/tsconfig.spec.json b/alfa-client/libs/postfach/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/postfach/tsconfig.spec.json +++ b/alfa-client/libs/postfach/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/tech-shared/.eslintrc.json b/alfa-client/libs/tech-shared/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/tech-shared/.eslintrc.json +++ b/alfa-client/libs/tech-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/tech-shared/jest.config.ts b/alfa-client/libs/tech-shared/jest.config.ts index 90e98b1caecb9c024345e037be6ada89baa51252..9699d6c0f3407adb3d999c0939efc86a8e332c4f 100644 --- a/alfa-client/libs/tech-shared/jest.config.ts +++ b/alfa-client/libs/tech-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'tech-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/tech-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'tech-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/tech-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/tech-shared/project.json b/alfa-client/libs/tech-shared/project.json index b96e3cd6fb956247c93b09101f75955d36e0084e..7f95933e1a83aacfb5fcd110ecc52aebeb6677f4 100644 --- a/alfa-client/libs/tech-shared/project.json +++ b/alfa-client/libs/tech-shared/project.json @@ -1,34 +1,31 @@ { - "name": "tech-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/tech-shared/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/tech-shared/src/**/*.ts", - "libs/tech-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/tech-shared/tsconfig.spec.json", - "jestConfig": "libs/tech-shared/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/tech-shared"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "tech-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/tech-shared/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/tech-shared/src/**/*.ts", "libs/tech-shared/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/tech-shared/tsconfig.spec.json", + "jestConfig": "libs/tech-shared/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/tech-shared"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.spec.ts index 53c8ac8c027317c987fafa9e82153f0dc3939a9f..85677d89699f6287043b22853246d7e6a047a361 100644 --- a/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.spec.ts @@ -2,20 +2,21 @@ import { createAriaLabelForIconButton } from './assistive-technologies.util'; import { EMPTY_STRING } from '@alfa-client/tech-shared'; describe('createAriaLabelForIconButton', () => { + const tooltip = 'Tooltip text'; + const svgIcon = 'test_icon'; - const tooltip = 'Tooltip text'; - const svgIcon = 'test_icon'; + it('should return tooltip', () => { + const ariaLabel = createAriaLabelForIconButton(tooltip, svgIcon); - it('should return tooltip', () => { - const ariaLabel = createAriaLabelForIconButton(tooltip, svgIcon); + expect(ariaLabel).toBe(tooltip); + }); - expect(ariaLabel).toBe(tooltip); - }) + it.each([null, EMPTY_STRING])( + 'should return label with svg icon name for tooltip %s', + (value: string) => { + const ariaLabel = createAriaLabelForIconButton(value, svgIcon); - it.each([null, EMPTY_STRING])('should return label with svg icon name for tooltip %s', (value: string) => { - const ariaLabel = createAriaLabelForIconButton(value, svgIcon); - - expect(ariaLabel).toBe(`Icon Button mit einem ${svgIcon} Icon`); - }) - -}) \ No newline at end of file + expect(ariaLabel).toBe(`Icon Button mit einem ${svgIcon} Icon`); + }, + ); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.ts b/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.ts index d4a724362e399b1aee48672c751d02af254e65ab..679d22dac353c3c9ccba83615ad5986af5b0e969 100644 --- a/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.ts +++ b/alfa-client/libs/tech-shared/src/lib/assistive-technologies.util.ts @@ -1,5 +1,5 @@ import { isEmpty } from 'lodash-es'; export function createAriaLabelForIconButton(tooltip: string, svgIcon: string): string { - return isEmpty(tooltip) ? `Icon Button mit einem ${svgIcon} Icon` : tooltip; -} \ No newline at end of file + return isEmpty(tooltip) ? `Icon Button mit einem ${svgIcon} Icon` : tooltip; +} diff --git a/alfa-client/libs/tech-shared/src/lib/date.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/date.util.spec.ts index 4a3d206c39280b9e7b755a1d8c97a434651e85b4..b739329170727d037960224b4605805e3efb9e68 100644 --- a/alfa-client/libs/tech-shared/src/lib/date.util.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/date.util.spec.ts @@ -23,7 +23,18 @@ */ import { formatDate, registerLocaleData } from '@angular/common'; import localeDe from '@angular/common/locales/de'; -import { formatDateWithoutYearWithTime, formatForDatabase, formatFullDate, formatFullDateWithTimeAndDay, formatFullDateWithTimeWithoutSeconds, formatFullDateWithoutSeperator, formatHourMinute, formatToPrettyDate, formatWithoutYear, isISODateInPast } from './date.util'; +import { + formatDateWithoutYearWithTime, + formatForDatabase, + formatFullDate, + formatFullDateWithTimeAndDay, + formatFullDateWithTimeWithoutSeconds, + formatFullDateWithoutSeperator, + formatHourMinute, + formatToPrettyDate, + formatWithoutYear, + isISODateInPast, +} from './date.util'; import faker from '@faker-js/faker'; import * as dateFns from 'date-fns'; @@ -33,120 +44,117 @@ jest.mock('date-fns', () => mockAsEsModule('date-fns')); registerLocaleData(localeDe); function mockAsEsModule(module: string) { - return { - __esModule: true, - ...jest.requireActual(module) - }; + return { + __esModule: true, + ...jest.requireActual(module), + }; } describe('Date Util', () => { + const dateToFormat: Date = new Date('1010-01-01:01:01:01'); - const dateToFormat: Date = new Date('1010-01-01:01:01:01'); + describe('formatForDatabase()', () => { + it('should return correct date string with Date object', () => { + const formattedDate: string = formatForDatabase(dateToFormat); - describe('formatForDatabase()', () => { - it('should return correct date string with Date object', () => { - const formattedDate: string = formatForDatabase(dateToFormat); + expect(formattedDate).toEqual('1010-01-01'); + }); + }); - expect(formattedDate).toEqual('1010-01-01'); - }) - }) + it('should return full date with hour and minutes', () => { + const formattedDate: string = formatFullDateWithTimeWithoutSeconds(dateToFormat); - it('should return full date with hour and minutes', () => { - const formattedDate: string = formatFullDateWithTimeWithoutSeconds(dateToFormat); + expect(formattedDate).toEqual('01.01.10 01:01'); + }); - expect(formattedDate).toEqual('01.01.10 01:01'); - }) + it('should return name of day, full date, hour, minute and seconds', () => { + const formattedDate: string = formatFullDateWithTimeAndDay(dateToFormat); - it('should return name of day, full date, hour, minute and seconds', () => { - const formattedDate: string = formatFullDateWithTimeAndDay(dateToFormat); + expect(formattedDate).toEqual('Montag, 01.01.1010, 01:01:01'); + }); - expect(formattedDate).toEqual('Montag, 01.01.1010, 01:01:01'); - }) + it('should return full date', () => { + const formattedDate: string = formatFullDate(dateToFormat); - it('should return full date', () => { - const formattedDate: string = formatFullDate(dateToFormat); + expect(formattedDate).toEqual('01.01.1010'); + }); - expect(formattedDate).toEqual('01.01.1010'); - }) + it('should return hour and minute', () => { + const formattedDate: string = formatHourMinute(dateToFormat); - it('should return hour and minute', () => { - const formattedDate: string = formatHourMinute(dateToFormat); + expect(formattedDate).toEqual('01:01'); + }); - expect(formattedDate).toEqual('01:01'); - }) + it('should return day and name of month', () => { + const formattedDate: string = formatWithoutYear(dateToFormat); - it('should return day and name of month', () => { - const formattedDate: string = formatWithoutYear(dateToFormat); + expect(formattedDate).toEqual('01. Jan.'); + }); - expect(formattedDate).toEqual('01. Jan.'); - }) + it('should return full date without seperator', () => { + const formattedDate: string = formatFullDateWithoutSeperator(dateToFormat); - it('should return full date without seperator', () => { - const formattedDate: string = formatFullDateWithoutSeperator(dateToFormat); + expect(formattedDate).toEqual('10100101'); + }); - expect(formattedDate).toEqual('10100101'); - }) + it('should return date with month and day and time with hour and minute', () => { + const formattedDate: string = formatDateWithoutYearWithTime(dateToFormat); - it('should return date with month and day and time with hour and minute', () => { - const formattedDate: string = formatDateWithoutYearWithTime(dateToFormat); + expect(formattedDate).toEqual('01. Jan. 01:01'); + }); - expect(formattedDate).toEqual('01. Jan. 01:01'); - }) + describe('formatToPrettyDate()', () => { + it('should format date without year', () => { + const today: Date = new Date(); + const day: string = formatDate(today, 'dd', 'de'); + const month: string = formatDate(today, 'MMM', 'de'); - describe('formatToPrettyDate()', () => { + const result: string = formatToPrettyDate(today); - it('should format date without year', () => { - const today: Date = new Date(); - const day: string = formatDate(today, 'dd', 'de'); - const month: string = formatDate(today, 'MMM', 'de'); + expect(result).toEqual(`${day}. ${month}`); + }); - const result: string = formatToPrettyDate(today); + it('should format date without year', () => { + const result: string = formatToPrettyDate(dateToFormat); - expect(result).toEqual(`${day}. ${month}`); - }) + expect(result).toEqual('01.01.1010'); + }); + }); - it('should format date without year', () => { - const result: string = formatToPrettyDate(dateToFormat); + describe('isISODateInPast', () => { + it('should call parseISO', () => { + const parseISO = jest.spyOn(dateFns, 'parseISO'); + const isoDate: string = faker.date.past().toISOString(); - expect(result).toEqual('01.01.1010'); - }) - }) + isISODateInPast(isoDate); - describe('isISODateInPast', () => { - it('should call parseISO', () => { - const parseISO = jest.spyOn(dateFns, 'parseISO'); - const isoDate: string = faker.date.past().toISOString(); + expect(parseISO).toHaveBeenCalledWith(isoDate); + }); - isISODateInPast(isoDate); + it('should call isPast', () => { + const isPast = jest.spyOn(dateFns, 'isPast'); + const date: Date = faker.date.past(); + const isoDate: string = date.toISOString(); - expect(parseISO).toHaveBeenCalledWith(isoDate); - }) + isISODateInPast(isoDate); - it('should call isPast', () => { - const isPast = jest.spyOn(dateFns, 'isPast'); - const date: Date = faker.date.past(); - const isoDate: string = date.toISOString() + expect(isPast).toHaveBeenCalledWith(date); + }); - isISODateInPast(isoDate); + it('should return false for future dates', () => { + const isoDate: string = faker.date.future().toISOString(); - expect(isPast).toHaveBeenCalledWith(date); - }) + const result: boolean = isISODateInPast(isoDate); - it('should return false for future dates', () => { - const isoDate: string = faker.date.future().toISOString(); + expect(result).toBeFalsy(); + }); - const result: boolean = isISODateInPast(isoDate); + it('should return true for past dates', () => { + const isoDate: string = faker.date.past().toISOString(); - expect(result).toBeFalsy(); - }) + const result: boolean = isISODateInPast(isoDate); - it('should return true for past dates', () => { - const isoDate: string = faker.date.past().toISOString(); - - const result: boolean = isISODateInPast(isoDate); - - expect(result).toBeTruthy(); - }) - }) - -}) \ No newline at end of file + expect(result).toBeTruthy(); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/date.util.ts b/alfa-client/libs/tech-shared/src/lib/date.util.ts index fb0fdcc474ffb78d7363fab6118290a08b7bdc5d..36b8c1f6a6e719c9c3cc93778382f2f261668e2a 100644 --- a/alfa-client/libs/tech-shared/src/lib/date.util.ts +++ b/alfa-client/libs/tech-shared/src/lib/date.util.ts @@ -26,62 +26,61 @@ import { formatDate } from '@angular/common'; import * as dateFns from 'date-fns'; export function formatForDatabase(date: Date): string { - const dateFormat: string = 'yyyy-MM-dd'; - return formatDate(date, dateFormat, 'de'); + const dateFormat: string = 'yyyy-MM-dd'; + return formatDate(date, dateFormat, 'de'); } export function formatFullDateWithTimeWithoutSeconds(date: Date): string { - return formatDate(date, 'dd.MM.yy HH:mm', 'de'); + return formatDate(date, 'dd.MM.yy HH:mm', 'de'); } export function formatFullDateWithTimeAndDay(date: Date): string { - return formatDate(date, 'EEEE, dd.MM.yyyy, HH:mm:ss', 'de'); + return formatDate(date, 'EEEE, dd.MM.yyyy, HH:mm:ss', 'de'); } export function formatFullDate(date: Date): string { - return formatDate(date, 'dd.MM.yyyy', 'de'); + return formatDate(date, 'dd.MM.yyyy', 'de'); } export function formatHourMinute(date: Date): string { - return formatDate(date, 'hh:mm', 'de'); + return formatDate(date, 'hh:mm', 'de'); } export function formatWithoutYear(date: Date): string { - return formatDate(date, 'dd. MMM', 'de'); + return formatDate(date, 'dd. MMM', 'de'); } export function formatFullDateWithoutSeperator(date: Date): string { - return formatDate(date, 'yyyyMMdd', 'de'); + return formatDate(date, 'yyyyMMdd', 'de'); } export function formatDateWithoutYearWithTime(date: Date): string { - return formatDate(date, 'dd. MMM HH:mm', 'de'); + return formatDate(date, 'dd. MMM HH:mm', 'de'); } export function formatToPrettyDate(date: Date): string { - date = dateFns.isValid(date) ? date : dateFns.parseISO(date as unknown as string); + date = dateFns.isValid(date) ? date : dateFns.parseISO(date as unknown as string); - if (dateFns.isSameYear(new Date(), date)) { - return formatWithoutYear(date) - } + if (dateFns.isSameYear(new Date(), date)) { + return formatWithoutYear(date); + } - return formatFullDate(date); + return formatFullDate(date); } - export function createFutureDate(todayPlusDays: number): Date { - const date = new Date(); - date.setDate(date.getDate() + todayPlusDays); + const date = new Date(); + date.setDate(date.getDate() + todayPlusDays); - return date; + return date; } export function isParsableToDate(date: string): boolean { - return !isNaN(Date.parse(date)); + return !isNaN(Date.parse(date)); } export function isISODateInPast(isoDate: string): boolean { - const date: Date = dateFns.parseISO(isoDate); + const date: Date = dateFns.parseISO(isoDate); - return dateFns.isPast(date); -} \ No newline at end of file + return dateFns.isPast(date); +} diff --git a/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.spec.ts b/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.spec.ts index ebc090a90332ec94b47b9107de05d25d869512a2..10b94e399d82a1ef6c97eb156995e20584aebd4e 100644 --- a/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.spec.ts @@ -24,71 +24,71 @@ import { CatchHttpError } from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { HttpErrorHandler } from '../error/error.handler'; -import { catchHttpErrorHandleErrorResponse, handleDefaultErrorHandling, handleDefaultRetryHandling } from './catch-http-error.decorator'; +import { + catchHttpErrorHandleErrorResponse, + handleDefaultErrorHandling, + handleDefaultRetryHandling, +} from './catch-http-error.decorator'; describe('CatchHttpError Decorator', () => { + let httpErrorHandler: Mock<HttpErrorHandler>; - let httpErrorHandler: Mock<HttpErrorHandler>; + beforeEach(() => { + httpErrorHandler = mock(HttpErrorHandler); + }); - beforeEach(() => { - httpErrorHandler = mock(HttpErrorHandler); - }) + it('should be created', () => { + expect(CatchHttpError).toBeTruthy(); + }); - it('should be created', () => { - expect(CatchHttpError).toBeTruthy(); - }) + describe('handleDefaultErrorHandling', () => { + it('should call http error handler if is true', () => { + handleDefaultErrorHandling(true, useFromMock(httpErrorHandler)); - describe('handleDefaultErrorHandling', () => { + expect(httpErrorHandler.disableDefaultHandling).toHaveBeenCalled(); + }); - it('should call http error handler if is true', () => { - handleDefaultErrorHandling(true, useFromMock(httpErrorHandler)); + it('should do nothing if is false', () => { + handleDefaultErrorHandling(false, useFromMock(httpErrorHandler)); - expect(httpErrorHandler.disableDefaultHandling).toHaveBeenCalled(); - }) + expect(httpErrorHandler.disableDefaultHandling).not.toHaveBeenCalled(); + }); + }); - it('should do nothing if is false', () => { - handleDefaultErrorHandling(false, useFromMock(httpErrorHandler)); + describe('handleDefaultRetryHandling', () => { + it('should call http error handler if is true', () => { + handleDefaultRetryHandling(true, useFromMock(httpErrorHandler)); - expect(httpErrorHandler.disableDefaultHandling).not.toHaveBeenCalled(); - }) - }) + expect(httpErrorHandler.disableRetry).toHaveBeenCalled(); + }); - describe('handleDefaultRetryHandling', () => { + it('should do nothing if is false', () => { + handleDefaultRetryHandling(false, useFromMock(httpErrorHandler)); - it('should call http error handler if is true', () => { - handleDefaultRetryHandling(true, useFromMock(httpErrorHandler)); + expect(httpErrorHandler.disableRetry).not.toHaveBeenCalled(); + }); + }); - expect(httpErrorHandler.disableRetry).toHaveBeenCalled(); - }) + describe('catchHttpErrorCatchError', () => { + const response = {}; + const name: string = 'registeredMethodName'; - it('should do nothing if is false', () => { - handleDefaultRetryHandling(false, useFromMock(httpErrorHandler)); + it('should enable default error handling', () => { + catchHttpErrorHandleErrorResponse(useFromMock(httpErrorHandler), response, name); - expect(httpErrorHandler.disableRetry).not.toHaveBeenCalled(); - }) - }) + expect(httpErrorHandler.enableDefaultHandling).toHaveBeenCalled(); + }); - describe('catchHttpErrorCatchError', () => { + it('should enable default retry handling', () => { + catchHttpErrorHandleErrorResponse(useFromMock(httpErrorHandler), response, name); - const response = {}; - const name: string = 'registeredMethodName'; + expect(httpErrorHandler.enableRetry).toHaveBeenCalled(); + }); - it('should enable default error handling', () => { - catchHttpErrorHandleErrorResponse(useFromMock(httpErrorHandler), response, name); + it('should execute post error method from http error handler', () => { + catchHttpErrorHandleErrorResponse(useFromMock(httpErrorHandler), response, name); - expect(httpErrorHandler.enableDefaultHandling).toHaveBeenCalled(); - }) - - it('should enable default retry handling', () => { - catchHttpErrorHandleErrorResponse(useFromMock(httpErrorHandler), response, name); - - expect(httpErrorHandler.enableRetry).toHaveBeenCalled(); - }) - - it('should execute post error method from http error handler', () => { - catchHttpErrorHandleErrorResponse(useFromMock(httpErrorHandler), response, name); - - expect(httpErrorHandler.doAfterErrorReceived).toHaveBeenCalledWith(name, response); - }) - }) -}) \ No newline at end of file + expect(httpErrorHandler.doAfterErrorReceived).toHaveBeenCalledWith(name, response); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.ts b/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.ts index a72780d1cf5e6d549a385b5d0e042589f3ccc65a..03881a44de8bb93530fb8851b33d5fc424466389 100644 --- a/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.ts +++ b/alfa-client/libs/tech-shared/src/lib/decorator/catch-http-error.decorator.ts @@ -25,36 +25,55 @@ import { catchError } from 'rxjs/operators'; import { HttpErrorHandler } from '../error/error.handler'; import { enableInterceptorDefaultHandling, injectHttpErrorHandler } from './error.decorator.util'; -export function CatchHttpError(name: string, disableRetry: boolean = false, disableDefaultHandling: boolean = false): MethodDecorator { - return function (target: any, propertyName: any, descriptor: any) { - const originalMethod = descriptor.value; - descriptor.value = function (...args: any) { - const httpErrorHandler: HttpErrorHandler = injectHttpErrorHandler(); +export function CatchHttpError( + name: string, + disableRetry: boolean = false, + disableDefaultHandling: boolean = false, +): MethodDecorator { + return function (target: any, propertyName: any, descriptor: any) { + const originalMethod = descriptor.value; + descriptor.value = function (...args: any) { + const httpErrorHandler: HttpErrorHandler = injectHttpErrorHandler(); - handleDefaultErrorHandling(disableDefaultHandling, httpErrorHandler); - handleDefaultRetryHandling(disableRetry, httpErrorHandler); + handleDefaultErrorHandling(disableDefaultHandling, httpErrorHandler); + handleDefaultRetryHandling(disableRetry, httpErrorHandler); - return originalMethod.apply(this, args).pipe( - catchError(errorResponse => catchHttpErrorHandleErrorResponse(httpErrorHandler, errorResponse, name))); - }; - return descriptor; - } + return originalMethod + .apply(this, args) + .pipe( + catchError((errorResponse) => + catchHttpErrorHandleErrorResponse(httpErrorHandler, errorResponse, name), + ), + ); + }; + return descriptor; + }; } -export function handleDefaultErrorHandling(disableDefaultHandling: boolean, httpErrorHandler: HttpErrorHandler): void { - if (disableDefaultHandling) { - httpErrorHandler.disableDefaultHandling(); - } +export function handleDefaultErrorHandling( + disableDefaultHandling: boolean, + httpErrorHandler: HttpErrorHandler, +): void { + if (disableDefaultHandling) { + httpErrorHandler.disableDefaultHandling(); + } } -export function handleDefaultRetryHandling(disableRetry: boolean, httpErrorHandler: HttpErrorHandler): void { - if (disableRetry) { - httpErrorHandler.disableRetry(); - } +export function handleDefaultRetryHandling( + disableRetry: boolean, + httpErrorHandler: HttpErrorHandler, +): void { + if (disableRetry) { + httpErrorHandler.disableRetry(); + } } -export function catchHttpErrorHandleErrorResponse(httpErrorHandler: HttpErrorHandler, errorResponse: any, name: string): any { - enableInterceptorDefaultHandling(httpErrorHandler); - httpErrorHandler.doAfterErrorReceived(name, errorResponse); - return errorResponse; -} \ No newline at end of file +export function catchHttpErrorHandleErrorResponse( + httpErrorHandler: HttpErrorHandler, + errorResponse: any, + name: string, +): any { + enableInterceptorDefaultHandling(httpErrorHandler); + httpErrorHandler.doAfterErrorReceived(name, errorResponse); + return errorResponse; +} diff --git a/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.spec.ts index 835afe4fd6d03913fd76fa07694a098182478803..979cedea0b4c78886c580f5cc24cb22a717f4023 100644 --- a/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.spec.ts @@ -23,43 +23,43 @@ */ import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { HttpErrorHandler } from '../error/error.handler'; -import { disableInterceptorDefaultHandling, enableInterceptorDefaultHandling } from './error.decorator.util'; +import { + disableInterceptorDefaultHandling, + enableInterceptorDefaultHandling, +} from './error.decorator.util'; describe('Error decorator util', () => { + let httpErrorHandler: Mock<HttpErrorHandler>; - let httpErrorHandler: Mock<HttpErrorHandler>; + beforeEach(() => { + httpErrorHandler = mock(HttpErrorHandler); + }); - beforeEach(() => { - httpErrorHandler = mock(HttpErrorHandler); - }) + describe('enableInterceptorDefaultHandling', () => { + it('should enable default error handling', () => { + enableInterceptorDefaultHandling(useFromMock(httpErrorHandler)); - describe('enableInterceptorDefaultHandling', () => { + expect(httpErrorHandler.enableDefaultHandling).toHaveBeenCalled(); + }); - it('should enable default error handling', () => { - enableInterceptorDefaultHandling(useFromMock(httpErrorHandler)); + it('should enable default retry handling', () => { + enableInterceptorDefaultHandling(useFromMock(httpErrorHandler)); - expect(httpErrorHandler.enableDefaultHandling).toHaveBeenCalled(); - }) + expect(httpErrorHandler.enableRetry).toHaveBeenCalled(); + }); + }); - it('should enable default retry handling', () => { - enableInterceptorDefaultHandling(useFromMock(httpErrorHandler)); + describe('disableInterceptorDefaultHandling', () => { + it('should disable default error handling', () => { + disableInterceptorDefaultHandling(useFromMock(httpErrorHandler)); - expect(httpErrorHandler.enableRetry).toHaveBeenCalled(); - }) - }) + expect(httpErrorHandler.disableDefaultHandling).toHaveBeenCalled(); + }); - describe('disableInterceptorDefaultHandling', () => { + it('should disable default retry handling', () => { + disableInterceptorDefaultHandling(useFromMock(httpErrorHandler)); - it('should disable default error handling', () => { - disableInterceptorDefaultHandling(useFromMock(httpErrorHandler)); - - expect(httpErrorHandler.disableDefaultHandling).toHaveBeenCalled(); - }) - - it('should disable default retry handling', () => { - disableInterceptorDefaultHandling(useFromMock(httpErrorHandler)); - - expect(httpErrorHandler.disableRetry).toHaveBeenCalled(); - }) - }) -}) \ No newline at end of file + expect(httpErrorHandler.disableRetry).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.ts b/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.ts index 97eb1a5e176f1793a22f3e2d812eb0692d8273da..ab5b9f6b9227a417b6cff5e4969ee6c05d226b46 100644 --- a/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.ts +++ b/alfa-client/libs/tech-shared/src/lib/decorator/error.decorator.util.ts @@ -25,15 +25,15 @@ import { HttpErrorHandler } from '../error/error.handler'; import { TechSharedModule } from '../tech-shared.module'; export function injectHttpErrorHandler(): HttpErrorHandler { - return TechSharedModule.injector.get(HttpErrorHandler); + return TechSharedModule.injector.get(HttpErrorHandler); } export function enableInterceptorDefaultHandling(httpErrorHandler: HttpErrorHandler): void { - httpErrorHandler.enableDefaultHandling(); - httpErrorHandler.enableRetry(); + httpErrorHandler.enableDefaultHandling(); + httpErrorHandler.enableRetry(); } export function disableInterceptorDefaultHandling(httpErrorHandler: HttpErrorHandler): void { - httpErrorHandler.disableDefaultHandling(); - httpErrorHandler.disableRetry(); -} \ No newline at end of file + httpErrorHandler.disableDefaultHandling(); + httpErrorHandler.disableRetry(); +} diff --git a/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.spec.ts b/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.spec.ts index 48f8a49de7b48a24637361d27ec83580793207d7..d2096fdd1f39ae8c44dd8d7807a44a0ae81026b2 100644 --- a/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.spec.ts @@ -25,14 +25,13 @@ import { Mock, mock } from '@alfa-client/test-utils'; import { HttpErrorHandler } from '../error/error.handler'; describe('SkipInterceptor Decorator', () => { + let httpErrorHandler: Mock<HttpErrorHandler>; - let httpErrorHandler: Mock<HttpErrorHandler>; + beforeEach(() => { + httpErrorHandler = mock(HttpErrorHandler); + }); - beforeEach(() => { - httpErrorHandler = mock(HttpErrorHandler); - }) - - it.skip('should be created', () => { - //expect(SkipInterceptor()).toBeTruthy(); - }) -}) \ No newline at end of file + it.skip('should be created', () => { + //expect(SkipInterceptor()).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.ts b/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.ts index b28cd7137451cc9c361e500e751a5845f1977b9a..3b4e3082a758ae9b5739f2ca415d1c95a828a9cc 100644 --- a/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.ts +++ b/alfa-client/libs/tech-shared/src/lib/decorator/skip-error-interceptor.decorator.ts @@ -23,19 +23,25 @@ */ import { HttpErrorHandler } from '@alfa-client/tech-shared'; import { finalize } from 'rxjs/operators'; -import { disableInterceptorDefaultHandling, enableInterceptorDefaultHandling, injectHttpErrorHandler } from './error.decorator.util'; +import { + disableInterceptorDefaultHandling, + enableInterceptorDefaultHandling, + injectHttpErrorHandler, +} from './error.decorator.util'; export function SkipInterceptor(): MethodDecorator { - return function (target: any, propertyName: any, descriptor: any) { - const originalMethod = descriptor.value; + return function (target: any, propertyName: any, descriptor: any) { + const originalMethod = descriptor.value; - descriptor.value = function (...args: any) { - const httpErrorHandler: HttpErrorHandler = injectHttpErrorHandler(); + descriptor.value = function (...args: any) { + const httpErrorHandler: HttpErrorHandler = injectHttpErrorHandler(); - disableInterceptorDefaultHandling(httpErrorHandler); + disableInterceptorDefaultHandling(httpErrorHandler); - return originalMethod.apply(this, args).pipe(finalize(() => enableInterceptorDefaultHandling(httpErrorHandler))); - }; - return descriptor; - } -} \ No newline at end of file + return originalMethod + .apply(this, args) + .pipe(finalize(() => enableInterceptorDefaultHandling(httpErrorHandler))); + }; + return descriptor; + }; +} diff --git a/alfa-client/libs/tech-shared/src/lib/error/error.handler.ts b/alfa-client/libs/tech-shared/src/lib/error/error.handler.ts index 8388067ba294c9a3e174bb8ad83e13c06821c13c..4db0cac0a6d954a1f9270bd29c2941f967814d4b 100644 --- a/alfa-client/libs/tech-shared/src/lib/error/error.handler.ts +++ b/alfa-client/libs/tech-shared/src/lib/error/error.handler.ts @@ -28,48 +28,48 @@ import { BehaviorSubject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class HttpErrorHandler { + private readonly defaultHandling: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true); + private readonly retryOnConnectionTimeout: BehaviorSubject<boolean> = + new BehaviorSubject<boolean>(true); + private postErrorActionByName: { [key: string]: any } = {}; - private readonly defaultHandling: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true); - private readonly retryOnConnectionTimeout: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(true); - private postErrorActionByName: { [key: string]: any } = {}; + public registerCustomHandling(name: string, doAfterErrorReceived: any): void { + if (isNil(this.postErrorActionByName[name])) { + this.postErrorActionByName[name] = doAfterErrorReceived; + } else { + console.error(`HttpErrorHandler: duplicate post error action registration of ${name}`); + } + } - public registerCustomHandling(name: string, doAfterErrorReceived: any): void { - if (isNil(this.postErrorActionByName[name])) { - this.postErrorActionByName[name] = doAfterErrorReceived; - } else { - console.error(`HttpErrorHandler: duplicate post error action registration of ${name}`); - } - } + public doAfterErrorReceived(name: string, errorResponse: HttpErrorResponse): void { + if (!isNil(this.postErrorActionByName[name])) { + this.postErrorActionByName[name](errorResponse); + } else { + console.error(`HttpErrorHandler: no post error action defined for ${name}`); + } + } - public doAfterErrorReceived(name: string, errorResponse: HttpErrorResponse): void { - if (!isNil(this.postErrorActionByName[name])) { - this.postErrorActionByName[name](errorResponse); - } else { - console.error(`HttpErrorHandler: no post error action defined for ${name}`); - } - } + public enableDefaultHandling(): void { + this.defaultHandling.next(true); + } - public enableDefaultHandling(): void { - this.defaultHandling.next(true); - } + public shouldDoDefaultHandling(): boolean { + return this.defaultHandling.value; + } - public shouldDoDefaultHandling(): boolean { - return this.defaultHandling.value; - } + public disableDefaultHandling(): void { + this.defaultHandling.next(false); + } - public disableDefaultHandling(): void { - this.defaultHandling.next(false); - } + public enableRetry(): void { + this.retryOnConnectionTimeout.next(true); + } - public enableRetry(): void { - this.retryOnConnectionTimeout.next(true); - } + public shouldDoRetry(): boolean { + return this.retryOnConnectionTimeout.value; + } - public shouldDoRetry(): boolean { - return this.retryOnConnectionTimeout.value; - } - - public disableRetry(): void { - this.retryOnConnectionTimeout.next(false); - } -} \ No newline at end of file + public disableRetry(): void { + this.retryOnConnectionTimeout.next(false); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/error/error.util.ts b/alfa-client/libs/tech-shared/src/lib/error/error.util.ts index 9d6a8b56deaa8c6c04679506f6534173e331db28..c6029db8c9e7534811804cf9ed2e3ce929997b73 100644 --- a/alfa-client/libs/tech-shared/src/lib/error/error.util.ts +++ b/alfa-client/libs/tech-shared/src/lib/error/error.util.ts @@ -26,13 +26,13 @@ import { ApiError, MessageCode } from '@alfa-client/tech-shared'; import { isNil } from 'lodash-es'; export function isApiError(value: any): boolean { - return !isNil(value?.issues) && !isNil(value.issues[0]); + return !isNil(value?.issues) && !isNil(value.issues[0]); } export function isServiceUnavailableMessageCode(error: ApiError): boolean { - return error.issues[0].messageCode == MessageCode.SERVICE_UNAVAILABLE; + return error.issues[0].messageCode == MessageCode.SERVICE_UNAVAILABLE; } export function getApiErrorFromHttpErrorResponse(httpErrorResponse: HttpErrorResponse): ApiError { - return httpErrorResponse?.error?.error; -} \ No newline at end of file + return httpErrorResponse?.error?.error; +} diff --git a/alfa-client/libs/tech-shared/src/lib/form.util.ts b/alfa-client/libs/tech-shared/src/lib/form.util.ts index b94ee735c28e55dadec1012942cc8e9a5fa7c385..8e5454ef78e3a059a755ef17af59bbae894cc04f 100644 --- a/alfa-client/libs/tech-shared/src/lib/form.util.ts +++ b/alfa-client/libs/tech-shared/src/lib/form.util.ts @@ -1,4 +1,7 @@ import { Provider } from '@angular/core'; import { ControlContainer, FormGroupDirective } from '@angular/forms'; -export const FormProvider: Provider = { provide: ControlContainer, useExisting: FormGroupDirective }; \ No newline at end of file +export const FormProvider: Provider = { + provide: ControlContainer, + useExisting: FormGroupDirective, +}; diff --git a/alfa-client/libs/tech-shared/src/lib/http.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/http.util.spec.ts index 446a531338a5cb7a869c5d904d79fb0b383568e8..9889e0cf03739289e27d9af5cee7c09745b6ff68 100644 --- a/alfa-client/libs/tech-shared/src/lib/http.util.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/http.util.spec.ts @@ -22,148 +22,156 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { HttpResponse, HttpStatusCode } from '@angular/common/http'; -import { buildBlobWithFileName, isChangingDataRequest, isConnectionTimeout, isForbidden, isServerError, isServiceUnavailable, isUnauthorized, isUnprocessableEntity } from './http.util'; +import { + buildBlobWithFileName, + isChangingDataRequest, + isConnectionTimeout, + isForbidden, + isServerError, + isServiceUnavailable, + isUnauthorized, + isUnprocessableEntity, +} from './http.util'; import { BlobWithFileName, HttpMethod } from './tech.model'; describe('http util', () => { + const SERVER_ERROR_CODES: HttpStatusCode[] = [500, 501, 505, 506, 507, 508, 510, 511]; + const CONNECTION_TIMEOUT_CODES: HttpStatusCode[] = [502, 503, 504]; + const CLIENT_ERROR: HttpStatusCode[] = [400, 401, 402, 403, 404, 422]; + + describe('isForbidden', () => { + it.each(CLIENT_ERROR.slice(HttpStatusCode.Forbidden).concat(SERVER_ERROR_CODES))( + 'should be false on %i', + (httpStatusCode: HttpStatusCode) => { + const result: boolean = isForbidden(httpStatusCode); - const SERVER_ERROR_CODES: HttpStatusCode[] = [500, 501, 505, 506, 507, 508, 510, 511]; - const CONNECTION_TIMEOUT_CODES: HttpStatusCode[] = [502, 503, 504]; - const CLIENT_ERROR: HttpStatusCode[] = [400, 401, 402, 403, 404, 422]; + expect(result).toBeFalsy(); + }, + ); - describe('isForbidden', () => { + it('should be true on 403', () => { + const result: boolean = isForbidden(HttpStatusCode.Forbidden); - it.each(CLIENT_ERROR.slice(HttpStatusCode.Forbidden).concat(SERVER_ERROR_CODES)) - ('should be false on %i', (httpStatusCode: HttpStatusCode) => { - const result: boolean = isForbidden(httpStatusCode); + expect(result).toBeTruthy(); + }); + }); - expect(result).toBeFalsy(); - }); + describe('isUnauthorized', () => { + it.each(CLIENT_ERROR.slice(HttpStatusCode.Unauthorized).concat(SERVER_ERROR_CODES))( + 'should be false on %i', + (httpStatusCode: HttpStatusCode) => { + const result: boolean = isUnauthorized(httpStatusCode); - it('should be true on 403', () => { - const result: boolean = isForbidden(HttpStatusCode.Forbidden); + expect(result).toBeFalsy(); + }, + ); - expect(result).toBeTruthy(); - }) - }) + it('should be true on 401', () => { + const result: boolean = isUnauthorized(HttpStatusCode.Unauthorized); - describe('isUnauthorized', () => { + expect(result).toBeTruthy(); + }); + }); - it.each(CLIENT_ERROR.slice(HttpStatusCode.Unauthorized).concat(SERVER_ERROR_CODES)) - ('should be false on %i', (httpStatusCode: HttpStatusCode) => { - const result: boolean = isUnauthorized(httpStatusCode); + describe('isServerError', () => { + it.each(SERVER_ERROR_CODES)('should be true on %i', (httpStatusCode: HttpStatusCode) => { + const result: boolean = isServerError(httpStatusCode); + + expect(result).toBeTruthy(); + }); + + it.each(CLIENT_ERROR.concat(CONNECTION_TIMEOUT_CODES))('should be false on %i', () => { + const result: boolean = isServerError(HttpStatusCode.Forbidden); + + expect(result).toBeFalsy(); + }); + }); + + describe('isUnprocessableEntity', () => { + it.each( + CLIENT_ERROR.slice(HttpStatusCode.UnprocessableEntity) + .concat(SERVER_ERROR_CODES) + .concat(SERVER_ERROR_CODES), + )('should be false on %i', (httpStatusCode: HttpStatusCode) => { + const result: boolean = isUnprocessableEntity(httpStatusCode); + + expect(result).toBeFalsy(); + }); + + it('should be true on %i', () => { + const result: boolean = isUnprocessableEntity(HttpStatusCode.UnprocessableEntity); + + expect(result).toBeTruthy(); + }); + }); + + describe('isChangingDataRequest', () => { + const CHANGING_DATA_REQUEST_METHOD: string[] = [ + HttpMethod.POST, + HttpMethod.PUT, + HttpMethod.PATCH, + HttpMethod.DELETE, + ]; + + it.each(CHANGING_DATA_REQUEST_METHOD)('should return true on %i', (method: string) => { + const result: boolean = isChangingDataRequest(<any>{ method }); + + expect(result).toBeTruthy(); + }); + + it('should return false on %i', () => { + const result: boolean = isChangingDataRequest(<any>{ method: HttpMethod.GET }); + + expect(result).toBeFalsy(); + }); + }); + + describe('isConnectionTimeout', () => { + it.each(CONNECTION_TIMEOUT_CODES)('should return true on %i', (statusCode: number) => { + const result: boolean = isConnectionTimeout(statusCode); + + expect(result).toBeTruthy(); + }); + + it.each(SERVER_ERROR_CODES)('should return false on %i', (statusCode: number) => { + const result: boolean = isConnectionTimeout(statusCode); + + expect(result).toBeFalsy(); + }); + }); + + describe('isServiceUnavailable', () => { + it('should return true on %i', () => { + const result: boolean = isServiceUnavailable(HttpStatusCode.ServiceUnavailable); - expect(result).toBeFalsy(); - }); + expect(result).toBeTruthy(); + }); - it('should be true on 401', () => { - const result: boolean = isUnauthorized(HttpStatusCode.Unauthorized); + it.each( + SERVER_ERROR_CODES.concat(CONNECTION_TIMEOUT_CODES.slice(HttpStatusCode.ServiceUnavailable)), + )('should return false on %i', (statusCode: number) => { + const result: boolean = isServiceUnavailable(statusCode); - expect(result).toBeTruthy(); - }); - }) + expect(result).toBeFalsy(); + }); + }); - describe('isServerError', () => { + describe('buildBlobWithFileName', () => { + const body: Blob = new Blob(); + const fileName: string = '927ee047-0123-4c36-911c-52e984accc87_Abgabe.Abgabe.0401.xdomea'; + const headerString: string = 'attachment; filename=' + fileName; + const httpResponse: HttpResponse<Blob> = <any>{ body, headers: { get: () => headerString } }; - it.each(SERVER_ERROR_CODES) - ('should be true on %i', (httpStatusCode: HttpStatusCode) => { - const result: boolean = isServerError(httpStatusCode); + it('should have blob', () => { + const blobWithFileName: BlobWithFileName = buildBlobWithFileName(httpResponse); - expect(result).toBeTruthy(); - }); + expect(blobWithFileName.blob).toEqual(body); + }); - it.each(CLIENT_ERROR.concat(CONNECTION_TIMEOUT_CODES)) - ('should be false on %i', () => { - const result: boolean = isServerError(HttpStatusCode.Forbidden); + it('should have fileName', () => { + const blobWithFileName: BlobWithFileName = buildBlobWithFileName(httpResponse); - expect(result).toBeFalsy(); - }) - }) - - describe('isUnprocessableEntity', () => { - - it.each(CLIENT_ERROR.slice(HttpStatusCode.UnprocessableEntity).concat(SERVER_ERROR_CODES).concat(SERVER_ERROR_CODES)) - ('should be false on %i', (httpStatusCode: HttpStatusCode) => { - const result: boolean = isUnprocessableEntity(httpStatusCode); - - expect(result).toBeFalsy(); - }); - - it('should be true on %i', () => { - const result: boolean = isUnprocessableEntity(HttpStatusCode.UnprocessableEntity); - - expect(result).toBeTruthy(); - }) - }) - - describe('isChangingDataRequest', () => { - - const CHANGING_DATA_REQUEST_METHOD: string[] = [HttpMethod.POST, HttpMethod.PUT, HttpMethod.PATCH, HttpMethod.DELETE]; - - it.each(CHANGING_DATA_REQUEST_METHOD) - ('should return true on %i', (method: string) => { - const result: boolean = isChangingDataRequest(<any>{ method }); - - expect(result).toBeTruthy(); - }) - - it('should return false on %i', () => { - const result: boolean = isChangingDataRequest(<any>{ method: HttpMethod.GET }); - - expect(result).toBeFalsy(); - }) - }) - - describe('isConnectionTimeout', () => { - - it.each(CONNECTION_TIMEOUT_CODES) - ('should return true on %i', (statusCode: number) => { - const result: boolean = isConnectionTimeout(statusCode); - - expect(result).toBeTruthy(); - }) - - it.each(SERVER_ERROR_CODES) - ('should return false on %i', (statusCode: number) => { - const result: boolean = isConnectionTimeout(statusCode); - - expect(result).toBeFalsy(); - }) - }) - - describe('isServiceUnavailable', () => { - - it('should return true on %i', () => { - const result: boolean = isServiceUnavailable(HttpStatusCode.ServiceUnavailable); - - expect(result).toBeTruthy(); - }) - - it.each(SERVER_ERROR_CODES.concat(CONNECTION_TIMEOUT_CODES.slice(HttpStatusCode.ServiceUnavailable))) - ('should return false on %i', (statusCode: number) => { - const result: boolean = isServiceUnavailable(statusCode); - - expect(result).toBeFalsy(); - }) - }) - - describe('buildBlobWithFileName', () => { - - const body: Blob = new Blob(); - const fileName: string = '927ee047-0123-4c36-911c-52e984accc87_Abgabe.Abgabe.0401.xdomea'; - const headerString: string = 'attachment; filename=' + fileName - const httpResponse: HttpResponse<Blob> = <any>{ body, headers: { get: () => headerString }}; - - it('should have blob', () => { - const blobWithFileName: BlobWithFileName = buildBlobWithFileName(httpResponse); - - expect(blobWithFileName.blob).toEqual(body); - }) - - it('should have fileName', () => { - const blobWithFileName: BlobWithFileName = buildBlobWithFileName(httpResponse); - - expect(blobWithFileName.fileName).toEqual(fileName); - }) - }) -}) \ No newline at end of file + expect(blobWithFileName.fileName).toEqual(fileName); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/http.util.ts b/alfa-client/libs/tech-shared/src/lib/http.util.ts index 19d200b98b78fe9e8f4de4804fe80156e71b2d34..4a26c2806d506512cdee4c094985f0d898046f1a 100644 --- a/alfa-client/libs/tech-shared/src/lib/http.util.ts +++ b/alfa-client/libs/tech-shared/src/lib/http.util.ts @@ -25,62 +25,71 @@ import { HttpRequest, HttpResponse, HttpStatusCode } from '@angular/common/http' import { BlobWithFileName, HttpHeader, HttpMethod } from './tech.model'; export function isForbidden(status: HttpStatusCode): boolean { - return status == HttpStatusCode.Forbidden; + return status == HttpStatusCode.Forbidden; } export function isUnauthorized(status: HttpStatusCode): boolean { - return status == HttpStatusCode.Unauthorized; + return status == HttpStatusCode.Unauthorized; } export function isUnprocessableEntity(status: HttpStatusCode): boolean { - return status == HttpStatusCode.UnprocessableEntity; + return status == HttpStatusCode.UnprocessableEntity; } export function isServerError(status: HttpStatusCode): boolean { - return status >= 500 && status < 600 && !isConnectionTimeout(status); + return status >= 500 && status < 600 && !isConnectionTimeout(status); } export function isConnectionTimeout(status: HttpStatusCode): boolean { - return isBadGateway(status) || isServiceUnavailable(status) || isGatewayTimeout(status); + return isBadGateway(status) || isServiceUnavailable(status) || isGatewayTimeout(status); } function isBadGateway(status: HttpStatusCode): boolean { - return status == HttpStatusCode.BadGateway; + return status == HttpStatusCode.BadGateway; } export function isServiceUnavailable(status: HttpStatusCode): boolean { - return status == HttpStatusCode.ServiceUnavailable; + return status == HttpStatusCode.ServiceUnavailable; } function isGatewayTimeout(status: HttpStatusCode): boolean { - return status == HttpStatusCode.GatewayTimeout; + return status == HttpStatusCode.GatewayTimeout; } export function isNotFound(status: HttpStatusCode): boolean { - return status == HttpStatusCode.NotFound; + return status == HttpStatusCode.NotFound; } export function isChangingDataRequest(request: HttpRequest<unknown>): boolean { - return request.method === HttpMethod.POST || request.method === HttpMethod.PUT || request.method === HttpMethod.PATCH || request.method === HttpMethod.DELETE; + return ( + request.method === HttpMethod.POST || + request.method === HttpMethod.PUT || + request.method === HttpMethod.PATCH || + request.method === HttpMethod.DELETE + ); } export function existRequestHeader(request: HttpRequest<unknown>, key: string) { - return request.headers.has(key); + return request.headers.has(key); } -export function addRequestHeader(request: HttpRequest<unknown>, key: string, token: string): HttpRequest<unknown> { - return request.clone({ headers: request.headers.set(key, token) }); +export function addRequestHeader( + request: HttpRequest<unknown>, + key: string, + token: string, +): HttpRequest<unknown> { + return request.clone({ headers: request.headers.set(key, token) }); } export function buildBlobWithFileName(response: HttpResponse<Blob>): BlobWithFileName { - return { blob: response.body, fileName: extractFileNameFromResponse(response) }; + return { blob: response.body, fileName: extractFileNameFromResponse(response) }; } function extractFileNameFromResponse(response: HttpResponse<Blob>): string { - const header: string = getContentDispositionHeader(response); - return header.substring(header.lastIndexOf('filename') + 9, header.length); + const header: string = getContentDispositionHeader(response); + return header.substring(header.lastIndexOf('filename') + 9, header.length); } function getContentDispositionHeader(response: HttpResponse<Blob>): string { - return response.headers.get(HttpHeader.CONTENT_DISPOSITION); -} \ No newline at end of file + return response.headers.get(HttpHeader.CONTENT_DISPOSITION); +} diff --git a/alfa-client/libs/tech-shared/src/lib/interceptor/http-binary-file.interceptor.ts b/alfa-client/libs/tech-shared/src/lib/interceptor/http-binary-file.interceptor.ts index 69f4d0823774ea979f25be02eaaf6d5ab4cb71ca..f71c08b76ea28f1af0ee28ec6e01e6510994b45c 100644 --- a/alfa-client/libs/tech-shared/src/lib/interceptor/http-binary-file.interceptor.ts +++ b/alfa-client/libs/tech-shared/src/lib/interceptor/http-binary-file.interceptor.ts @@ -21,7 +21,14 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponseBase } from '@angular/common/http'; +import { + HttpErrorResponse, + HttpEvent, + HttpHandler, + HttpInterceptor, + HttpRequest, + HttpResponseBase, +} from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable, throwError } from 'rxjs'; import { catchError } from 'rxjs/operators'; @@ -32,43 +39,48 @@ import { catchError } from 'rxjs/operators'; // Der kopierte Code ist minimal richtung CleanCode optimiert @Injectable() export class HttpBinaryFileInterceptor implements HttpInterceptor { + public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { + return next.handle(req).pipe( + catchError((response: HttpResponseBase) => { + if (this.shouldConvertToJson((<any>response).error)) { + return this.convertToJson((<HttpErrorResponse>response).error); + } + return throwError(response); + }), + ); + } - public intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { - return next.handle(req).pipe(catchError((response: HttpResponseBase) => { - if (this.shouldConvertToJson((<any>response).error)) { - return this.convertToJson((<HttpErrorResponse>response).error) - } - return throwError(response); - })); - } + private shouldConvertToJson(err: HttpResponseBase): boolean { + return ( + err instanceof HttpErrorResponse && + err.error instanceof Blob && + err.error.type === 'application/json' + ); + } - private shouldConvertToJson(err: HttpResponseBase): boolean { - return err instanceof HttpErrorResponse && err.error instanceof Blob && err.error.type === 'application/json'; - } + convertToJson(errorResponse: HttpErrorResponse): Promise<any> { + return new Promise<any>((resolve, reject) => { + let reader = new FileReader(); + reader.onload = (event: Event) => { + try { + reject(this.buildResponse(errorResponse, event)); + } catch (error) { + reject(errorResponse); + } + }; + reader.onerror = (e) => reject(errorResponse); + reader.readAsText(errorResponse.error); + }); + } - convertToJson(errorResponse: HttpErrorResponse): Promise<any> { - return new Promise<any>((resolve, reject) => { - let reader = new FileReader(); - reader.onload = (event: Event) => { - try { - reject(this.buildResponse(errorResponse, event)) - } catch (error) { - reject(errorResponse); - } - }; - reader.onerror = (e) => reject(errorResponse); - reader.readAsText((errorResponse).error); - }); - } - - buildResponse(err: HttpResponseBase, event: Event): HttpErrorResponse { - const errmsg = JSON.parse((<any>event.target).result); - return new HttpErrorResponse({ - error: errmsg, - headers: err.headers, - status: err.status, - statusText: err.statusText, - url: err.url - }) - } -} \ No newline at end of file + buildResponse(err: HttpResponseBase, event: Event): HttpErrorResponse { + const errmsg = JSON.parse((<any>event.target).result); + return new HttpErrorResponse({ + error: errmsg, + headers: err.headers, + status: err.status, + statusText: err.statusText, + url: err.url, + }); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.spec.ts b/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.spec.ts index 277347249251bba9f7cc2581f85e87b541417557..48ec7f024c731f600ec72f6d8ffb4f6da8fe1ed7 100644 --- a/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.spec.ts @@ -26,16 +26,14 @@ import { HttpXsrfInterceptor } from './http-xsrf.interceptor'; import { HttpXsrfTokenExtractor } from '@angular/common/http'; describe('HttpXsrfInterceptor', () => { + beforeEach(() => + TestBed.configureTestingModule({ + providers: [HttpXsrfInterceptor, HttpXsrfTokenExtractor], + }), + ); - beforeEach(() => TestBed.configureTestingModule({ - providers: [ - HttpXsrfInterceptor, - HttpXsrfTokenExtractor - ] - })); - - it('should be created', () => { - const interceptor: HttpXsrfInterceptor = TestBed.inject(HttpXsrfInterceptor); - expect(interceptor).toBeTruthy(); - }); + it('should be created', () => { + const interceptor: HttpXsrfInterceptor = TestBed.inject(HttpXsrfInterceptor); + expect(interceptor).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.ts b/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.ts index 11606baad2d236b732de908416146062026789de..a7dcd4c44cf9af5283a5af62eda4c707cababcf7 100644 --- a/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.ts +++ b/alfa-client/libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor.ts @@ -21,7 +21,13 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpXsrfTokenExtractor } from '@angular/common/http'; +import { + HttpEvent, + HttpHandler, + HttpInterceptor, + HttpRequest, + HttpXsrfTokenExtractor, +} from '@angular/common/http'; import { Injectable } from '@angular/core'; import { addRequestHeader, isNotNull } from '@alfa-client/tech-shared'; import { Observable } from 'rxjs'; @@ -29,27 +35,26 @@ import { existRequestHeader, isChangingDataRequest } from '../http.util'; @Injectable() export class HttpXsrfInterceptor implements HttpInterceptor { + static readonly X_XSRF_TOKEN_HEADER: string = 'X-XSRF-TOKEN'; - static readonly X_XSRF_TOKEN_HEADER: string = 'X-XSRF-TOKEN'; + constructor(private tokenExtractor: HttpXsrfTokenExtractor) {} - constructor(private tokenExtractor: HttpXsrfTokenExtractor) { } + intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { + if (isChangingDataRequest(request)) { + request = this.handleRequest(request); + } + return next.handle(request); + } - intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { - if (isChangingDataRequest(request)) { - request = this.handleRequest(request); - } - return next.handle(request); - } + private handleRequest(request: HttpRequest<unknown>): HttpRequest<unknown> { + let token: string = this.getToken(); + if (isNotNull(token) && !existRequestHeader(request, HttpXsrfInterceptor.X_XSRF_TOKEN_HEADER)) { + request = addRequestHeader(request, HttpXsrfInterceptor.X_XSRF_TOKEN_HEADER, token); + } + return request; + } - private handleRequest(request: HttpRequest<unknown>): HttpRequest<unknown> { - let token: string = this.getToken(); - if (isNotNull(token) && !existRequestHeader(request, HttpXsrfInterceptor.X_XSRF_TOKEN_HEADER)) { - request = addRequestHeader(request, HttpXsrfInterceptor.X_XSRF_TOKEN_HEADER, token); - } - return request; - } - - private getToken(): string { - return this.tokenExtractor.getToken(); - } -} \ No newline at end of file + private getToken(): string { + return this.tokenExtractor.getToken(); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/interceptor/xhr.interceptor.spec.ts b/alfa-client/libs/tech-shared/src/lib/interceptor/xhr.interceptor.spec.ts index 5b91bc43068843b7fcc84c5791146696c0a2557e..43f7d90d77f3fdf69a0f51ac81f74577ed5d1020 100644 --- a/alfa-client/libs/tech-shared/src/lib/interceptor/xhr.interceptor.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/interceptor/xhr.interceptor.spec.ts @@ -27,26 +27,25 @@ import { HttpMethod } from '../tech.model'; import { XhrInterceptor } from './xhr.interceptor'; describe('XhrInterceptor', () => { - let interceptor: XhrInterceptor; + let interceptor: XhrInterceptor; - const url: string = faker.internet.url(); + const url: string = faker.internet.url(); - beforeEach(() => { - interceptor = new XhrInterceptor(); - }) + beforeEach(() => { + interceptor = new XhrInterceptor(); + }); - it('should be created', () => { - expect(interceptor).toBeTruthy(); - }); + it('should be created', () => { + expect(interceptor).toBeTruthy(); + }); - describe('addHeader', () => { + describe('addHeader', () => { + it('should add X-Requested-With header', () => { + const request: HttpRequest<unknown> = new HttpRequest(HttpMethod.GET, url); - it('should add X-Requested-With header', () => { - const request: HttpRequest<unknown> = new HttpRequest(HttpMethod.GET, url); + const result: HttpRequest<unknown> = interceptor.addHeader(request); - const result: HttpRequest<unknown> = interceptor.addHeader(request); - - expect(result.headers.get('X-Requested-With')).toEqual('XMLHttpRequest'); - }) - }) -}); \ No newline at end of file + expect(result.headers.get('X-Requested-With')).toEqual('XMLHttpRequest'); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/interceptor/xhr.interceptor.ts b/alfa-client/libs/tech-shared/src/lib/interceptor/xhr.interceptor.ts index 6d606a89bdca4aa6290ea82f5ab04d44d864a326..9db6425f7156e4d8a6c0d74ddf07aa3e6e421022 100644 --- a/alfa-client/libs/tech-shared/src/lib/interceptor/xhr.interceptor.ts +++ b/alfa-client/libs/tech-shared/src/lib/interceptor/xhr.interceptor.ts @@ -27,14 +27,13 @@ import { Observable } from 'rxjs'; @Injectable() export class XhrInterceptor implements HttpInterceptor { + intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { + return next.handle(this.addHeader(req)); + } - intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { - return next.handle(this.addHeader(req)); - } - - addHeader(req: HttpRequest<unknown>): HttpRequest<unknown> { - return req.clone({ - headers: req.headers.set('X-Requested-With', 'XMLHttpRequest') - }); - } -} \ No newline at end of file + addHeader(req: HttpRequest<unknown>): HttpRequest<unknown> { + return req.clone({ + headers: req.headers.set('X-Requested-With', 'XMLHttpRequest'), + }); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/message-code.ts b/alfa-client/libs/tech-shared/src/lib/message-code.ts index 1818014e635c66dcfda8f64a9395646b63902365..2532a2b12056c4f179d1f6a7b6bdff2d49cbf11a 100644 --- a/alfa-client/libs/tech-shared/src/lib/message-code.ts +++ b/alfa-client/libs/tech-shared/src/lib/message-code.ts @@ -22,7 +22,7 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum MessageCode { - RESOURCE_NOT_FOUND = 'resource.not_found', - SERVICE_UNAVAILABLE = 'generale.service_unavailable', - USER_MANAGER_SERVICE_UNAVAILABLE = 'general.service_unavailable.usermanager' + RESOURCE_NOT_FOUND = 'resource.not_found', + SERVICE_UNAVAILABLE = 'generale.service_unavailable', + USER_MANAGER_SERVICE_UNAVAILABLE = 'general.service_unavailable.usermanager', } diff --git a/alfa-client/libs/tech-shared/src/lib/ngrx/actions.ts b/alfa-client/libs/tech-shared/src/lib/ngrx/actions.ts index ae9c89b4622151dae796471c3ad7ef10b0c70f71..907ccaf7749c9f9cb7438addf98a0da8b56de6dc 100644 --- a/alfa-client/libs/tech-shared/src/lib/ngrx/actions.ts +++ b/alfa-client/libs/tech-shared/src/lib/ngrx/actions.ts @@ -28,13 +28,15 @@ import { ApiError } from '../tech.model'; export const EMPTY_ACTION: Action = {} as Action; -export interface TypedActionCreatorWithProps<T> extends ActionCreator<string, (props: T) => T & TypedAction<string>> { } -export interface TypedActionCreator extends ActionCreator<string, () => TypedAction<string>> { } +export interface TypedActionCreatorWithProps<T> + extends ActionCreator<string, (props: T) => T & TypedAction<string>> {} +export interface TypedActionCreator extends ActionCreator<string, () => TypedAction<string>> {} -export interface ApiErrorAction {//TODO rename ApiErrorProps - apiError: ApiError +export interface ApiErrorAction { + //TODO rename ApiErrorProps + apiError: ApiError; } export interface ResourceUriProps { - resourceUri: ResourceUri -} \ No newline at end of file + resourceUri: ResourceUri; +} diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.spec.ts index fc8c33edc0481742a44040cfe48b1806814897a7..bdccd48d064c38005764cbd5655e50e4ad96528c 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.spec.ts @@ -24,29 +24,27 @@ import { ConvertForDataTestPipe } from './convert-for-data-test.pipe'; describe('convertForDataTest', () => { - const pipe = new ConvertForDataTestPipe(); + const pipe = new ConvertForDataTestPipe(); - it('create an instance', () => { - expect(pipe).toBeTruthy(); - }); + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); - describe('transform null value', () => { + describe('transform null value', () => { + it('should return null', () => { + const result: any = pipe.transform(null); - it('should return null', () => { - const result: any = pipe.transform(null); + expect(result).toBeNull(); + }); + }); - expect(result).toBeNull(); - }) - }) + describe('transform string value', () => { + it('should replace space by underscore', () => { + const value: string = 'value replacing space'; - describe('transform string value', () => { + const result: any = pipe.transform(value); - it('should replace space by underscore', () => { - const value: string = 'value replacing space'; - - const result: any = pipe.transform(value); - - expect(result).toBe('value_replacing_space'); - }) - }) -}) \ No newline at end of file + expect(result).toBe('value_replacing_space'); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.ts index 0375d65c9e01e259910bc0f3e4cdd7c0efc8bcca..e056b77eb22f32ed6c2b9c9765c5101252acef18 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/convert-for-data-test.pipe.ts @@ -27,7 +27,7 @@ import { convertForDataTest } from '../tech.util'; @Pipe({ name: 'convertForDataTest' }) export class ConvertForDataTestPipe implements PipeTransform { - transform(value: string) { - return isNil(value) ? null : convertForDataTest(value); - } -} \ No newline at end of file + transform(value: string) { + return isNil(value) ? null : convertForDataTest(value); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.spec.ts index ac01fd5505b63817da54cb9d325cda428eb5958e..bcb5ccda18d145f7568d740b50828eed2ecd9555 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.spec.ts @@ -24,42 +24,42 @@ import { EnumToLabelPipe } from './enum-to-label.pipe'; describe('EnumToLabelPipe', () => { - const pipe = new EnumToLabelPipe(); + const pipe = new EnumToLabelPipe(); - it('create an instance', () => { - expect(pipe).toBeTruthy(); - }); + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); - describe('transform enum to label', () => { - it('output as expected', () => { - const enumValue = DummyStatus.TEST; - const enumValueLabel: string = DummyStatusLabel[enumValue]; + describe('transform enum to label', () => { + it('output as expected', () => { + const enumValue = DummyStatus.TEST; + const enumValueLabel: string = DummyStatusLabel[enumValue]; - const result = pipe.transform(enumValue, DummyStatusLabel); + const result = pipe.transform(enumValue, DummyStatusLabel); - expect(result).toBe(enumValueLabel); - }); + expect(result).toBe(enumValueLabel); + }); - it('enumValue is null', () => { - const result = pipe.transform(null, DummyStatusLabel); + it('enumValue is null', () => { + const result = pipe.transform(null, DummyStatusLabel); - expect(result).toBe(null); - }); + expect(result).toBe(null); + }); - it('enumLabel is null', () => { - const enumValue = DummyStatus.TEST; + it('enumLabel is null', () => { + const enumValue = DummyStatus.TEST; - const result = pipe.transform(enumValue, null); + const result = pipe.transform(enumValue, null); - expect(result).toBe(null); - }); - }) + expect(result).toBe(null); + }); + }); }); export enum DummyStatus { - TEST + TEST, } export enum DummyStatusLabel { - TEST = 'test' -} \ No newline at end of file + TEST = 'test', +} diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.ts index 31c379bcc02a78267e9247d8610e322f012730ff..5ad36f8845b75a9625f35f434bff4a7f94acf23a 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/enum-to-label.pipe.ts @@ -26,7 +26,7 @@ import { isNil } from 'lodash-es'; @Pipe({ name: 'enumToLabel' }) export class EnumToLabelPipe implements PipeTransform { - transform(enumValue: any, enumLabel: any) { - return (isNil(enumValue) || isNil(enumLabel)) ? null : enumLabel[enumValue]; - } + transform(enumValue: any, enumLabel: any) { + return isNil(enumValue) || isNil(enumLabel) ? null : enumLabel[enumValue]; + } } diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.spec.ts index 4cc28b870ce62395e9b6500e7ed70452f38452ac..758ba85d6ec9454d05eb43a218bde742fc6e1b8c 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.spec.ts @@ -24,40 +24,38 @@ import { FileSizePipe } from './file-size.pipe'; describe('FileSizePipe', () => { - const pipe = new FileSizePipe(); + const pipe = new FileSizePipe(); - it('create an instance', () => { - expect(pipe).toBeTruthy(); - }); + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); - describe('pass date in pipe', () => { - const kb = 1024; + describe('pass date in pipe', () => { + const kb = 1024; - it('1.073.741.824 should return 1,00 GB', () => { - const size = Math.pow(kb, 3); + it('1.073.741.824 should return 1,00 GB', () => { + const size = Math.pow(kb, 3); - const pipeResult: string = pipe.transform(size); + const pipeResult: string = pipe.transform(size); - expect(pipeResult).toBe('1,00<span class="unit">GB</span>'); - }); + expect(pipeResult).toBe('1,00<span class="unit">GB</span>'); + }); - it('1.048.576 should return 1,00 MB', () => { - const size = Math.pow(kb, 2); + it('1.048.576 should return 1,00 MB', () => { + const size = Math.pow(kb, 2); - const pipeResult: string = pipe.transform(size); + const pipeResult: string = pipe.transform(size); - expect(pipeResult).toBe('1,00<span class="unit">MB</span>'); - }); + expect(pipeResult).toBe('1,00<span class="unit">MB</span>'); + }); - it('1000 should return 0,98 kB', () => { - const size = 1000; - const expectedSize = (size / kb).toFixed(2).replace('.', ','); - - const pipeResult: string = pipe.transform(size); - - expect(pipeResult).toBe(`${expectedSize}<span class="unit">kB</span>`); - }); - }); + it('1000 should return 0,98 kB', () => { + const size = 1000; + const expectedSize = (size / kb).toFixed(2).replace('.', ','); + const pipeResult: string = pipe.transform(size); + expect(pipeResult).toBe(`${expectedSize}<span class="unit">kB</span>`); + }); + }); }); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.ts index 38c97e6a9ac184a3acb006ab9f762d61f23ca7df..a8ca257d0b3687a5684b809694a56c421ae43ffd 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/file-size.pipe.ts @@ -25,17 +25,17 @@ import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'fileSize' }) export class FileSizePipe implements PipeTransform { - readonly kB = 1024; - readonly MB = Math.pow(this.kB, 2); - readonly GB = Math.pow(this.kB, 3); + readonly kB = 1024; + readonly MB = Math.pow(this.kB, 2); + readonly GB = Math.pow(this.kB, 3); - transform(size: number) { - if (size >= this.GB) return this.formatFileSize(size / this.GB, 'GB'); - if (size >= this.MB) return this.formatFileSize(size / this.MB, 'MB'); - return this.formatFileSize(size / this.kB, 'kB'); - } + transform(size: number) { + if (size >= this.GB) return this.formatFileSize(size / this.GB, 'GB'); + if (size >= this.MB) return this.formatFileSize(size / this.MB, 'MB'); + return this.formatFileSize(size / this.kB, 'kB'); + } - private formatFileSize(number: number, unit: string) { - return `${number.toFixed(2).replace('.', ',')}<span class="unit">${unit}</span>`; - } + private formatFileSize(number: number, unit: string) { + return `${number.toFixed(2).replace('.', ',')}<span class="unit">${unit}</span>`; + } } diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.spec.ts index cdd729c3b78439c3d005cddefda4807c307a1857..789e8a2cb1604a9bf63dbfa8d7697d672b95326f 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.spec.ts @@ -29,25 +29,25 @@ import { FormatDateWithTimePipe } from './format-date-with-time.pipe'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('FormatDateWithTimePipe', () => { - let pipe: FormatDateWithTimePipe = new FormatDateWithTimePipe(); + let pipe: FormatDateWithTimePipe = new FormatDateWithTimePipe(); - it('should create', () => { - expect(pipe).toBeTruthy(); - }); + it('should create', () => { + expect(pipe).toBeTruthy(); + }); - it('should return formatted date with time and day', () => { - const date: Date = new Date('01.01.2021'); + it('should return formatted date with time and day', () => { + const date: Date = new Date('01.01.2021'); - const result: string = pipe.transform(date); + const result: string = pipe.transform(date); - expect(result).toBe('Freitag, 01.01.2021, 00:00:00'); - }) + expect(result).toBe('Freitag, 01.01.2021, 00:00:00'); + }); - it('should return formatted date with time without seconds and day', () => { - const date: Date = new Date('01.01.2021'); + it('should return formatted date with time without seconds and day', () => { + const date: Date = new Date('01.01.2021'); - const result: string = pipe.transform(date, false); + const result: string = pipe.transform(date, false); - expect(result).toBe('01.01.21 00:00'); - }) -}) \ No newline at end of file + expect(result).toBe('01.01.21 00:00'); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.ts index a6551f8329dc2f421107d96961b36ec58593b24c..d366ee34d67b1329cb31abd6883deeafec8afab9 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-with-time.pipe.ts @@ -26,9 +26,9 @@ import { formatFullDateWithTimeAndDay, formatFullDateWithTimeWithoutSeconds } fr @Pipe({ name: 'formatDateWithTimePipe' }) export class FormatDateWithTimePipe implements PipeTransform { - transform(date: Date, withSeconds: boolean = true): string { - return withSeconds - ? formatFullDateWithTimeAndDay(date) - : formatFullDateWithTimeWithoutSeconds(date); - } -} \ No newline at end of file + transform(date: Date, withSeconds: boolean = true): string { + return withSeconds ? + formatFullDateWithTimeAndDay(date) + : formatFullDateWithTimeWithoutSeconds(date); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.spec.ts index 2c472008d9506db725ae9cdd588aeaf644c064c9..9b800e392bd88bea703ad1ea87fd72920107a37b 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.spec.ts @@ -29,18 +29,17 @@ import { FormatDateWithoutYearWithTimePipe } from './format-date-without-year-wi registerLocaleData(localeDe, 'de', localeDeExtra); describe('FormatDateWithoutYearWithTimePipe', () => { - let pipe: FormatDateWithoutYearWithTimePipe = new FormatDateWithoutYearWithTimePipe(); + let pipe: FormatDateWithoutYearWithTimePipe = new FormatDateWithoutYearWithTimePipe(); - it('should create', () => { - expect(pipe).toBeTruthy(); - }); + it('should create', () => { + expect(pipe).toBeTruthy(); + }); - it('should return formatted date with time and day', () => { - const date: Date = new Date('01.01.2021'); + it('should return formatted date with time and day', () => { + const date: Date = new Date('01.01.2021'); - const result: string = pipe.transform(date); + const result: string = pipe.transform(date); - expect(result).toBe('01. Jan. 00:00'); - }) - -}) \ No newline at end of file + expect(result).toBe('01. Jan. 00:00'); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.ts index 1db9ea10b06ca34f5640ebb3f99c2d02a51c42cf..52234be39abbb3dd7d604bfc54882807e85bd0b4 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/format-date-without-year-with-time.pipe.ts @@ -26,7 +26,7 @@ import { formatDateWithoutYearWithTime } from '../date.util'; @Pipe({ name: 'formatDateWithoutYearWithTime' }) export class FormatDateWithoutYearWithTimePipe implements PipeTransform { - transform(date: Date): string { - return formatDateWithoutYearWithTime(date); - } -} \ No newline at end of file + transform(date: Date): string { + return formatDateWithoutYearWithTime(date); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.spec.ts index 8d058c44a5df2b542028fc83737aa41d318ff079..aac6c51ac1c30b913f960d30c172db9ec133459b 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.spec.ts @@ -29,28 +29,27 @@ import { FormatToPrettyDatePipe } from './format-to-pretty-date.pipe'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('FormatToPrettyDatePipe', () => { - let pipe: FormatToPrettyDatePipe = new FormatToPrettyDatePipe(); + let pipe: FormatToPrettyDatePipe = new FormatToPrettyDatePipe(); - it('should create', () => { - expect(pipe).toBeTruthy(); - }); + it('should create', () => { + expect(pipe).toBeTruthy(); + }); + it('should return formatted for this year', () => { + const year: number = new Date().getFullYear(); + const date: Date = new Date(year + '-01-01'); - it('should return formatted for this year', () => { - const year: number = new Date().getFullYear(); - const date: Date = new Date(year + '-01-01'); + const result: string = pipe.transform(date); - const result: string = pipe.transform(date); + expect(result).toBe('01. Jan.'); + }); - expect(result).toBe('01. Jan.'); - }) + it('should format in "dd.MM.yyyy"', () => { + const date: Date = new Date(); + date.setFullYear(2050, 4, 10); - it('should format in "dd.MM.yyyy"', () => { - const date: Date = new Date(); - date.setFullYear(2050, 4, 10); + const result: string = pipe.transform(date); - const result: string = pipe.transform(date); - - expect(result).toBe('10.05.2050'); - }) + expect(result).toBe('10.05.2050'); + }); }); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.ts index 3dede4dfdae9ba03db03fe82a935bba1f5f7f78c..24036ddf2fdd9c03fa551b7375af093fc4bf35c2 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/format-to-pretty-date.pipe.ts @@ -26,7 +26,7 @@ import { formatToPrettyDate } from '../date.util'; @Pipe({ name: 'formatToPrettyDate' }) export class FormatToPrettyDatePipe implements PipeTransform { - transform(date: Date): string { - return formatToPrettyDate(date); - } -} \ No newline at end of file + transform(date: Date): string { + return formatToPrettyDate(date); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.spec.ts index efa62e08a81ead8d8ef5657001dd6f363845eef3..d28782d0fef619b1cb5297d23e938957686b0b02 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.spec.ts @@ -3,21 +3,20 @@ import { Resource } from '@ngxp/rest'; import { GetUrlPipe } from './get-url.pipe'; describe('GetUrlPipe', () => { + const selfLink: string = 'self'; + const url: string = faker.internet.url(); + const resource: Resource = { + _links: { + self: { + href: url, + }, + }, + }; + const pipe: GetUrlPipe = new GetUrlPipe(); - const selfLink: string = 'self'; - const url: string = faker.internet.url(); - const resource: Resource = { - _links: { - self: { - href: url - } - } - } - const pipe: GetUrlPipe = new GetUrlPipe(); + it('should return resource url', () => { + const result: string = pipe.transform(resource, selfLink); - it('should return resource url', () => { - const result: string = pipe.transform(resource, selfLink); - - expect(result).toBe(url); - }) -}) \ No newline at end of file + expect(result).toBe(url); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.ts index 50f0e6f05f8ab029e12d0bd3fb3fc327340a2c1d..0c130a8548597cfbcac2bf8d911b5bd1ee6ab175 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/get-url.pipe.ts @@ -3,7 +3,7 @@ import { Resource, getUrl } from '@ngxp/rest'; @Pipe({ name: 'getUrl' }) export class GetUrlPipe implements PipeTransform { - transform(resource: Resource, link: string) { - return getUrl(resource, link); - } + transform(resource: Resource, link: string) { + return getUrl(resource, link); + } } diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.spec.ts index 2f4bf0aebfa96a138f3f7d2fbb850ed4ee5c46d8..e7ff1676a507c878018db9eb3cc4e1de38b2d972 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.spec.ts @@ -1,34 +1,33 @@ -import { Resource } from "@ngxp/rest"; -import { createDummyResource } from "libs/tech-shared/test/resource"; -import { HasAnyLinkPipe } from "./has-any-link.pipe"; +import { Resource } from '@ngxp/rest'; +import { createDummyResource } from 'libs/tech-shared/test/resource'; +import { HasAnyLinkPipe } from './has-any-link.pipe'; describe('HasAnyLinkPipe', () => { + const oneLink: string = 'one'; + const anotherLink: string = 'another'; + const resource: Resource = createDummyResource([oneLink, anotherLink]); + const pipe: HasAnyLinkPipe = new HasAnyLinkPipe(); - const oneLink: string = 'one'; - const anotherLink: string = 'another'; - const resource: Resource = createDummyResource([oneLink, anotherLink]); - const pipe: HasAnyLinkPipe = new HasAnyLinkPipe(); + it('should return true if resource has at least on link', () => { + const result: boolean = pipe.transform(resource, oneLink, 'notExists'); - it('should return true if resource has at least on link', () => { - const result: boolean = pipe.transform(resource, oneLink, 'notExists'); + expect(result).toBe(true); + }); + it('resource return true if resoure has multiple links', () => { + const result: boolean = pipe.transform(resource, oneLink, anotherLink); - expect(result).toBe(true); - }) - it('resource return true if resoure has multiple links', () => { - const result: boolean = pipe.transform(resource, oneLink, anotherLink); + expect(result).toBe(true); + }); - expect(result).toBe(true); - }) + it('should return false if resource has no of given links', () => { + const result: boolean = pipe.transform(resource, 'notExists', 'notExistsToo'); - it('should return false if resource has no of given links', () => { - const result: boolean = pipe.transform(resource, 'notExists', 'notExistsToo'); + expect(result).toBe(false); + }); - expect(result).toBe(false); - }) + it('should return false if resource is null', () => { + const result: boolean = pipe.transform(null, 'notExists', 'notExistsToo'); - it('should return false if resource is null', () => { - const result: boolean = pipe.transform(null, 'notExists', 'notExistsToo'); - - expect(result).toBe(false); - }) -}) + expect(result).toBe(false); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts index e528dbb3d9b1200aabe03878c75cf3463c25b00d..a6627c5fd1072763525025f304082f42749be211 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/has-any-link.pipe.ts @@ -1,10 +1,12 @@ -import { Pipe, PipeTransform } from "@angular/core"; -import { hasLink, Resource } from "@ngxp/rest"; -import { isEmpty } from "lodash-es"; +import { Pipe, PipeTransform } from '@angular/core'; +import { hasLink, Resource } from '@ngxp/rest'; +import { isEmpty } from 'lodash-es'; @Pipe({ name: 'hasAnyLink' }) export class HasAnyLinkPipe implements PipeTransform { - transform(resource: Resource, ...links: string[]) { - return !isEmpty(links.map(link => hasLink(resource, link)).filter(hasLink => hasLink === true)); - } + transform(resource: Resource, ...links: string[]) { + return !isEmpty( + links.map((link) => hasLink(resource, link)).filter((hasLink) => hasLink === true), + ); + } } diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.spec.ts index a6977e701922aa693357f67610f998b93cdf45aa..74bcd1d05175fa9e373043852e5c4699baa30514 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.spec.ts @@ -26,25 +26,25 @@ import { createDummyResource } from 'libs/tech-shared/test/resource'; import { HasLinkPipe } from './has-link.pipe'; describe('HasLinkPipe', () => { - const selfLink: string = 'self'; - const dummyLink: string = 'dummy'; - const resource: Resource = createDummyResource([selfLink]); - const pipe: HasLinkPipe = new HasLinkPipe(); + const selfLink: string = 'self'; + const dummyLink: string = 'dummy'; + const resource: Resource = createDummyResource([selfLink]); + const pipe: HasLinkPipe = new HasLinkPipe(); - it('resource has link', () => { - const result: boolean = pipe.transform(resource, selfLink); + it('resource has link', () => { + const result: boolean = pipe.transform(resource, selfLink); - expect(result).toBe(true); - }) - it('resource doesnt has link', () => { - const result: boolean = pipe.transform(resource, dummyLink); + expect(result).toBe(true); + }); + it('resource doesnt has link', () => { + const result: boolean = pipe.transform(resource, dummyLink); - expect(result).toBe(false); - }) + expect(result).toBe(false); + }); - it('should return false on null resource', () => { - const result: boolean = pipe.transform(null, dummyLink); + it('should return false on null resource', () => { + const result: boolean = pipe.transform(null, dummyLink); - expect(result).toBe(false); - }) -}) + expect(result).toBe(false); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.ts index bde2bdfaccf4e99f79de11c3d4f105edb7ac80e4..70ac58beccf1b77fe59f7c50bd0b0fa2a0f6f254 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/has-link.pipe.ts @@ -26,7 +26,7 @@ import { hasLink, Resource } from '@ngxp/rest'; @Pipe({ name: 'hasLink' }) export class HasLinkPipe implements PipeTransform { - transform(resource: Resource, link: string) { - return hasLink(resource, link); - } + transform(resource: Resource, link: string) { + return hasLink(resource, link); + } } diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.spec.ts index a6968406b12228873647524223e32bffecdc903d..f6d761b827f0f0388938e95272fde774bd6303d3 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.spec.ts @@ -26,19 +26,19 @@ import { createDummyResource } from 'libs/tech-shared/test/resource'; import { NotHasLinkPipe } from './not-has-link.pipe'; describe('NotHasLinkPipe', () => { - const selfLink: string = 'self'; - const dummyLink: string = 'dummy'; - const resource: Resource = createDummyResource([selfLink]); - const pipe: NotHasLinkPipe = new NotHasLinkPipe(); + const selfLink: string = 'self'; + const dummyLink: string = 'dummy'; + const resource: Resource = createDummyResource([selfLink]); + const pipe: NotHasLinkPipe = new NotHasLinkPipe(); - it('resource has link', () => { - const result: boolean = pipe.transform(resource, selfLink); + it('resource has link', () => { + const result: boolean = pipe.transform(resource, selfLink); - expect(result).toBe(false); - }) - it('resource doesnt has link', () => { - const result: boolean = pipe.transform(resource, dummyLink); + expect(result).toBe(false); + }); + it('resource doesnt has link', () => { + const result: boolean = pipe.transform(resource, dummyLink); - expect(result).toBe(true); - }) -}) + expect(result).toBe(true); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts index a6f5a28e2c5a644f55b0fdf0b1cb095d6e8ad43e..8f8f786c562cf744e412b91f62a66827897535c7 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/not-has-link.pipe.ts @@ -26,7 +26,7 @@ import { hasLink, Resource } from '@ngxp/rest'; @Pipe({ name: 'notHasLink' }) export class NotHasLinkPipe implements PipeTransform { - transform(resource: Resource, link: string) { - return !hasLink(resource, link); - } + transform(resource: Resource, link: string) { + return !hasLink(resource, link); + } } diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.spec.ts index 74cdb8e28fdc248fd0b8aefcd07f818fce962996..309a04197539defcfa29b8320840d4f84aab7721 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.spec.ts @@ -27,32 +27,31 @@ import { createDummyListResource } from 'libs/tech-shared/test/resource'; import { ToEmbeddedResourcesPipe } from './to-embedded-resource.pipe'; describe('ToEmbeddedResourcesPipe', () => { - const pipe = new ToEmbeddedResourcesPipe(); + const pipe = new ToEmbeddedResourcesPipe(); - it('create an instance', () => { - expect(pipe).toBeTruthy(); - }); + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); - describe('transform listResource to resources by link', () => { - const listResource = createDummyListResource([DummyListLinkRel.LIST]); + describe('transform listResource to resources by link', () => { + const listResource = createDummyListResource([DummyListLinkRel.LIST]); - it('should return embedded resources', () => { + it('should return embedded resources', () => { + const result = pipe.transform(listResource, DummyListLinkRel.LIST); - const result = pipe.transform(listResource, DummyListLinkRel.LIST); + expect(result).toBe(getEmbeddedResource(listResource, DummyListLinkRel.LIST)); + }); - expect(result).toBe(getEmbeddedResource(listResource, DummyListLinkRel.LIST)); - }); + it('should return null by empty listResource', () => { + const result = pipe.transform(null, DummyListLinkRel.LIST); - it('should return null by empty listResource', () => { - const result = pipe.transform(null, DummyListLinkRel.LIST); + expect(result).toBe(null); + }); - expect(result).toBe(null); - }); + it('should return null by empty linkel', () => { + const result = pipe.transform(listResource, null); - it('should return null by empty linkel', () => { - const result = pipe.transform(listResource, null); - - expect(result).toBe(null); - }); - }) -}); \ No newline at end of file + expect(result).toBe(null); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.ts index e1bc931b94086382fbe98c460614f476a047fe21..53aec73b8461648669ba4f95b7d4aa1ecb3c5021 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-embedded-resource.pipe.ts @@ -27,8 +27,8 @@ import { isNil } from 'lodash-es'; @Pipe({ name: 'toEmbeddedResources' }) export class ToEmbeddedResourcesPipe implements PipeTransform { - transform(listResource: any, linkRel: any) { - if (isNil(listResource) || isNil(linkRel)) return null; - return getEmbeddedResource(listResource, linkRel); - } -} \ No newline at end of file + transform(listResource: any, linkRel: any) { + if (isNil(listResource) || isNil(linkRel)) return null; + return getEmbeddedResource(listResource, linkRel); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.spec.ts index c9cee41a667e956570a150ea6ecf4cf019de4d76..6f709453705f390368bf511ccef753555b246769 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.spec.ts @@ -27,42 +27,44 @@ import { decodeUrlFromEmbedding } from '../tech.util'; import { ToResourceUriPipe } from './to-resource-uri.pipe'; describe('ToResourceUriPipe', () => { - const base64ResultWithSlash: string = '/subjects?_d=1+2'; - const pipe = new ToResourceUriPipe(); + const base64ResultWithSlash: string = '/subjects?_d=1+2'; + const pipe = new ToResourceUriPipe(); - it('create an instance', () => { - expect(pipe).toBeTruthy(); - }); + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); - describe('pass resource in pipe', () => { - const dummyResource: Resource = createDummyResource(); + describe('pass resource in pipe', () => { + const dummyResource: Resource = createDummyResource(); - it('output as expected', () => { - const pipeResult: string = pipe.transform(dummyResource); + it('output as expected', () => { + const pipeResult: string = pipe.transform(dummyResource); - const result: string = decodeUrlFromEmbedding(pipeResult); + const result: string = decodeUrlFromEmbedding(pipeResult); - expect(result).toBe(getUrl(dummyResource)); - }); - it('replace "/" with "_" if necessary', () => { - const pipeResult: string = pipe.transform({ _links: { self: { href: base64ResultWithSlash } } }) + expect(result).toBe(getUrl(dummyResource)); + }); + it('replace "/" with "_" if necessary', () => { + const pipeResult: string = pipe.transform({ + _links: { self: { href: base64ResultWithSlash } }, + }); - const result: string = decodeUrlFromEmbedding(pipeResult); + const result: string = decodeUrlFromEmbedding(pipeResult); - expect(result).toBe(base64ResultWithSlash); - }); - }) + expect(result).toBe(base64ResultWithSlash); + }); + }); - describe('pass resource and linkrel in pipe', () => { - const linkRel: string = 'neuerLink'; - const dummyResourceWithLink: Resource = createDummyResource([linkRel]); + describe('pass resource and linkrel in pipe', () => { + const linkRel: string = 'neuerLink'; + const dummyResourceWithLink: Resource = createDummyResource([linkRel]); - it('output as expected', () => { - const pipeResult: string = pipe.transform(dummyResourceWithLink, linkRel); + it('output as expected', () => { + const pipeResult: string = pipe.transform(dummyResourceWithLink, linkRel); - const result: string = decodeUrlFromEmbedding(pipeResult); + const result: string = decodeUrlFromEmbedding(pipeResult); - expect(result).toBe(getUrl(dummyResourceWithLink, linkRel)); - }); - }) -}); \ No newline at end of file + expect(result).toBe(getUrl(dummyResourceWithLink, linkRel)); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.ts index 7b73f71f4483ae7727868f5115655f45f72a3eff..4c1d7971cd774eb1b53fc0b6bda21744f1a5235b 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-resource-uri.pipe.ts @@ -28,10 +28,10 @@ import { toResourceUri } from '../resource/resource.util'; @Pipe({ name: 'toResourceUri' }) export class ToResourceUriPipe implements PipeTransform { - transform(resource: Resource, linkRel?: string): string { - if (isNil(resource)) { - return null; - } - return toResourceUri(resource, linkRel); - } -} \ No newline at end of file + transform(resource: Resource, linkRel?: string): string { + if (isNil(resource)) { + return null; + } + return toResourceUri(resource, linkRel); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.spec.ts index 05edd3f12363af57ad046d42d4fd8dc1d95ee0e1..e2aae795a0c5de1e0eba531c27dcc65b750714d1 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.spec.ts @@ -24,40 +24,37 @@ import { ToTrafficLightTooltipPipe } from './to-traffic-light-tooltip.pipe'; describe('ToTrafficLightTooltipPipe', () => { - const pipe = new ToTrafficLightTooltipPipe(); + const pipe = new ToTrafficLightTooltipPipe(); - it('create an instance', () => { - expect(pipe).toBeTruthy(); - }); + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); - describe('pass date in pipe', () => { + describe('pass date in pipe', () => { + it('future should return "zukunft"', () => { + const future = new Date(); + future.setDate(future.getDate() + 2); - it('future should return "zukunft"', () => { - const future = new Date(); - future.setDate(future.getDate() + 2); + const pipeResult: string = pipe.transform(future); - const pipeResult: string = pipe.transform(future); + expect(pipeResult).toBe('Die Frist liegt in der Zukunft'); + }); - expect(pipeResult).toBe('Die Frist liegt in der Zukunft'); - }); + it('past should return "abgelaufen"', () => { + const past = new Date(); + past.setDate(past.getDate() - 2); - it('past should return "abgelaufen"', () => { - const past = new Date(); - past.setDate(past.getDate() - 2); + const pipeResult: string = pipe.transform(past); - const pipeResult: string = pipe.transform(past); + expect(pipeResult).toBe('Die Frist ist abgelaufen'); + }); - expect(pipeResult).toBe('Die Frist ist abgelaufen'); - }); - - it('today should return "endet Heute"', () => { - const today: Date = new Date(); - - const pipeResult: string = pipe.transform(today); - - expect(pipeResult).toBe('Die Frist endet Heute'); - }); - }); + it('today should return "endet Heute"', () => { + const today: Date = new Date(); + const pipeResult: string = pipe.transform(today); + expect(pipeResult).toBe('Die Frist endet Heute'); + }); + }); }); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.ts index bf16c0fc244b69318c7a74b8599b8e2513bc3f49..6113820006c8439f44329648e19c186f097c8797 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light-tooltip.pipe.ts @@ -26,11 +26,11 @@ import { isPast, isToday, isValid, parseISO } from 'date-fns'; @Pipe({ name: 'toTrafficLightTooltip' }) export class ToTrafficLightTooltipPipe implements PipeTransform { - transform(date: Date): string { - date = isValid(date) ? date : parseISO(date as unknown as string); + transform(date: Date): string { + date = isValid(date) ? date : parseISO(date as unknown as string); - if (isToday(date)) return 'Die Frist endet Heute'; - if (isPast(date)) return 'Die Frist ist abgelaufen'; - return 'Die Frist liegt in der Zukunft' - } + if (isToday(date)) return 'Die Frist endet Heute'; + if (isPast(date)) return 'Die Frist ist abgelaufen'; + return 'Die Frist liegt in der Zukunft'; + } } diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.spec.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.spec.ts index 75f8a24281a2aa9698f646cb95086bcfdcccf3b5..1ebdbaf82214b7bc86fc71b68459ae172874c2c8 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.spec.ts @@ -24,38 +24,37 @@ import { ToTrafficLightPipe } from './to-traffic-light.pipe'; describe('ToTrafficLightPipe', () => { - const pipe = new ToTrafficLightPipe(); + const pipe = new ToTrafficLightPipe(); - it('create an instance', () => { - expect(pipe).toBeTruthy(); - }); + it('create an instance', () => { + expect(pipe).toBeTruthy(); + }); - describe('pass date in pipe', () => { + describe('pass date in pipe', () => { + it('future should return empty string', () => { + const future = new Date(); + future.setDate(future.getDate() + 2); - it('future should return empty string', () => { - const future = new Date(); - future.setDate(future.getDate() + 2); + const pipeResult: string = pipe.transform(future); - const pipeResult: string = pipe.transform(future); + expect(pipeResult).toBe(''); + }); - expect(pipeResult).toBe(''); - }); + it('past should return red', () => { + const past = new Date(); + past.setDate(past.getDate() - 2); - it('past should return red', () => { - const past = new Date(); - past.setDate(past.getDate() - 2); + const pipeResult: string = pipe.transform(past); - const pipeResult: string = pipe.transform(past); + expect(pipeResult).toBe('red'); + }); - expect(pipeResult).toBe('red'); - }); + it('today should return yellow', () => { + const today: Date = new Date(); - it('today should return yellow', () => { - const today: Date = new Date(); + const pipeResult: string = pipe.transform(today); - const pipeResult: string = pipe.transform(today); - - expect(pipeResult).toBe('yellow'); - }); - }); -}); \ No newline at end of file + expect(pipeResult).toBe('yellow'); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.ts b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.ts index fba2b36ddb96eae0865dea5f44c28c9251d55bed..9e097a1e85ea8982778b16c2f0b735f923d14653 100644 --- a/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.ts +++ b/alfa-client/libs/tech-shared/src/lib/pipe/to-traffic-light.pipe.ts @@ -26,11 +26,11 @@ import { isPast, isToday, isValid, parseISO } from 'date-fns'; @Pipe({ name: 'toTrafficLight' }) export class ToTrafficLightPipe implements PipeTransform { - transform(date: Date): string { - date = isValid(date) ? date : parseISO(date as unknown as string); + transform(date: Date): string { + date = isValid(date) ? date : parseISO(date as unknown as string); - if (isToday(date)) return 'yellow'; - if (isPast(date)) return 'red'; - return '' - } + if (isToday(date)) return 'yellow'; + if (isPast(date)) return 'red'; + return ''; + } } diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts index ab44e45593572f7e7bb9e9b8d4ca29500015499a..30ad10c3a41ff49f19dc429f2ea52d0d2cc99cb4 100644 --- a/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.util.spec.ts @@ -24,127 +24,142 @@ import { EMPTY_ARRAY } from '@alfa-client/tech-shared'; import { Resource } from '@ngxp/rest'; -import { createDummyListResource, createDummyResource, toResource } from 'libs/tech-shared/test/resource'; +import { + createDummyListResource, + createDummyResource, + toResource, +} from 'libs/tech-shared/test/resource'; import { DummyListLinkRel } from '../../../test/dummy'; -import { createEmptyStateResource, createStateResource, getEmbeddedResources, isLoaded, isLoadingRequired, isValidStateResouce } from './resource.util'; +import { + createEmptyStateResource, + createStateResource, + getEmbeddedResources, + isLoaded, + isLoadingRequired, + isValidStateResouce, +} from './resource.util'; describe('resource util', () => { + describe('isLoadingRequired', () => { + it('should return true if not loaded', () => { + const isRequired: boolean = isLoadingRequired(createEmptyStateResource()); - describe('isLoadingRequired', () => { + expect(isRequired).toBe(true); + }); - it('should return true if not loaded', () => { - const isRequired: boolean = isLoadingRequired(createEmptyStateResource()); + it('should retrun false if already loading', () => { + const isRequired: boolean = isLoadingRequired(createEmptyStateResource(true)); - expect(isRequired).toBe(true); - }); + expect(isRequired).toBe(false); + }); - it('should retrun false if already loading', () => { - const isRequired: boolean = isLoadingRequired(createEmptyStateResource(true)); + it('should return false on reload if already loading', () => { + const isRequired: boolean = isLoadingRequired({ + ...createEmptyStateResource(true), + reload: true, + }); - expect(isRequired).toBe(false); - }); + expect(isRequired).toBe(false); + }); - it('should return false on reload if already loading', () => { - const isRequired: boolean = isLoadingRequired({ ...createEmptyStateResource(true), reload: true }); + it('should return true if reload requested', () => { + const isRequired: boolean = isLoadingRequired({ + ...createStateResource(toResource({})), + reload: true, + }); - expect(isRequired).toBe(false); - }) + expect(isRequired).toBe(true); + }); + }); - it('should return true if reload requested', () => { - const isRequired: boolean = isLoadingRequired({ ...createStateResource(toResource({})), reload: true }); + describe('isLoaded', () => { + it('should return false if not loaded', () => { + const loaded: boolean = isLoaded(createEmptyStateResource()); - expect(isRequired).toBe(true); - }) - }) + expect(loaded).toBe(false); + }); - describe('isLoaded', () => { + it('should retrun false if loading', () => { + const loaded: boolean = isLoaded(createEmptyStateResource(true)); - it('should return false if not loaded', () => { - const loaded: boolean = isLoaded(createEmptyStateResource()); + expect(loaded).toBe(false); + }); - expect(loaded).toBe(false); - }); + it('should return false on reload if already loading', () => { + const loaded: boolean = isLoaded({ ...createEmptyStateResource(true), reload: true }); - it('should retrun false if loading', () => { - const loaded: boolean = isLoaded(createEmptyStateResource(true)); + expect(loaded).toBe(false); + }); - expect(loaded).toBe(false); - }); + it('should return false if reload required', () => { + const loaded: boolean = isLoaded({ ...createStateResource(toResource({})), reload: true }); - it('should return false on reload if already loading', () => { - const loaded: boolean = isLoaded({ ...createEmptyStateResource(true), reload: true }); + expect(loaded).toBe(false); + }); - expect(loaded).toBe(false); - }) + it('should return true if resource is present and loaded', () => { + const loaded: boolean = isLoaded(createStateResource(toResource({}))); - it('should return false if reload required', () => { - const loaded: boolean = isLoaded({ ...createStateResource(toResource({})), reload: true }); + expect(loaded).toBe(true); + }); + }); - expect(loaded).toBe(false); - }) + describe('isValidStateResouce', () => { + it('should return false if not loaded', () => { + const isValid: boolean = isValidStateResouce(createEmptyStateResource()); - it('should return true if resource is present and loaded', () => { - const loaded: boolean = isLoaded(createStateResource(toResource({}))); + expect(isValid).toBe(false); + }); - expect(loaded).toBe(true); - }) - }) + it('should retrun false if loaded but is null', () => { + const isValid: boolean = isValidStateResouce(createStateResource(null)); - describe('isValidStateResouce', () => { + expect(isValid).toBe(false); + }); - it('should return false if not loaded', () => { - const isValid: boolean = isValidStateResouce(createEmptyStateResource()); + it('should return false on loading', () => { + const isValid: boolean = isValidStateResouce(createEmptyStateResource(true)); - expect(isValid).toBe(false); - }); + expect(isValid).toBe(false); + }); - it('should retrun false if loaded but is null', () => { - const isValid: boolean = isValidStateResouce(createStateResource(null)); + it('should retrun true if already loaded', () => { + const isValid: boolean = isValidStateResouce({ + ...createStateResource(createDummyResource()), + }); - expect(isValid).toBe(false); - }); + expect(isValid).toBe(true); + }); + }); - it('should return false on loading', () => { - const isValid: boolean = isValidStateResouce(createEmptyStateResource(true)); + describe('getEmbeddedResources', () => { + it('should return empty array if state resource null', () => { + const embedded = getEmbeddedResources(null, null); - expect(isValid).toBe(false); - }) + expect(embedded).toEqual(EMPTY_ARRAY); + }); - it('should retrun true if already loaded', () => { - const isValid: boolean = isValidStateResouce({...createStateResource(createDummyResource())}); + it('should return empty array if resource null', () => { + const embedded = getEmbeddedResources(createEmptyStateResource(), null); - expect(isValid).toBe(true); - }); - }) + expect(embedded).toEqual(EMPTY_ARRAY); + }); - describe('getEmbeddedResources', () => { - it('should return empty array if state resource null', () => { - const embedded = getEmbeddedResources(null, null); + it('should return null if embedded relation does not exist', () => { + const stateResource = createStateResource<Resource>(createDummyResource()); - expect(embedded).toEqual(EMPTY_ARRAY); - }); + const embedded = getEmbeddedResources<string[]>(stateResource, 'users'); - it('should return empty array if resource null', () => { - const embedded = getEmbeddedResources(createEmptyStateResource(), null); + expect(embedded).toBeNull(); + }); - expect(embedded).toEqual(EMPTY_ARRAY); - }); + it('should return embedded resource', () => { + const dummyListResource = createDummyListResource(); + const stateResource = createStateResource<Resource>(dummyListResource); - it('should return null if embedded relation does not exist', () => { - const stateResource = createStateResource<Resource>(createDummyResource()); + const embedded = getEmbeddedResources<Resource>(stateResource, DummyListLinkRel.LIST); - const embedded = getEmbeddedResources<string[]>(stateResource, 'users'); - - expect(embedded).toBeNull(); - }); - - it('should return embedded resource', () => { - const dummyListResource = createDummyListResource(); - const stateResource = createStateResource<Resource>(dummyListResource); - - const embedded = getEmbeddedResources<Resource>(stateResource, DummyListLinkRel.LIST); - - expect(embedded).toEqual(dummyListResource._embedded[DummyListLinkRel.LIST]); - }) - }); -}) + expect(embedded).toEqual(dummyListResource._embedded[DummyListLinkRel.LIST]); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/resource/resource.util.ts b/alfa-client/libs/tech-shared/src/lib/resource/resource.util.ts index 1ff48958fef7efaa73ddc59880da5313f2a77135..4057e0460b36dd2a2ca1dd6206d602afff7f298b 100644 --- a/alfa-client/libs/tech-shared/src/lib/resource/resource.util.ts +++ b/alfa-client/libs/tech-shared/src/lib/resource/resource.util.ts @@ -27,69 +27,78 @@ import { isNil } from 'lodash-es'; import { ApiError } from '../tech.model'; export interface ListResource extends Resource { - _embedded + _embedded; } export interface StateResource<T> { - resource: T; - reload: boolean; - loading: boolean; - loaded: boolean; - error?: ApiError; + resource: T; + reload: boolean; + loading: boolean; + loaded: boolean; + error?: ApiError; } export function createEmptyStateResource<T>(loading: boolean = false): StateResource<T> { - return createStateResource(null, loading); + return createStateResource(null, loading); } export function createStateResource<T>(resource: T, loading: boolean = false): StateResource<T> { - return { loading, loaded: !isNil(resource), reload: false, resource } + return { loading, loaded: !isNil(resource), reload: false, resource }; } export function createErrorStateResource<T>(error: ApiError): StateResource<any> { - return { ...createEmptyStateResource<T>(), error, loaded: true }; + return { ...createEmptyStateResource<T>(), error, loaded: true }; } export function createAnyErrorStateResource<T>(error: any): StateResource<any> { - return { ...createEmptyStateResource<T>(), error, loaded: true }; + return { ...createEmptyStateResource<T>(), error, loaded: true }; } -export function doIfLoadingRequired(stateResource: StateResource<any>, runable: () => void): boolean { - if (isLoadingRequired(stateResource)) { - runable(); - return true - } - return false; +export function doIfLoadingRequired( + stateResource: StateResource<any>, + runable: () => void, +): boolean { + if (isLoadingRequired(stateResource)) { + runable(); + return true; + } + return false; } export function isLoadingRequired(stateResource: StateResource<any>): boolean { - return !stateResource.loading && ((!stateResource.loaded) || stateResource.reload); + return !stateResource.loading && (!stateResource.loaded || stateResource.reload); } export function isLoaded(stateResource: StateResource<Resource>): boolean { - return !stateResource.loading && !stateResource.reload && isNotNull(stateResource.resource); + return !stateResource.loading && !stateResource.reload && isNotNull(stateResource.resource); } export function hasError(stateResource: StateResource<any>): boolean { - return !isNil(stateResource.error); + return !isNil(stateResource.error); } export function toResourceUri(resource: Resource, linkRel?: string): string { - const url: ResourceUri = isNil(linkRel) ? getUrl(resource) : getUrl(resource, linkRel); - return encodeUrlForEmbedding(url); + const url: ResourceUri = isNil(linkRel) ? getUrl(resource) : getUrl(resource, linkRel); + return encodeUrlForEmbedding(url); } -export function doOnValidStateResource(stateResource: StateResource<Resource>, actionOnValid: () => void): void { - if (isValidStateResouce(stateResource)) actionOnValid(); +export function doOnValidStateResource( + stateResource: StateResource<Resource>, + actionOnValid: () => void, +): void { + if (isValidStateResouce(stateResource)) actionOnValid(); } export function isValidStateResouce(stateResource: StateResource<Resource>): boolean { - return stateResource.loaded && isNotNull(stateResource.resource); + return stateResource.loaded && isNotNull(stateResource.resource); } -export function getEmbeddedResources<T>(stateResource: StateResource<Resource>, linkRel: string): T[] { - if (isNil(stateResource) || isNil(stateResource.resource)) { - return []; - } - return getEmbeddedResource<T[]>(stateResource.resource, linkRel); -} \ No newline at end of file +export function getEmbeddedResources<T>( + stateResource: StateResource<Resource>, + linkRel: string, +): T[] { + if (isNil(stateResource) || isNil(stateResource.resource)) { + return []; + } + return getEmbeddedResource<T[]>(stateResource.resource, linkRel); +} diff --git a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts index 1269404f7443894c2234622d03b0e53ae2e242b1..3c0f79816c61a330523bb8d804392002eb74c9ad 100644 --- a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.spec.ts @@ -23,78 +23,80 @@ */ import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; import { CommandResource } from '@alfa-client/command-shared'; -import { ApiError, createEmptyStateResource, createErrorStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + ApiError, + createEmptyStateResource, + createErrorStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { Resource } from '@ngxp/rest'; import { createApiError } from 'libs/tech-shared/test/error'; import { Observable } from 'rxjs'; import { AbstractFormService } from './formservice.abstract'; describe('AbstractFormService', () => { - let formService: AbstractFormService; + let formService: AbstractFormService; - beforeEach(() => { - formService = new DummyFormService(new UntypedFormBuilder()); - }) + beforeEach(() => { + formService = new DummyFormService(new UntypedFormBuilder()); + }); - it('should create', () => { - expect(formService).toBeTruthy(); - }); + it('should create', () => { + expect(formService).toBeTruthy(); + }); - describe('handleResponse', () => { - const apiError: ApiError = createApiError(); - const stateResource: StateResource<CommandResource> = createErrorStateResource(apiError); + describe('handleResponse', () => { + const apiError: ApiError = createApiError(); + const stateResource: StateResource<CommandResource> = createErrorStateResource(apiError); - beforeEach(() => { - formService.setError = jest.fn(); - }) + beforeEach(() => { + formService.setError = jest.fn(); + }); - it('should setError on validation error', () => { - formService.handleResponse({ ...stateResource, loading: false }); + it('should setError on validation error', () => { + formService.handleResponse({ ...stateResource, loading: false }); - expect(formService.setError).toHaveBeenCalledWith(apiError); - }) + expect(formService.setError).toHaveBeenCalledWith(apiError); + }); - it('should return stateresource while loading', () => { - const commandStateResource: StateResource<CommandResource> = createEmptyStateResource(true); + it('should return stateresource while loading', () => { + const commandStateResource: StateResource<CommandResource> = createEmptyStateResource(true); - const result: StateResource<Resource> = formService.handleResponse(commandStateResource); + const result: StateResource<Resource> = formService.handleResponse(commandStateResource); - expect(result).toBe(commandStateResource); - }) - }) + expect(result).toBe(commandStateResource); + }); + }); - describe('patch', () => { + describe('patch', () => { + it('should set form value', () => { + const formValue = { [DummyFormService.FIELD]: 'huhu' }; - it('should set form value', () => { - const formValue = { [DummyFormService.FIELD]: 'huhu' }; - - formService.patch(formValue); - - expect(formService.form.value).toEqual(formValue); - }) - }) -}) + formService.patch(formValue); + expect(formService.form.value).toEqual(formValue); + }); + }); +}); export class DummyFormService extends AbstractFormService { - - static FIELD = 'field'; - - constructor(formBuilder: UntypedFormBuilder) { - super(formBuilder); - } - - initForm(): UntypedFormGroup { - return this.formBuilder.group({ - [DummyFormService.FIELD]: new UntypedFormControl(null) - }); - } - - doSubmit(): Observable<StateResource<any>> { - throw new Error('Method not implemented.'); - } - - getPathPrefix(): string { - throw new Error('Method not implemented.'); - } -} \ No newline at end of file + static FIELD = 'field'; + + constructor(formBuilder: UntypedFormBuilder) { + super(formBuilder); + } + + initForm(): UntypedFormGroup { + return this.formBuilder.group({ + [DummyFormService.FIELD]: new UntypedFormControl(null), + }); + } + + doSubmit(): Observable<StateResource<any>> { + throw new Error('Method not implemented.'); + } + + getPathPrefix(): string { + throw new Error('Method not implemented.'); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts index db7f7ab51435da90d9746a9c2d76829c4c74f166..628817e5900b524ff157d0cc8da8056ecb08d2f1 100644 --- a/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts +++ b/alfa-client/libs/tech-shared/src/lib/service/formservice.abstract.ts @@ -29,58 +29,58 @@ import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; export abstract class AbstractFormService { - form: UntypedFormGroup; - pathPrefix: string; - source: any; + form: UntypedFormGroup; + pathPrefix: string; + source: any; - constructor(public formBuilder: UntypedFormBuilder) { - this.form = this.initForm(); - } + constructor(public formBuilder: UntypedFormBuilder) { + this.form = this.initForm(); + } - protected abstract initForm(): UntypedFormGroup; + protected abstract initForm(): UntypedFormGroup; - public submit(): Observable<StateResource<Resource>> { - return this.doSubmit().pipe(map(result => this.handleResponse(result))); - } + public submit(): Observable<StateResource<Resource>> { + return this.doSubmit().pipe(map((result) => this.handleResponse(result))); + } - protected abstract doSubmit(): Observable<StateResource<Resource>>; + protected abstract doSubmit(): Observable<StateResource<Resource>>; - handleResponse(result: StateResource<Resource>): StateResource<Resource> { - if (result.loading) return result; - if (hasError(result)) { - this.setError(result.error); - } - return result; - } + handleResponse(result: StateResource<Resource>): StateResource<Resource> { + if (result.loading) return result; + if (hasError(result)) { + this.setError(result.error); + } + return result; + } - patch(valueToPatch: any): void { - this.form.reset(); - this.form.patchValue(valueToPatch); + patch(valueToPatch: any): void { + this.form.reset(); + this.form.patchValue(valueToPatch); - this.source = valueToPatch; + this.source = valueToPatch; - this.doAfterPatch(valueToPatch); - } + this.doAfterPatch(valueToPatch); + } - doAfterPatch(source: any): void { - //No Implementation here for abstract class - } + doAfterPatch(source: any): void { + //No Implementation here for abstract class + } - setError(apiError: ApiError): void { - apiError.issues.forEach(issue => setValidationError(this.form, issue, this.getPathPrefix())) - } + setError(apiError: ApiError): void { + apiError.issues.forEach((issue) => setValidationError(this.form, issue, this.getPathPrefix())); + } - protected abstract getPathPrefix(): string; + protected abstract getPathPrefix(): string; - getFormValue(): any { - return this.form.value; - } + getFormValue(): any { + return this.form.value; + } - protected getSourceValue(): any { - return this.source; - } + protected getSourceValue(): any { + return this.source; + } - public isPatch(): boolean { - return !isNil(this.source); - } -} \ No newline at end of file + public isPatch(): boolean { + return !isNil(this.source); + } +} diff --git a/alfa-client/libs/tech-shared/src/lib/tech-shared.module.spec.ts b/alfa-client/libs/tech-shared/src/lib/tech-shared.module.spec.ts index f574fe756af57420a077be36134929934a00ff6b..3ec02f36beb050d7d1c085898632a41a715e3289 100644 --- a/alfa-client/libs/tech-shared/src/lib/tech-shared.module.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/tech-shared.module.spec.ts @@ -25,13 +25,13 @@ import { TechSharedModule } from './tech-shared.module'; import { TestBed } from '@angular/core/testing'; describe('TechSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [TechSharedModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [TechSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(TechSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(TechSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts b/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts index 7b256305fb9b71bea2ff22273bee218ebe3c9fb2..293d66ea74f158d0995fb1e74ce6212249be069e 100644 --- a/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts +++ b/alfa-client/libs/tech-shared/src/lib/tech-shared.module.ts @@ -43,61 +43,61 @@ import { ToTrafficLightTooltipPipe } from './pipe/to-traffic-light-tooltip.pipe' import { ToTrafficLightPipe } from './pipe/to-traffic-light.pipe'; @NgModule({ - imports: [CommonModule], - declarations: [ - FormatToPrettyDatePipe, - EnumToLabelPipe, - FormatDateWithTimePipe, - FormatDateWithoutYearWithTimePipe, - HasLinkPipe, - HasAnyLinkPipe, - NotHasLinkPipe, - ToResourceUriPipe, - ToTrafficLightPipe, - ToTrafficLightTooltipPipe, - ToEmbeddedResourcesPipe, - ConvertForDataTestPipe, - FileSizePipe, - GetUrlPipe - ], - exports: [ - FormatToPrettyDatePipe, - EnumToLabelPipe, - FormatDateWithTimePipe, - FormatDateWithoutYearWithTimePipe, - HasLinkPipe, - HasAnyLinkPipe, - NotHasLinkPipe, - ToResourceUriPipe, - ToTrafficLightPipe, - ToTrafficLightTooltipPipe, - ToEmbeddedResourcesPipe, - ConvertForDataTestPipe, - FileSizePipe, - GetUrlPipe - ], - providers: [ - { - provide: HTTP_INTERCEPTORS, - useClass: XhrInterceptor, - multi: true, - }, - { - provide: HTTP_INTERCEPTORS, - useClass: HttpXsrfInterceptor, - multi: true, - }, - { - provide: HTTP_INTERCEPTORS, - useClass: HttpBinaryFileInterceptor, - multi: true, - }, - ], + imports: [CommonModule], + declarations: [ + FormatToPrettyDatePipe, + EnumToLabelPipe, + FormatDateWithTimePipe, + FormatDateWithoutYearWithTimePipe, + HasLinkPipe, + HasAnyLinkPipe, + NotHasLinkPipe, + ToResourceUriPipe, + ToTrafficLightPipe, + ToTrafficLightTooltipPipe, + ToEmbeddedResourcesPipe, + ConvertForDataTestPipe, + FileSizePipe, + GetUrlPipe, + ], + exports: [ + FormatToPrettyDatePipe, + EnumToLabelPipe, + FormatDateWithTimePipe, + FormatDateWithoutYearWithTimePipe, + HasLinkPipe, + HasAnyLinkPipe, + NotHasLinkPipe, + ToResourceUriPipe, + ToTrafficLightPipe, + ToTrafficLightTooltipPipe, + ToEmbeddedResourcesPipe, + ConvertForDataTestPipe, + FileSizePipe, + GetUrlPipe, + ], + providers: [ + { + provide: HTTP_INTERCEPTORS, + useClass: XhrInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: HttpXsrfInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: HttpBinaryFileInterceptor, + multi: true, + }, + ], }) export class TechSharedModule { - public static injector: Injector; + public static injector: Injector; - constructor(private injector: Injector) { - TechSharedModule.injector = this.injector; - } + constructor(private injector: Injector) { + TechSharedModule.injector = this.injector; + } } diff --git a/alfa-client/libs/tech-shared/src/lib/tech.model.ts b/alfa-client/libs/tech-shared/src/lib/tech.model.ts index 2dbacb75afc724a136cc6229225afb5222a219b4..01fd103a38e586a236163d0778b236f441628706 100644 --- a/alfa-client/libs/tech-shared/src/lib/tech.model.ts +++ b/alfa-client/libs/tech-shared/src/lib/tech.model.ts @@ -24,49 +24,49 @@ import { HttpHeaders } from '@angular/common/http'; * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export interface ApiError { - issues: Issue[] + issues: Issue[]; } export interface Issue { - field: string, - messageCode: string,//TODO statt string -> ValidationMessageCode nutzen - message: string, - parameters: IssueParam[], - exceptionId?: string + field: string; + messageCode: string; //TODO statt string -> ValidationMessageCode nutzen + message: string; + parameters: IssueParam[]; + exceptionId?: string; } export interface IssueParam { - name: string, - value: string; + name: string; + value: string; } export enum HttpMethod { - POST = 'POST', - PUT = 'PUT', - PATCH = 'PATCH', - DELETE = 'DELETE', - GET = 'GET' + POST = 'POST', + PUT = 'PUT', + PATCH = 'PATCH', + DELETE = 'DELETE', + GET = 'GET', } export enum HttpHeader { - ACCEPT = 'Accept', - CONTENT_DISPOSITION = 'content-disposition' + ACCEPT = 'Accept', + CONTENT_DISPOSITION = 'content-disposition', } export interface BlobWithFileName { - blob: Blob, - fileName: string + blob: Blob; + fileName: string; } export enum ContentType { - APPLICATION_JSON = 'application/json', - APPLICATION_PDF = 'application/pdf', - IMAGES_ALL = 'images/*', - APPLICATION_ALL = 'application/*', - APPLICATION_OCTET_STREAM = 'application/octet-stream' + APPLICATION_JSON = 'application/json', + APPLICATION_PDF = 'application/pdf', + IMAGES_ALL = 'images/*', + APPLICATION_ALL = 'application/*', + APPLICATION_OCTET_STREAM = 'application/octet-stream', } export interface GetRequestOptions { - headers: HttpHeaders | { [header: string]: string | string[] }, - responseType: 'json', + headers: HttpHeaders | { [header: string]: string | string[] }; + responseType: 'json'; } diff --git a/alfa-client/libs/tech-shared/src/lib/tech.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/tech.util.spec.ts index f775e7687b5587a488d9672ee2c895c455257af7..d8cd4e7808dc1b383bb2c8c76ab96df2e10794ae 100644 --- a/alfa-client/libs/tech-shared/src/lib/tech.util.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/tech.util.spec.ts @@ -22,307 +22,312 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { faker } from '@faker-js/faker'; -import { allEmpty, convertForDataTest, decodeUrlFromEmbedding, EMPTY_STRING, encodeUrlForEmbedding, getFirstLetter, getStringValue, hasMinLength, isNotEmpty, isNotNil, isNotNull, replaceAllWhitespaces, replacePlaceholder, replacePlaceholders, simpleTransliteration } from './tech.util'; +import { + allEmpty, + convertForDataTest, + decodeUrlFromEmbedding, + EMPTY_STRING, + encodeUrlForEmbedding, + getFirstLetter, + getStringValue, + hasMinLength, + isNotEmpty, + isNotNil, + isNotNull, + replaceAllWhitespaces, + replacePlaceholder, + replacePlaceholders, + simpleTransliteration, +} from './tech.util'; describe('TechUtil', () => { + describe('replaceAllWhitespaces', () => { + it('should replace whitespaces in value', () => { + const value: string = 'value to replace whitespaces'; - describe('replaceAllWhitespaces', () => { + const result: string = replaceAllWhitespaces(value, '_'); - it('should replace whitespaces in value', () => { - const value: string = 'value to replace whitespaces'; + expect(result).toBe('value_to_replace_whitespaces'); + }); + }); - const result: string = replaceAllWhitespaces(value, '_'); + describe('simpleTransliteration', () => { + it('should replace whitespaces in value', () => { + const value: string = 'áàâäãéèëêíìïîóòöôõúùüûñçăşţ-_'; - expect(result).toBe('value_to_replace_whitespaces'); - }) - }) + const result: string = simpleTransliteration(value); - describe('simpleTransliteration', () => { + expect(result).toBe('aaaaaeeeeiiiiooooouuuuncast-_'); + }); + }); - it('should replace whitespaces in value', () => { - const value: string = 'áàâäãéèëêíìïîóòöôõúùüûñçăşţ-_'; + describe('replace placeholder', () => { + it('should replace with value', () => { + const text = 'replace {this}'; + const placeholder = 'this'; + const value = 'with this'; - const result: string = simpleTransliteration(value); + const replaced = replacePlaceholder(text, placeholder, value); - expect(result).toBe('aaaaaeeeeiiiiooooouuuuncast-_'); - }) - }) + expect(replaced).toBe('replace with this'); + }); - describe('replace placeholder', () => { + it('should replace all', () => { + const text = 'replace {here} and {here}'; + const placeholder = 'here'; + const value = 'there'; - it('should replace with value', () => { - const text = 'replace {this}'; - const placeholder = 'this'; - const value = 'with this'; + const replaced = replacePlaceholder(text, placeholder, value); - const replaced = replacePlaceholder(text, placeholder, value); + expect(replaced).toBe('replace there and there'); + }); - expect(replaced).toBe('replace with this'); - }); + it('should ignore other placeholder', () => { + const text = 'replace {here}'; + const placeholder = 'there'; + const value = 'this'; - it('should replace all', () => { - const text = 'replace {here} and {here}'; - const placeholder = 'here'; - const value = 'there'; + const replaced = replacePlaceholder(text, placeholder, value); - const replaced = replacePlaceholder(text, placeholder, value); + expect(replaced).toBe('replace {here}'); + }); + }); - expect(replaced).toBe('replace there and there'); - }); + describe('replace placeholders', () => { + it('should replace all placeholder', () => { + const text = 'replace {here} and {there}'; + const placeholders = { here: 'this', there: 'that' }; - it('should ignore other placeholder', () => { - const text = 'replace {here}'; - const placeholder = 'there'; - const value = 'this'; + const replaced = replacePlaceholders(text, placeholders); - const replaced = replacePlaceholder(text, placeholder, value); + expect(replaced).toBe('replace this and that'); + }); + }); - expect(replaced).toBe('replace {here}'); - }) - }); + describe('get first letter', () => { + it('should return on valid string value', () => { + const value: string = `e ${faker.random.word()}`; - describe('replace placeholders', () => { + expect(getFirstLetter(value)).toBe('e'); + }); - it('should replace all placeholder', () => { - const text = 'replace {here} and {there}' - const placeholders = { here: 'this', there: 'that' }; + it('should return undefined on undefined value', () => { + expect(getFirstLetter(undefined)).toBeNull(); + }); - const replaced = replacePlaceholders(text, placeholders); + it('should return undefined on null value', () => { + expect(getFirstLetter(null)).toBeNull(); + }); + }); - expect(replaced).toBe('replace this and that'); - }) - }) + describe('isNotEmpty', () => { + it('should return true on filled string', () => { + const result: boolean = isNotEmpty(faker.random.word()); - describe('get first letter', () => { + expect(result).toBeTruthy(); + }); - it('should return on valid string value', () => { - const value: string = `e ${faker.random.word()}`; + it('should return true if array contains elements', () => { + const result: boolean = isNotEmpty(faker.helpers.arrayElement()); - expect(getFirstLetter(value)).toBe('e'); - }) + expect(result).toBeTruthy(); + }); - it('should return undefined on undefined value', () => { - expect(getFirstLetter(undefined)).toBeNull(); - }) + it('should return true if object contains properties', () => { + const result: boolean = isNotEmpty(faker.helpers.objectValue({ key: 'value' })); - it('should return undefined on null value', () => { - expect(getFirstLetter(null)).toBeNull(); - }) - }) + expect(result).toBeTruthy(); + }); - describe('isNotEmpty', () => { - it('should return true on filled string', () => { - const result: boolean = isNotEmpty(faker.random.word()); + it('should return false if string length is zero', () => { + const result: boolean = isNotEmpty(''); - expect(result).toBeTruthy(); - }); + expect(result).toBeFalsy(); + }); - it('should return true if array contains elements', () => { - const result: boolean = isNotEmpty(faker.helpers.arrayElement()); + it('should return false if array length is zero', () => { + const result: boolean = isNotEmpty([]); - expect(result).toBeTruthy(); - }); + expect(result).toBeFalsy(); + }); - it('should return true if object contains properties', () => { - const result: boolean = isNotEmpty(faker.helpers.objectValue({ key: 'value' })); + it('should return false if object length is zero', () => { + const result: boolean = isNotEmpty({}); - expect(result).toBeTruthy(); - }); + expect(result).toBeFalsy(); + }); + }); - it('should return false if string length is zero', () => { - const result: boolean = isNotEmpty(''); + describe('isNotNil', () => { + it('should return true if value is filled string', () => { + const result: boolean = isNotNil(faker.random.word()); - expect(result).toBeFalsy(); - }); + expect(result).toBeTruthy(); + }); - it('should return false if array length is zero', () => { - const result: boolean = isNotEmpty([]); + it('should return false if value is null', () => { + const result: boolean = isNotNil(null); - expect(result).toBeFalsy(); - }); + expect(result).toBeFalsy(); + }); - it('should return false if object length is zero', () => { - const result: boolean = isNotEmpty({}); + it('should return false if value is undefined', () => { + const result: boolean = isNotNil(undefined); - expect(result).toBeFalsy(); - }); - }); + expect(result).toBeFalsy(); + }); + }); - describe('isNotNil', () => { - it('should return true if value is filled string', () => { - const result: boolean = isNotNil(faker.random.word()); + describe('isNotNulll', () => { + it('should return true if value is filled string', () => { + const result: boolean = isNotNull(faker.random.word()); - expect(result).toBeTruthy(); - }); + expect(result).toBeTruthy(); + }); - it('should return false if value is null', () => { - const result: boolean = isNotNil(null); + it('should return false if value is null', () => { + const result: boolean = isNotNull(null); - expect(result).toBeFalsy(); - }); + expect(result).toBeFalsy(); + }); - it('should return false if value is undefined', () => { - const result: boolean = isNotNil(undefined); + it('should return true if value is undefined', () => { + const result: boolean = isNotNull(undefined); - expect(result).toBeFalsy(); - }); - }); + expect(result).toBeTruthy(); + }); + }); - describe('isNotNulll', () => { + describe('hasMinLength with length of 3', () => { + const minValue: number = 3; + const SEARCH_STRING = 'i search for...'; - it('should return true if value is filled string', () => { - const result: boolean = isNotNull(faker.random.word()); + it('should return false on null value', () => { + const hasLength = hasMinLength(null, minValue); - expect(result).toBeTruthy(); - }); + expect(hasLength).toBeFalsy(); + }); - it('should return false if value is null', () => { - const result: boolean = isNotNull(null); + it('should return false on undefined value', () => { + const hasLength = hasMinLength(undefined, minValue); - expect(result).toBeFalsy(); - }); + expect(hasLength).toBeFalsy(); + }); - it('should return true if value is undefined', () => { - const result: boolean = isNotNull(undefined); + it('should return false on empty string => ""', () => { + const hasLength = hasMinLength(EMPTY_STRING, minValue); - expect(result).toBeTruthy(); - }); - }); + expect(hasLength).toBeFalsy(); + }); - describe('hasMinLength with length of 3', () => { + it('should return false on length less than 2', () => { + const hasLength = hasMinLength(EMPTY_STRING, minValue); - const minValue: number = 3; - const SEARCH_STRING = 'i search for...'; + expect(hasLength).toBeFalsy(); + }); - it('should return false on null value', () => { - const hasLength = hasMinLength(null, minValue); + it('should return true on length equals than 3 ', () => { + const hasLength = hasMinLength('huh', minValue); - expect(hasLength).toBeFalsy(); - }) + expect(hasLength).toBeTruthy(); + }); - it('should return false on undefined value', () => { - const hasLength = hasMinLength(undefined, minValue); + it('should return true on length greater than 3 ', () => { + const hasLength = hasMinLength(SEARCH_STRING, minValue); - expect(hasLength).toBeFalsy(); - }) + expect(hasLength).toBeTruthy(); + }); + }); - it('should return false on empty string => ""', () => { - const hasLength = hasMinLength(EMPTY_STRING, minValue); + describe('convertForDataTest', () => { + it('should replace whitespaces and transliterate Umlauts in value', () => { + const value: string = 'value to replace whitespaces and Ümläuts with Öös'; - expect(hasLength).toBeFalsy(); - }) + const result: string = convertForDataTest(value); - it('should return false on length less than 2', () => { - const hasLength = hasMinLength(EMPTY_STRING, minValue); + expect(result).toBe('value_to_replace_whitespaces_and_Umlauts_with_Oos'); + }); + }); - expect(hasLength).toBeFalsy(); - }) + describe('get string value', () => { + it('should return empty string on null', () => { + const value: string = null; - it('should return true on length equals than 3 ', () => { - const hasLength = hasMinLength('huh', minValue); + const result: string = getStringValue(value); - expect(hasLength).toBeTruthy(); - }) + expect(result).toBe(EMPTY_STRING); + }); - it('should return true on length greater than 3 ', () => { - const hasLength = hasMinLength(SEARCH_STRING, minValue); + it('should return empty string on undefined', () => { + const value: string = undefined; - expect(hasLength).toBeTruthy(); - }) - }) + const result: string = getStringValue(value); - describe('convertForDataTest', () => { + expect(result).toBe(EMPTY_STRING); + }); - it('should replace whitespaces and transliterate Umlauts in value', () => { - const value: string = 'value to replace whitespaces and Ümläuts with Öös'; + it('should return given value', () => { + const value: string = 'value of this...'; - const result: string = convertForDataTest(value); + const result: string = getStringValue(value); - expect(result).toBe('value_to_replace_whitespaces_and_Umlauts_with_Oos'); - }) - }) + expect(result).toBe(value); + }); + }); - describe('get string value', () => { + describe('encodeUrlForEmbedding', () => { + it('should return encoded URL to be embedded in a URI', () => { + const url: string = faker.internet.url(); + const forbiddenChars: RegExp = /[^-a-zA-Z0-9_=]/; - it('should return empty string on null', () => { - const value: string = null; + const encoded: string = encodeUrlForEmbedding(url); + const searchForbiddenChars: number = encoded.search(forbiddenChars); - const result: string = getStringValue(value); + expect(searchForbiddenChars).toBe(-1); + expect(url).toBe(decodeUrlFromEmbedding(encoded)); + }); + }); - expect(result).toBe(EMPTY_STRING); - }) + describe('decodeUrlFromEmbedding', () => { + it('should return URL from encoded string', () => { + const url: string = faker.internet.url(); + const encodedUrl: string = encodeUrlForEmbedding(url); - it('should return empty string on undefined', () => { - const value: string = undefined; + const decoded: string = decodeUrlFromEmbedding(encodedUrl); - const result: string = getStringValue(value); + expect(decoded).toBe(url); + }); + }); - expect(result).toBe(EMPTY_STRING); - }) + describe('allEmpty', () => { + it('should return true on all empty', () => { + const empty: boolean = allEmpty(EMPTY_STRING, EMPTY_STRING, EMPTY_STRING); - it('should return given value', () => { - const value: string = 'value of this...'; + expect(empty).toBeTruthy(); + }); - const result: string = getStringValue(value); + it('should return false on one NOT empty', () => { + const empty: boolean = allEmpty(EMPTY_STRING, EMPTY_STRING, 'quatsch'); - expect(result).toBe(value); - }) - }) + expect(empty).toBeFalsy(); + }); - describe('encodeUrlForEmbedding', () => { - it('should return encoded URL to be embedded in a URI', () => { - const url: string = faker.internet.url(); - const forbiddenChars: RegExp = /[^-a-zA-Z0-9_=]/; + it('should return false on all NOT empty', () => { + const empty: boolean = allEmpty('1', '2', '3'); - const encoded: string = encodeUrlForEmbedding(url); - const searchForbiddenChars: number = encoded.search(forbiddenChars); + expect(empty).toBeFalsy(); + }); - expect(searchForbiddenChars).toBe(-1); - expect(url).toBe(decodeUrlFromEmbedding(encoded)); - }) - }) + it('should return true on null', () => { + const empty: boolean = allEmpty(null); - describe('decodeUrlFromEmbedding', () => { - it('should return URL from encoded string', () => { - const url: string = faker.internet.url(); - const encodedUrl: string = encodeUrlForEmbedding(url); + expect(empty).toBeTruthy(); + }); - const decoded: string = decodeUrlFromEmbedding(encodedUrl); + it('should return true on undefined', () => { + const empty: boolean = allEmpty(undefined); - expect(decoded).toBe(url); - }) - }) - - describe('allEmpty', () => { - - it('should return true on all empty', () => { - const empty: boolean = allEmpty(EMPTY_STRING, EMPTY_STRING, EMPTY_STRING); - - expect(empty).toBeTruthy(); - }) - - it('should return false on one NOT empty', () => { - const empty: boolean = allEmpty(EMPTY_STRING, EMPTY_STRING, 'quatsch'); - - expect(empty).toBeFalsy(); - }) - - it('should return false on all NOT empty', () => { - const empty: boolean = allEmpty('1', '2', '3'); - - expect(empty).toBeFalsy(); - }) - - it('should return true on null', () => { - const empty: boolean = allEmpty(null); - - expect(empty).toBeTruthy(); - }) - - it('should return true on undefined', () => { - const empty: boolean = allEmpty(undefined); - - expect(empty).toBeTruthy(); - }) - }) -}) \ No newline at end of file + expect(empty).toBeTruthy(); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/tech.util.ts b/alfa-client/libs/tech-shared/src/lib/tech.util.ts index 8d777ed7f98173720200933a6189caea53d99a06..1b295bc50d9e83fda642d6a9b13f4e48ada0cf0a 100644 --- a/alfa-client/libs/tech-shared/src/lib/tech.util.ts +++ b/alfa-client/libs/tech-shared/src/lib/tech.util.ts @@ -30,99 +30,103 @@ export const EMPTY_STRING: string = ''; export const EMPTY_ARRAY = []; export function getBaseUrl(): string { - const { protocol, host, } = window.location; - const basePath = `${protocol}//${host}`; - return basePath.endsWith('/') ? `${basePath}` : `${basePath}/`; + const { protocol, host } = window.location; + const basePath = `${protocol}//${host}`; + return basePath.endsWith('/') ? `${basePath}` : `${basePath}/`; } export function isEmptyObject(obj: any): boolean { - return Object.keys(obj).length === 0; + return Object.keys(obj).length === 0; } export function replacePlaceholders(text: string, placeholders: { [key: string]: string }): string { - let replaced = text; - Object.keys(placeholders).forEach(key => replaced = replacePlaceholder(replaced, key, placeholders[key])); - return replaced; + let replaced = text; + Object.keys(placeholders).forEach( + (key) => (replaced = replacePlaceholder(replaced, key, placeholders[key])), + ); + return replaced; } export function replacePlaceholder(text: string, placeholder: string, value: string): string { - const regex = new RegExp('{' + placeholder + '}', 'g'); - return text.replace(regex, value); + const regex = new RegExp('{' + placeholder + '}', 'g'); + return text.replace(regex, value); } export function hasExceptionId(apiError: ApiError): boolean { - return isNotNil(apiError) && isNotNil(apiError.issues) && isNotNil(apiError.issues[0].exceptionId); + return ( + isNotNil(apiError) && isNotNil(apiError.issues) && isNotNil(apiError.issues[0].exceptionId) + ); } export function sleep(delayInMs: number) { - const start = new Date().getTime(); - while (new Date().getTime() < start + delayInMs); + const start = new Date().getTime(); + while (new Date().getTime() < start + delayInMs); } export function getFirstLetter(value: string): string { - return isNil(value) ? null : value.substring(0, 1); + return isNil(value) ? null : value.substring(0, 1); } export function isNotEmpty(value: any): boolean { - return !isEmpty(value); + return !isEmpty(value); } export function isNotNil(value: any): boolean { - return !isNil(value); + return !isNil(value); } export function isNotNull(value: any): boolean { - return !isNull(value); + return !isNull(value); } export function isNotUndefined(value: any): boolean { - return !isUndefined(value); + return !isUndefined(value); } export function hasMinLength(value: any, length: number): boolean { - return isNotNil(value) && value.length >= length; + return isNotNil(value) && value.length >= length; } export function hasContent(value?: string): boolean { - return hasMinLength(value?.trim(), 1); + return hasMinLength(value?.trim(), 1); } export function convertForDataTest(value: string): string { - value = replaceAllWhitespaces(value, '_'); - return simpleTransliteration(value); + value = replaceAllWhitespaces(value, '_'); + return simpleTransliteration(value); } export function replaceAllWhitespaces(value: string, replaceWith: string) { - return value.replace(/ /g, replaceWith); + return value.replace(/ /g, replaceWith); } export function simpleTransliteration(value: string) { - return value.normalize('NFKD').replace(/[^-A-Za-z0-9_]/g, ''); + return value.normalize('NFKD').replace(/[^-A-Za-z0-9_]/g, ''); } export function getStringValue(value: null | undefined | string): string { - if (isNil(value)) { - return EMPTY_STRING; - } - return value; + if (isNil(value)) { + return EMPTY_STRING; + } + return value; } export function encodeUrlForEmbedding(url: string): string { - return Base64.encodeURI(url); + return Base64.encodeURI(url); } export function decodeUrlFromEmbedding(url: string): string { - return Base64.decode(url); + return Base64.decode(url); } export function sanitizeFileName(value: any): string { - return sanitize(value); + return sanitize(value); } export function allEmpty(value: string, ...values: string[]): boolean { - return [...values, value].filter(value => isNotEmpty(value)).length === 0; + return [...values, value].filter((value) => isNotEmpty(value)).length === 0; } export function isClipboardReadSupported(): boolean { - return isNotNil(navigator.clipboard.readText); -} \ No newline at end of file + return isNotNil(navigator.clipboard.readText); +} diff --git a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.messages.ts b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.messages.ts index 306b41f11a1ab59e1e074b3cd3371cc662f2d7e2..50986629811aef92ed9344ead719d4fee8d05bc7 100644 --- a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.messages.ts +++ b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.messages.ts @@ -22,18 +22,19 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum ValidationMessageCode { - VALIDATION_FIELD_FILE_SIZE_EXCEEDED = 'validation_field_file_size_exceeded', - VALIDATION_FIELD_EMPTY = 'validation_field_empty', + VALIDATION_FIELD_FILE_SIZE_EXCEEDED = 'validation_field_file_size_exceeded', + VALIDATION_FIELD_EMPTY = 'validation_field_empty', } export const VALIDATION_MESSAGES: { [code: string]: string } = { - [ValidationMessageCode.VALIDATION_FIELD_EMPTY]: 'Bitte {field} ausfüllen', - validation_field_max_size: '{field} darf höchstens {max} Zeichen enthalten', - validation_field_min_size: '{field} muss aus mindestens {min} Zeichen bestehen', - validation_field_size: '{field} muss mindestens {min} und darf höchstens {max} Zeichen enthalten', - validation_field_date_past: 'Das Datum für {field} muss in der Zukunft liegen', - validation_field_invalid: 'Bitte {field} korrekt ausfüllen', - [ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED]: 'Anhänge größer {max}{unit} können nicht hinzugefügt werden.', + [ValidationMessageCode.VALIDATION_FIELD_EMPTY]: 'Bitte {field} ausfüllen', + validation_field_max_size: '{field} darf höchstens {max} Zeichen enthalten', + validation_field_min_size: '{field} muss aus mindestens {min} Zeichen bestehen', + validation_field_size: '{field} muss mindestens {min} und darf höchstens {max} Zeichen enthalten', + validation_field_date_past: 'Das Datum für {field} muss in der Zukunft liegen', + validation_field_invalid: 'Bitte {field} korrekt ausfüllen', + [ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED]: + 'Anhänge größer {max}{unit} können nicht hinzugefügt werden.', - fe_only_validation_bearbeiter_not_exist: 'Der Bearbeiter existiert nicht' -} + fe_only_validation_bearbeiter_not_exist: 'Der Bearbeiter existiert nicht', +}; diff --git a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts index c71b980535eab7b7fd2d8165bb55cf0f4040ba53..3149fb9d66fc4c4818958a4367a87c56844fc867 100644 --- a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts +++ b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.spec.ts @@ -27,109 +27,113 @@ import { Issue } from '../tech.model'; import { getControlForIssue, getMessageForIssue, setValidationError } from './tech.validation.util'; describe('ValidationUtils', () => { + describe('setValidationError', () => { + const baseField1Control = new UntypedFormControl(); + const baseField2Control = new UntypedFormControl(); + const subGroupFieldControl = new UntypedFormControl(); - describe('setValidationError', () => { + const form = new UntypedFormGroup({ + baseField1: baseField1Control, + baseField2: baseField2Control, + subGroup: new UntypedFormGroup({ + subGroupField1: subGroupFieldControl, + }), + }); - const baseField1Control = new UntypedFormControl(); - const baseField2Control = new UntypedFormControl(); - const subGroupFieldControl = new UntypedFormControl(); + describe('get control for issue', () => { + it('should return base field control', () => { + const issue: Issue = { ...createIssue(), field: 'baseField1' }; - const form = new UntypedFormGroup({ - baseField1: baseField1Control, - baseField2: baseField2Control, - subGroup: new UntypedFormGroup({ - subGroupField1: subGroupFieldControl - }) - }); + const control = getControlForIssue(form, issue); - describe('get control for issue', () => { + expect(control).toBe(baseField1Control); + }); - it('should return base field control', () => { - const issue: Issue = { ...createIssue(), field: 'baseField1' }; + it('should reeturn sub group field', () => { + const issue: Issue = { ...createIssue(), field: 'subGroup.subGroupField1' }; - const control = getControlForIssue(form, issue); + const control = getControlForIssue(form, issue); - expect(control).toBe(baseField1Control); - }); + expect(control).toBe(subGroupFieldControl); + }); - it('should reeturn sub group field', () => { - const issue: Issue = { ...createIssue(), field: 'subGroup.subGroupField1' }; + it('should ignore path prefix', () => { + const issue: Issue = { ...createIssue(), field: 'command.wiedervorlage.baseField1' }; - const control = getControlForIssue(form, issue); + const control = getControlForIssue(form, issue, 'command.wiedervorlage'); - expect(control).toBe(subGroupFieldControl); - }) + expect(control).toBe(baseField1Control); + }); + }); - it('should ignore path prefix', () => { - const issue: Issue = { ...createIssue(), field: 'command.wiedervorlage.baseField1' }; + describe('in base field', () => { + const issue: Issue = { ...createIssue(), field: 'baseField1' }; - const control = getControlForIssue(form, issue, 'command.wiedervorlage'); + it('should set error in control', () => { + setValidationError(form, issue); - expect(control).toBe(baseField1Control); - }) - }) + expect(baseField1Control.errors).not.toBeNull(); + }); - describe('in base field', () => { + it('should set message code in control', () => { + setValidationError(form, issue); - const issue: Issue = { ...createIssue(), field: 'baseField1' }; + expect(baseField1Control.hasError(issue.messageCode)).toBe(true); + }); - it('should set error in control', () => { - setValidationError(form, issue); + it('should set control touched', () => { + setValidationError(form, issue); - expect(baseField1Control.errors).not.toBeNull(); - }); + expect(baseField1Control.touched).toBe(true); + }); - it('should set message code in control', () => { - setValidationError(form, issue); + it('should not set error in other control', () => { + setValidationError(form, issue); - expect(baseField1Control.hasError(issue.messageCode)).toBe(true); - }); + expect(baseField2Control.errors).toBeNull(); + }); + }); - it('should set control touched', () => { - setValidationError(form, issue); + describe('in subGroup Field', () => { + const issue: Issue = { ...createIssue(), field: 'subGroup.subGroupField1' }; - expect(baseField1Control.touched).toBe(true); - }) + it('should set error in control', () => { + setValidationError(form, issue); - it('should not set error in other control', () => { - setValidationError(form, issue); + expect(subGroupFieldControl.errors).not.toBeNull(); + }); + }); + }); - expect(baseField2Control.errors).toBeNull(); - }); - }); + describe('get message for issue', () => { + const fieldLabel = 'Field Label'; - describe('in subGroup Field', () => { + it('should return message', () => { + const msg = getMessageForIssue(fieldLabel, { + ...createIssue(), + messageCode: 'validation_field_size', + }); - const issue: Issue = { ...createIssue(), field: 'subGroup.subGroupField1' }; + expect(msg).toContain('muss mindestens'); + }); - it('should set error in control', () => { - setValidationError(form, issue); + it('should set field label', () => { + const msg = getMessageForIssue(fieldLabel, { + ...createIssue(), + messageCode: 'validation_field_size', + }); - expect(subGroupFieldControl.errors).not.toBeNull(); - }); - }); - }); + expect(msg).toContain(fieldLabel); + }); - describe('get message for issue', () => { + it('should replace min param', () => { + const msg = getMessageForIssue(fieldLabel, { + ...createIssue(), + messageCode: 'validation_field_size', + parameters: [{ name: 'min', value: '3' }], + }); - const fieldLabel = 'Field Label'; - - it('should return message', () => { - const msg = getMessageForIssue(fieldLabel, { ...createIssue(), messageCode: 'validation_field_size' }); - - expect(msg).toContain('muss mindestens'); - }); - - it('should set field label', () => { - const msg = getMessageForIssue(fieldLabel, { ...createIssue(), messageCode: 'validation_field_size' }); - - expect(msg).toContain(fieldLabel); - }); - - it('should replace min param', () => { - const msg = getMessageForIssue(fieldLabel, { ...createIssue(), messageCode: 'validation_field_size', parameters: [{ name: 'min', value: '3' }] }); - - expect(msg).toContain('3'); - }); - }) -}) + expect(msg).toContain('3'); + }); + }); +}); diff --git a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts index 05e3c6563273e182ceb101ca870b8a7c9d4680b7..9007e2411258c8dc6b90d77b3d298f52ba7fb1e8 100644 --- a/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts +++ b/alfa-client/libs/tech-shared/src/lib/validation/tech.validation.util.ts @@ -28,44 +28,48 @@ import { replacePlaceholder } from '../tech.util'; import { ValidationMessageCode, VALIDATION_MESSAGES } from './tech.validation.messages'; export function isValidationError(issue: Issue): boolean { - return issue.messageCode.includes('javax.validation.constraints') + return issue.messageCode.includes('javax.validation.constraints'); } export function setValidationError(form: UntypedFormGroup, issue: Issue, pathPrefix?: string) { - const control = getControlForIssue(form, issue, pathPrefix); + const control = getControlForIssue(form, issue, pathPrefix); - control.setErrors({ [issue.messageCode]: issue }); - control.markAsTouched(); + control.setErrors({ [issue.messageCode]: issue }); + control.markAsTouched(); } -export function getControlForIssue(form: UntypedFormGroup, issue: Issue, pathPrefix?: string): AbstractControl { - const fieldPath = pathPrefix ? issue.field.substring(pathPrefix.length + 1) : issue.field; +export function getControlForIssue( + form: UntypedFormGroup, + issue: Issue, + pathPrefix?: string, +): AbstractControl { + const fieldPath = pathPrefix ? issue.field.substring(pathPrefix.length + 1) : issue.field; - let curControl: AbstractControl = form; - fieldPath.split('.').forEach(field => curControl = (<UntypedFormGroup>curControl).controls[field]); + let curControl: AbstractControl = form; + fieldPath + .split('.') + .forEach((field) => (curControl = (<UntypedFormGroup>curControl).controls[field])); - return curControl; + return curControl; } export function getMessageForIssue(label: string, issue: Issue) { - let msg = VALIDATION_MESSAGES[issue.messageCode]; + let msg = VALIDATION_MESSAGES[issue.messageCode]; - if (isNil(msg)) { - console.warn('No message for code ' + issue.messageCode + ' found.'); - return issue.messageCode; - } + if (isNil(msg)) { + console.warn('No message for code ' + issue.messageCode + ' found.'); + return issue.messageCode; + } - msg = replacePlaceholder(msg, 'field', label); - issue.parameters.forEach(param => - msg = replacePlaceholder(msg, param.name, param.value) - ); - return msg; + msg = replacePlaceholder(msg, 'field', label); + issue.parameters.forEach((param) => (msg = replacePlaceholder(msg, param.name, param.value))); + return msg; } export function getMessageCode(apiError: ApiError): string { - return apiError.issues[0].messageCode; + return apiError.issues[0].messageCode; } -export function isValidationFieldFileSizeExceedError(error: any){ - return getMessageCode(error) === ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED; -} \ No newline at end of file +export function isValidationFieldFileSizeExceedError(error: any) { + return getMessageCode(error) === ValidationMessageCode.VALIDATION_FIELD_FILE_SIZE_EXCEEDED; +} diff --git a/alfa-client/libs/tech-shared/src/test-setup.ts b/alfa-client/libs/tech-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/tech-shared/src/test-setup.ts +++ b/alfa-client/libs/tech-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/tech-shared/test/data-test.ts b/alfa-client/libs/tech-shared/test/data-test.ts index aaeb9cf39d04b1df2578bc3de39e7f8827e52765..d0c53e43d65c6547e211bce4ac0ef9bfb887b9b4 100644 --- a/alfa-client/libs/tech-shared/test/data-test.ts +++ b/alfa-client/libs/tech-shared/test/data-test.ts @@ -22,9 +22,9 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export function getDataTestClassOf(value: string): string { - return `[data-test-class="${value}"]`; + return `[data-test-class="${value}"]`; } export function getDataTestIdOf(value: string): string { - return `[data-test-id="${value}"]`; -} \ No newline at end of file + return `[data-test-id="${value}"]`; +} diff --git a/alfa-client/libs/tech-shared/test/dummy.ts b/alfa-client/libs/tech-shared/test/dummy.ts index 950831832138adc50489bcd0533c0635989d8b16..33e1ab1611c9df963f722a8c340641e10e0c2d33 100644 --- a/alfa-client/libs/tech-shared/test/dummy.ts +++ b/alfa-client/libs/tech-shared/test/dummy.ts @@ -21,16 +21,16 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -class Dummy { } +class Dummy {} export function createDummy(): Dummy { - return new Dummy(); + return new Dummy(); } export enum DummyLinkRel { - DUMMY = 'dummyLink' + DUMMY = 'dummyLink', } export enum DummyListLinkRel { - LIST = 'dummyList' -} \ No newline at end of file + LIST = 'dummyList', +} diff --git a/alfa-client/libs/tech-shared/test/error.ts b/alfa-client/libs/tech-shared/test/error.ts index cdedda90ed275427f58f78da01331e8cee3b095b..e842f95b78713b9b888453a4b96beefb76f61b31 100644 --- a/alfa-client/libs/tech-shared/test/error.ts +++ b/alfa-client/libs/tech-shared/test/error.ts @@ -26,31 +26,31 @@ import { faker } from '@faker-js/faker'; import { ApiError, Issue, IssueParam } from '../src/lib/tech.model'; export function createIssueParam(): IssueParam { - return { - name: faker.random.word(), - value: faker.random.word() - } + return { + name: faker.random.word(), + value: faker.random.word(), + }; } export function createIssue(): Issue { - return { - field: faker.random.word(), - message: faker.random.words(10), - messageCode: faker.random.words(5), - parameters: [createIssueParam()] - }; + return { + field: faker.random.word(), + message: faker.random.words(10), + messageCode: faker.random.words(5), + parameters: [createIssueParam()], + }; } export function createApiError(): ApiError { - return { - issues: [createIssue()] - }; + return { + issues: [createIssue()], + }; } export function createHttpErrorResponse(apiError: ApiError = null): HttpErrorResponse { - return <HttpErrorResponse>{ - error: { - error: apiError ?? createApiError() - } - }; + return <HttpErrorResponse>{ + error: { + error: apiError ?? createApiError(), + }, + }; } diff --git a/alfa-client/libs/tech-shared/test/http.ts b/alfa-client/libs/tech-shared/test/http.ts index 0faa4d1efc5cd0009a3386492b83871767cacdf2..3bfff1482367600d2cb20022f485a6b287fc0476 100644 --- a/alfa-client/libs/tech-shared/test/http.ts +++ b/alfa-client/libs/tech-shared/test/http.ts @@ -25,8 +25,8 @@ import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { createApiError } from './error'; export function createHttpErrorResponse(): HttpErrorResponse { - return <any>{ - error: createApiError(), - status: HttpStatusCode.ServiceUnavailable - } -} \ No newline at end of file + return <any>{ + error: createApiError(), + status: HttpStatusCode.ServiceUnavailable, + }; +} diff --git a/alfa-client/libs/tech-shared/test/ngrx.ts b/alfa-client/libs/tech-shared/test/ngrx.ts index 890981ddad3b622196c2df0137f67629698b5d64..526b345e5b8d10646ef4d1f62fd72d01837a3b90 100644 --- a/alfa-client/libs/tech-shared/test/ngrx.ts +++ b/alfa-client/libs/tech-shared/test/ngrx.ts @@ -1,3 +1,3 @@ import { TypedAction } from '@ngrx/store/src/models'; -export const DUMMY_ACTION: TypedAction<string> = { type: 'Dummy Action'}; \ No newline at end of file +export const DUMMY_ACTION: TypedAction<string> = { type: 'Dummy Action' }; diff --git a/alfa-client/libs/tech-shared/test/resource.ts b/alfa-client/libs/tech-shared/test/resource.ts index f262f959e612e3f0f05e0732cff3f7055727c025..6c6f8be98f1dacc67b64c60a93769ee7ef9cf238 100644 --- a/alfa-client/libs/tech-shared/test/resource.ts +++ b/alfa-client/libs/tech-shared/test/resource.ts @@ -30,42 +30,42 @@ import { createDummy, DummyListLinkRel } from './dummy'; // @ts-ignore export function toResource<R = T & Resource, T = any>( - model: T, - linkRelations: string[] = [], - embeddedResources?: { [key: string]: Resource | Resource[] } + model: T, + linkRelations: string[] = [], + embeddedResources?: { [key: string]: Resource | Resource[] }, ): R { - const resource: Resource = { - ...(model), - _links: { - self: { - href: faker.internet.url() - }, - ...zipObject( - linkRelations, - times(linkRelations.length, () => ({ - href: faker.internet.url() - })) - ) - } - }; + const resource: Resource = { + ...model, + _links: { + self: { + href: faker.internet.url(), + }, + ...zipObject( + linkRelations, + times(linkRelations.length, () => ({ + href: faker.internet.url(), + })), + ), + }, + }; - if (isNotUndefined(embeddedResources)) { - resource._embedded = embeddedResources; - } + if (isNotUndefined(embeddedResources)) { + resource._embedded = embeddedResources; + } - return <any>resource; + return <any>resource; } export function createDummyResource(linkRelations: string[] = []): Resource { - return toResource(createDummy(), linkRelations); + return toResource(createDummy(), linkRelations); } export function createDummyListResource(linkRel: string[] = []): ListResource { - return toResource({}, [...linkRel], { - [DummyListLinkRel.LIST]: createDummyResource() - }) + return toResource({}, [...linkRel], { + [DummyListLinkRel.LIST]: createDummyResource(), + }); } export function createEmptyListResource(linkRelations: string[] = []): ListResource { - return toResource({}, [...linkRelations]); -} \ No newline at end of file + return toResource({}, [...linkRelations]); +} diff --git a/alfa-client/libs/tech-shared/test/window.ts b/alfa-client/libs/tech-shared/test/window.ts index 70f32e4e6609a7012db9c81590836925b41ce30c..bff8ccca5deb76bc72c31f24f899f46f406a4afb 100644 --- a/alfa-client/libs/tech-shared/test/window.ts +++ b/alfa-client/libs/tech-shared/test/window.ts @@ -1,6 +1,6 @@ export function setWindowLocationUrl(url: string): void { - Object.defineProperty(window, 'location', { - value: new URL(url), - writable: true, - }); -} \ No newline at end of file + Object.defineProperty(window, 'location', { + value: new URL(url), + writable: true, + }); +} diff --git a/alfa-client/libs/tech-shared/tsconfig.json b/alfa-client/libs/tech-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/tech-shared/tsconfig.json +++ b/alfa-client/libs/tech-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/tech-shared/tsconfig.lib.json b/alfa-client/libs/tech-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/tech-shared/tsconfig.lib.json +++ b/alfa-client/libs/tech-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/tech-shared/tsconfig.spec.json b/alfa-client/libs/tech-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/tech-shared/tsconfig.spec.json +++ b/alfa-client/libs/tech-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/test-utils/.eslintrc.json b/alfa-client/libs/test-utils/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/test-utils/.eslintrc.json +++ b/alfa-client/libs/test-utils/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/test-utils/jest.config.ts b/alfa-client/libs/test-utils/jest.config.ts index e140c832a807d33c66134eccb11e918359101393..019a3e2e1c238eec3f04594804ba07f6b7672774 100644 --- a/alfa-client/libs/test-utils/jest.config.ts +++ b/alfa-client/libs/test-utils/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'test-utils', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/test-utils', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'test-utils', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/test-utils', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/test-utils/project.json b/alfa-client/libs/test-utils/project.json index b0e23dcdf0669a54bee16ce716c3362bdf5ae042..32c488d8ffc3a5f48c952309de7ee3dfe2441b70 100644 --- a/alfa-client/libs/test-utils/project.json +++ b/alfa-client/libs/test-utils/project.json @@ -1,34 +1,31 @@ { - "name": "test-utils", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/test-utils/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/test-utils/src/**/*.ts", - "libs/test-utils/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/test-utils/tsconfig.spec.json", - "jestConfig": "libs/test-utils/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/test-utils"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "test-utils", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/test-utils/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/test-utils/src/**/*.ts", "libs/test-utils/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/test-utils/tsconfig.spec.json", + "jestConfig": "libs/test-utils/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/test-utils"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/test-utils/src/index.ts b/alfa-client/libs/test-utils/src/index.ts index f5bebce588a4599909fb879bda5cb646263860c9..2496647d81ac7e86f904aef5e70b2031539d4541 100644 --- a/alfa-client/libs/test-utils/src/index.ts +++ b/alfa-client/libs/test-utils/src/index.ts @@ -25,4 +25,3 @@ export * from './lib/helper'; export * from './lib/jest.helper'; export * from './lib/mocking'; export * from './lib/test-utils.module'; - diff --git a/alfa-client/libs/test-utils/src/lib/debug-operator.ts b/alfa-client/libs/test-utils/src/lib/debug-operator.ts index c3cb3fc3ce1f448ef09a83028b882ed6a44af942..a7064a47b59af6d1df5146dda033e03d0ae2ea81 100644 --- a/alfa-client/libs/test-utils/src/lib/debug-operator.ts +++ b/alfa-client/libs/test-utils/src/lib/debug-operator.ts @@ -1,22 +1,38 @@ -import { MonoTypeOperatorFunction, Observable, tap } from "rxjs"; +import { MonoTypeOperatorFunction, Observable, tap } from 'rxjs'; -export function debugTap<T>(fn: (value: T)=> void) { - return function(source: Observable<T>) { - source.pipe(debug(),tap(value => fn(value))).subscribe(); - return source; - }; +export function debugTap<T>(fn: (value: T) => void) { + return function (source: Observable<T>) { + source + .pipe( + debug(), + tap((value) => fn(value)), + ) + .subscribe(); + return source; + }; } function debug<T>(): MonoTypeOperatorFunction<T> { - return tap({ - next(value) { - console.log(`%c[Alfa Client: Next]`, "background: #009688; color: #fff; padding: 3px; font-size: 9px;", value); - }, - error(error) { - console.log(`%[Alfa Client: Error]`, "background: #E91E63; color: #fff; padding: 3px; font-size: 9px;", error); - }, - complete() { - console.log(`%c[Alfa Client]: Complete`, "background: #00BCD4; color: #fff; padding: 3px; font-size: 9px;"); - } - }) -} \ No newline at end of file + return tap({ + next(value) { + console.log( + `%c[Alfa Client: Next]`, + 'background: #009688; color: #fff; padding: 3px; font-size: 9px;', + value, + ); + }, + error(error) { + console.log( + `%[Alfa Client: Error]`, + 'background: #E91E63; color: #fff; padding: 3px; font-size: 9px;', + error, + ); + }, + complete() { + console.log( + `%c[Alfa Client]: Complete`, + 'background: #00BCD4; color: #fff; padding: 3px; font-size: 9px;', + ); + }, + }); +} diff --git a/alfa-client/libs/test-utils/src/lib/helper.ts b/alfa-client/libs/test-utils/src/lib/helper.ts index 016a3ef0ef70e4cdf2c643a15f53a5f57d2067e5..a4fcbd913f24c54d8f195ebe96edf4a73811a488 100644 --- a/alfa-client/libs/test-utils/src/lib/helper.ts +++ b/alfa-client/libs/test-utils/src/lib/helper.ts @@ -25,39 +25,55 @@ import { DebugElement, Type } from '@angular/core'; import { ComponentFixture } from '@angular/core/testing'; import { By } from '@angular/platform-browser'; -export function getElementFromFixtureByType<T>(fixture: ComponentFixture<any>, component: Type<T>): T { - return getDebugElementFromFixtureByType(fixture, component).componentInstance as T; +export function getElementFromFixtureByType<T>( + fixture: ComponentFixture<any>, + component: Type<T>, +): T { + return getDebugElementFromFixtureByType(fixture, component).componentInstance as T; } -function getDebugElementFromFixtureByType<T>(fixture: ComponentFixture<any>, component: Type<T>): DebugElement { - return fixture.debugElement.query(By.directive(component)); +function getDebugElementFromFixtureByType<T>( + fixture: ComponentFixture<any>, + component: Type<T>, +): DebugElement { + return fixture.debugElement.query(By.directive(component)); } export function getElementFromFixture(fixture: ComponentFixture<any>, htmlElement: string): any { - return fixture.nativeElement.querySelector(htmlElement); + return fixture.nativeElement.querySelector(htmlElement); } export function getElementsFromFixture(fixture: ComponentFixture<any>, htmlElement: string): any { - return fixture.nativeElement.querySelectorAll(htmlElement); + return fixture.nativeElement.querySelectorAll(htmlElement); } -export function dispatchEventFromFixture(fixture: ComponentFixture<any>, elementSelector: string, event: string): void { - const element: DebugElement = getDebugElementFromFixtureByCss(fixture, elementSelector) - element.nativeElement.dispatchEvent(new Event(event)); +export function dispatchEventFromFixture( + fixture: ComponentFixture<any>, + elementSelector: string, + event: string, +): void { + const element: DebugElement = getDebugElementFromFixtureByCss(fixture, elementSelector); + element.nativeElement.dispatchEvent(new Event(event)); } -export function getDebugElementFromFixtureByCss(fixture: ComponentFixture<any>, query: string): DebugElement { - return fixture.debugElement.query(By.css(query)); +export function getDebugElementFromFixtureByCss( + fixture: ComponentFixture<any>, + query: string, +): DebugElement { + return fixture.debugElement.query(By.css(query)); } export function getElementFromDomRoot(fixture: ComponentFixture<any>, htmlElement: string): any { - return fixture.nativeElement.parentNode.querySelector(htmlElement); + return fixture.nativeElement.parentNode.querySelector(htmlElement); } -function getDebugElementFromFixtureByDirective(fixture: ComponentFixture<any>, query: Type<any>): DebugElement { - return fixture.debugElement.query(By.directive(query)); +function getDebugElementFromFixtureByDirective( + fixture: ComponentFixture<any>, + query: Type<any>, +): DebugElement { + return fixture.debugElement.query(By.directive(query)); } export function getMockComponent<T>(fixture: ComponentFixture<unknown>, component: Type<T>): T { - return <T> getDebugElementFromFixtureByDirective(fixture, component).componentInstance; -} \ No newline at end of file + return <T>getDebugElementFromFixtureByDirective(fixture, component).componentInstance; +} diff --git a/alfa-client/libs/test-utils/src/lib/jest.helper.ts b/alfa-client/libs/test-utils/src/lib/jest.helper.ts index 55a12e5848a2979a5eedb730a724f18c0423962a..fe174af32fecd09221e48f5e54d2d27de0bb49e7 100644 --- a/alfa-client/libs/test-utils/src/lib/jest.helper.ts +++ b/alfa-client/libs/test-utils/src/lib/jest.helper.ts @@ -3,9 +3,9 @@ import { expect } from '@jest/globals'; import { getElementFromFixture } from './helper'; export function notExistsAsHtmlElement(fixture: ComponentFixture<any>, domElement: string): void { - expect(getElementFromFixture(fixture, domElement)).not.toBeInstanceOf(HTMLElement); + expect(getElementFromFixture(fixture, domElement)).not.toBeInstanceOf(HTMLElement); } export function existsAsHtmlElement(fixture: ComponentFixture<any>, domElement: string): void { - expect(getElementFromFixture(fixture, domElement)).toBeInstanceOf(HTMLElement); -} \ No newline at end of file + expect(getElementFromFixture(fixture, domElement)).toBeInstanceOf(HTMLElement); +} diff --git a/alfa-client/libs/test-utils/src/lib/mocking.ts b/alfa-client/libs/test-utils/src/lib/mocking.ts index 141db74e40b6275c057e8889b718015448889e6c..d62e8815a4fc9d1cc224d12288fe3f2ad0dce98e 100644 --- a/alfa-client/libs/test-utils/src/lib/mocking.ts +++ b/alfa-client/libs/test-utils/src/lib/mocking.ts @@ -23,38 +23,40 @@ */ import { Component, EventEmitter, Type } from '@angular/core'; -export type Mock<T> = { [K in keyof T]: jest.Mock; }; +export type Mock<T> = { [K in keyof T]: jest.Mock }; export function mock<T>(service: Type<T>): Mock<T> { - return <Mock<T>>Object.getOwnPropertyNames(service.prototype).reduce((mockValue, key) => ({ - ...mockValue, - [key]: jest.fn() - }), (<any>{})); + return <Mock<T>>Object.getOwnPropertyNames(service.prototype).reduce( + (mockValue, key) => ({ + ...mockValue, + [key]: jest.fn(), + }), + <any>{}, + ); } export function useFromMock<T>(mockToUse: Mock<T>): T { - return <T><any>mockToUse; + return <T>(<any>mockToUse); } export function mockComponent(options: Component): Component { + const metadata: Component = { + selector: options.selector, + template: options.template || '', + inputs: options.inputs, + outputs: options.outputs || [], + exportAs: options.exportAs || '', + }; - const metadata: Component = { - selector: options.selector, - template: options.template || '', - inputs: options.inputs, - outputs: options.outputs || [], - exportAs: options.exportAs || '' - }; + class Mock {} - class Mock { } + metadata.outputs.forEach((method) => { + Mock.prototype[method] = new EventEmitter<any>(); + }); - metadata.outputs.forEach(method => { - Mock.prototype[method] = new EventEmitter<any>(); - }); - - return Component(metadata)(Mock as any); + return Component(metadata)(Mock as any); } export function mockClass(clazz: any): Mock<any> { - return clazz as jest.Mocked<typeof clazz>; //NOSONAR -} \ No newline at end of file + return clazz as jest.Mocked<typeof clazz>; //NOSONAR +} diff --git a/alfa-client/libs/test-utils/src/lib/test-utils.module.spec.ts b/alfa-client/libs/test-utils/src/lib/test-utils.module.spec.ts index 4d4f9734472f34e64e9492dfdfbbe186f5cbe434..4ed5f676856a3d9741b1ea106d199cc5d969a5a5 100644 --- a/alfa-client/libs/test-utils/src/lib/test-utils.module.spec.ts +++ b/alfa-client/libs/test-utils/src/lib/test-utils.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { TestUtilsModule } from './test-utils.module'; describe('TestUtilsModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [TestUtilsModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [TestUtilsModule], + }).compileComponents(); + }); - it('should create', () => { - expect(TestUtilsModule).toBeDefined(); - }); + it('should create', () => { + expect(TestUtilsModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/test-utils/src/test-setup.ts b/alfa-client/libs/test-utils/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/test-utils/src/test-setup.ts +++ b/alfa-client/libs/test-utils/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/test-utils/tsconfig.json b/alfa-client/libs/test-utils/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/test-utils/tsconfig.json +++ b/alfa-client/libs/test-utils/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/test-utils/tsconfig.lib.json b/alfa-client/libs/test-utils/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/test-utils/tsconfig.lib.json +++ b/alfa-client/libs/test-utils/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/test-utils/tsconfig.spec.json b/alfa-client/libs/test-utils/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/test-utils/tsconfig.spec.json +++ b/alfa-client/libs/test-utils/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/ui/.eslintrc.json b/alfa-client/libs/ui/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/ui/.eslintrc.json +++ b/alfa-client/libs/ui/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/ui/jest.config.ts b/alfa-client/libs/ui/jest.config.ts index 5ea3a2c3665382587fde6aa28297b7d714ecb989..62eaaf35cfa9948f1bcf8a7ae7e9d067cf9acd8b 100644 --- a/alfa-client/libs/ui/jest.config.ts +++ b/alfa-client/libs/ui/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'ui', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/ui', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'ui', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/ui', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/ui/project.json b/alfa-client/libs/ui/project.json index ae9c1d3b2e87a8d15e1ae67d5d6197793780c1c2..0082d00a67c4132e2b963f680a98f67ddb473f2b 100644 --- a/alfa-client/libs/ui/project.json +++ b/alfa-client/libs/ui/project.json @@ -1,34 +1,31 @@ { - "name": "ui", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/ui/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/ui/src/**/*.ts", - "libs/ui/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/ui/tsconfig.spec.json", - "jestConfig": "libs/ui/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/ui"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "ui", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/ui/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/ui/src/**/*.ts", "libs/ui/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/ui/tsconfig.spec.json", + "jestConfig": "libs/ui/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/ui"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/ui/src/lib/font/_font_material.scss b/alfa-client/libs/ui/src/lib/font/_font_material.scss index ebd7593b116d14ee1b96f051038f3cb0ff095055..a93a9e375dc9279d5b0440a07d674cb5940e2fa5 100644 --- a/alfa-client/libs/ui/src/lib/font/_font_material.scss +++ b/alfa-client/libs/ui/src/lib/font/_font_material.scss @@ -23,35 +23,35 @@ */ // Kopiert von https://fonts.googleapis.com/icon?family=Material+Icons|Material+Icons+Outlined @font-face { - font-family: 'Material Icons'; - font-style: normal; - font-weight: 400; - src: url(flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2) format('woff2'); + font-family: 'Material Icons'; + font-style: normal; + font-weight: 400; + src: url(flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2) format('woff2'); } @font-face { - font-family: 'Material Icons Outlined'; - font-style: normal; - font-weight: 400; - src: url(gok-H7zzDkdnRel8-DQ6KAXJ69wP1tGnf4ZGhUcel5euIg.woff2) format('woff2'); + font-family: 'Material Icons Outlined'; + font-style: normal; + font-weight: 400; + src: url(gok-H7zzDkdnRel8-DQ6KAXJ69wP1tGnf4ZGhUcel5euIg.woff2) format('woff2'); } .material-icons { - font-family: 'Material Icons', sans-serif; - font-weight: normal; - font-style: normal; - font-size: 24px; - line-height: 1; - letter-spacing: normal; - text-transform: none; - display: inline-block; - white-space: nowrap; - word-wrap: normal; - direction: ltr; - -moz-font-feature-settings: 'liga'; - -moz-osx-font-smoothing: grayscale; + font-family: 'Material Icons', sans-serif; + font-weight: normal; + font-style: normal; + font-size: 24px; + line-height: 1; + letter-spacing: normal; + text-transform: none; + display: inline-block; + white-space: nowrap; + word-wrap: normal; + direction: ltr; + -moz-font-feature-settings: 'liga'; + -moz-osx-font-smoothing: grayscale; } .material-icons-outlined { - font-family: 'Material Icons Outlined', sans-serif; + font-family: 'Material Icons Outlined', sans-serif; } diff --git a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.html b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.html index 91b523cc9813fb48df9057ce7f77c4bb2ae7131d..564844ea4ba37fead4cd344f14bce711e1e0d0cd 100644 --- a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.html +++ b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.html @@ -23,4 +23,4 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<mat-icon svgIcon="logo"></mat-icon> \ No newline at end of file +<mat-icon svgIcon="logo"></mat-icon> diff --git a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.scss b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.scss index a7791b03362234c2f3d00bf4743aaf10b1873619..53f2c209c3a845353f2f2f47c3832415128965f6 100644 --- a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.scss +++ b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.scss @@ -25,25 +25,25 @@ //TODO Farben festlegen :host { - display: flex; - align-items: center; - justify-content: center; - width: 23px; - height: 23px; - border-radius: 50%; - position: relative; - overflow: hidden; - border: 1px solid #ccc; + display: flex; + align-items: center; + justify-content: center; + width: 23px; + height: 23px; + border-radius: 50%; + position: relative; + overflow: hidden; + border: 1px solid #ccc; - :host-context(.dark) { - background-color: #565656; - border: none; - width: 25px; - height: 25px; - } + :host-context(.dark) { + background-color: #565656; + border: none; + width: 25px; + height: 25px; + } - mat-icon { - width: 18px; - height: 18px; - } -} \ No newline at end of file + mat-icon { + width: 18px; + height: 18px; + } +} diff --git a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.spec.ts b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.spec.ts index a0ac14f8f4a4dccf647b5c9a60de6c14b3d5779c..9272b22e44a336ecf20fc009b2d40e36c516198d 100644 --- a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.spec.ts @@ -27,28 +27,23 @@ import { MatIconTestingModule } from '@angular/material/icon/testing'; import { AppIconComponent } from './app-icon.component'; describe('AppIconComponent', () => { - let component: AppIconComponent; - let fixture: ComponentFixture<AppIconComponent>; + let component: AppIconComponent; + let fixture: ComponentFixture<AppIconComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MatIcon, - AppIconComponent - ], - imports: [ - MatIconTestingModule - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [MatIcon, AppIconComponent], + imports: [MatIconTestingModule], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(AppIconComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(AppIconComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.ts b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.ts index d2d6ced7dfdfe0164d4b076ac98c4a91f281fdfa..4d86914716d0a047649a8a9dbb6b43f1d45b88fe 100644 --- a/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.ts +++ b/alfa-client/libs/ui/src/lib/icon/app-icon/app-icon.component.ts @@ -24,9 +24,8 @@ import { Component } from '@angular/core'; @Component({ - selector: 'ozgcloud-app-icon', - templateUrl: './app-icon.component.html', - styleUrls: ['./app-icon.component.scss'], + selector: 'ozgcloud-app-icon', + templateUrl: './app-icon.component.html', + styleUrls: ['./app-icon.component.scss'], }) -export class AppIconComponent { -} +export class AppIconComponent {} diff --git a/alfa-client/libs/ui/src/lib/icon/icon.model.ts b/alfa-client/libs/ui/src/lib/icon/icon.model.ts index 9be3e54ef42fa3b771de193375ed4ed8753d440d..a7b7d26ba85860a97d0977b9a1d2cdfa2bca0a43 100644 --- a/alfa-client/libs/ui/src/lib/icon/icon.model.ts +++ b/alfa-client/libs/ui/src/lib/icon/icon.model.ts @@ -22,25 +22,25 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum Icons { - ACCOUNT_OUTLINE = 'account_outline', - ASSIGNMENT_IND = 'assignment_ind', - AZ = 'az', - DELETE_FINALLY = 'delete_finally', - DISCARD_DOCUMENT = 'discard_document', - DONE = 'done', - EDIT = 'edit', - INCOMING = 'incoming', - LOESCHEN_ANFORDERN = 'request_deletion', - LOESCH_ANFORDERUNG_ZURUECKNEHMEN = 'undo_request_deletion', - LOGO = 'logo', - MAIL = 'mail', - NO_REPLY = 'no_reply', - NR = 'nr', - PDF_FILE = 'pdf_file', - PDF_EXPORT = 'pdf_export', - RESUBMISSION_EXPIRED = 'resubmission_expired', - STAMP = 'stamp', - VORGANG_VORPRUEFEN = 'vorgang_vorpruefen', - XDOMEA = 'xdomea_file', - PASTE_FROM_CLIPBOARD = 'paste_from_clipboard', + ACCOUNT_OUTLINE = 'account_outline', + ASSIGNMENT_IND = 'assignment_ind', + AZ = 'az', + DELETE_FINALLY = 'delete_finally', + DISCARD_DOCUMENT = 'discard_document', + DONE = 'done', + EDIT = 'edit', + INCOMING = 'incoming', + LOESCHEN_ANFORDERN = 'request_deletion', + LOESCH_ANFORDERUNG_ZURUECKNEHMEN = 'undo_request_deletion', + LOGO = 'logo', + MAIL = 'mail', + NO_REPLY = 'no_reply', + NR = 'nr', + PDF_FILE = 'pdf_file', + PDF_EXPORT = 'pdf_export', + RESUBMISSION_EXPIRED = 'resubmission_expired', + STAMP = 'stamp', + VORGANG_VORPRUEFEN = 'vorgang_vorpruefen', + XDOMEA = 'xdomea_file', + PASTE_FROM_CLIPBOARD = 'paste_from_clipboard', } diff --git a/alfa-client/libs/ui/src/lib/icon/icon.service.spec.ts b/alfa-client/libs/ui/src/lib/icon/icon.service.spec.ts index 5adc86dd248e128238a953cc6c91df4369925f94..40df735a542f2542ba3686ac773de165406eb4ba 100644 --- a/alfa-client/libs/ui/src/lib/icon/icon.service.spec.ts +++ b/alfa-client/libs/ui/src/lib/icon/icon.service.spec.ts @@ -27,43 +27,45 @@ import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { Icons } from './icon.model'; describe('IconService', () => { - let service: IconService; - let matIconRegistry: Mock<MatIconRegistry>; - let domSanitizer: Mock<any>; + let service: IconService; + let matIconRegistry: Mock<MatIconRegistry>; + let domSanitizer: Mock<any>; - const iconBasePath: string = '/assets/icons/'; - const iconsObjectLength = Object.keys(Icons).length + const iconBasePath: string = '/assets/icons/'; + const iconsObjectLength = Object.keys(Icons).length; - beforeEach(() => { - matIconRegistry = mock(MatIconRegistry); - domSanitizer = { bypassSecurityTrustResourceUrl: jest.fn() }; + beforeEach(() => { + matIconRegistry = mock(MatIconRegistry); + domSanitizer = { bypassSecurityTrustResourceUrl: jest.fn() }; - service = new IconService(useFromMock(matIconRegistry), useFromMock(domSanitizer)); - }) + service = new IconService(useFromMock(matIconRegistry), useFromMock(domSanitizer)); + }); - it('should create', () => { - expect(service).toBeDefined(); - }) + it('should create', () => { + expect(service).toBeDefined(); + }); - describe('add Icon to registry', () => { - it('should call registry to add SvgIgon', () => { - service.registerIcons(); + describe('add Icon to registry', () => { + it('should call registry to add SvgIgon', () => { + service.registerIcons(); - expect(matIconRegistry.addSvgIcon).toHaveBeenCalled(); - expect(matIconRegistry.addSvgIcon).toHaveBeenCalledTimes(iconsObjectLength); - }) + expect(matIconRegistry.addSvgIcon).toHaveBeenCalled(); + expect(matIconRegistry.addSvgIcon).toHaveBeenCalledTimes(iconsObjectLength); + }); - it('should call domSanitizer', () => { - service.registerIcons(); + it('should call domSanitizer', () => { + service.registerIcons(); - expect(domSanitizer.bypassSecurityTrustResourceUrl).toHaveBeenCalled(); - expect(domSanitizer.bypassSecurityTrustResourceUrl).toHaveBeenCalledTimes(iconsObjectLength); - }) + expect(domSanitizer.bypassSecurityTrustResourceUrl).toHaveBeenCalled(); + expect(domSanitizer.bypassSecurityTrustResourceUrl).toHaveBeenCalledTimes(iconsObjectLength); + }); - it('should call domSanitizer for `incoming` icon', () => { - service.registerIcons(); + it('should call domSanitizer for `incoming` icon', () => { + service.registerIcons(); - expect(domSanitizer.bypassSecurityTrustResourceUrl).toHaveBeenCalledWith(iconBasePath + 'incoming.svg'); - }) - }) -}) + expect(domSanitizer.bypassSecurityTrustResourceUrl).toHaveBeenCalledWith( + iconBasePath + 'incoming.svg', + ); + }); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/icon/icon.service.ts b/alfa-client/libs/ui/src/lib/icon/icon.service.ts index 33a1be1ff9c454a09ff741d68aac1199da1b5a89..43edbafc17c02140946b64bcc3fcab68eb32dcc7 100644 --- a/alfa-client/libs/ui/src/lib/icon/icon.service.ts +++ b/alfa-client/libs/ui/src/lib/icon/icon.service.ts @@ -28,17 +28,21 @@ import { Icons } from './icon.model'; @Injectable({ providedIn: 'root' }) export class IconService { + constructor( + private matIconRegistry: MatIconRegistry, + private domSanitizer: DomSanitizer, + ) {} - constructor( - private matIconRegistry: MatIconRegistry, - private domSanitizer: DomSanitizer - ) { } + public registerIcons(): void { + this.loadIcons(Object.values(Icons), '/assets/icons'); + } - public registerIcons(): void { - this.loadIcons(Object.values(Icons), '/assets/icons'); - } - - private loadIcons(iconKeys: string[], iconUrl: string): void { - iconKeys.forEach(key => this.matIconRegistry.addSvgIcon(key, this.domSanitizer.bypassSecurityTrustResourceUrl(`${iconUrl}/${key}.svg`))); - } + private loadIcons(iconKeys: string[], iconUrl: string): void { + iconKeys.forEach((key) => + this.matIconRegistry.addSvgIcon( + key, + this.domSanitizer.bypassSecurityTrustResourceUrl(`${iconUrl}/${key}.svg`), + ), + ); + } } diff --git a/alfa-client/libs/ui/src/lib/icon/postfach-icon/_postfach-icon.component.theme.scss b/alfa-client/libs/ui/src/lib/icon/postfach-icon/_postfach-icon.component.theme.scss index b83fefec3c9a2815702b84095983872308175a94..7fbf85546be92165daff5ec1af9b0362bbcf937d 100644 --- a/alfa-client/libs/ui/src/lib/icon/postfach-icon/_postfach-icon.component.theme.scss +++ b/alfa-client/libs/ui/src/lib/icon/postfach-icon/_postfach-icon.component.theme.scss @@ -22,12 +22,12 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ ozgcloud-postfach-icon { - .mat-badge-small.mat-badge-above .mat-badge-content { - top: -3px; - } - .mat-badge-small.mat-badge-overlap.mat-badge-after .mat-badge-content { - width: 12px; - height: 12px; - right: -4px; - } + .mat-badge-small.mat-badge-above .mat-badge-content { + top: -3px; + } + .mat-badge-small.mat-badge-overlap.mat-badge-after .mat-badge-content { + width: 12px; + height: 12px; + right: -4px; + } } diff --git a/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.html b/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.html index cc27036e0a9073bfbfa70f821d39f16618683e33..6160aaa86fc78c75fe33d742bcd1605d74f6d561 100644 --- a/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.html +++ b/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.html @@ -23,9 +23,11 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<mat-icon data-test-class="postfach-icon-mat-icon" - svgIcon="mail" - matBadge="⁠" - [matBadgeHidden]="!showBadge" - matBadgeSize="small"> -</mat-icon> \ No newline at end of file +<mat-icon + data-test-class="postfach-icon-mat-icon" + svgIcon="mail" + matBadge="⁠" + [matBadgeHidden]="!showBadge" + matBadgeSize="small" +> +</mat-icon> diff --git a/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.spec.ts b/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.spec.ts index b2a9a0f58d0cff0f79b846626beeb0af9e5370d6..339ab141b7279bfa64c1f65fbe7d72d57d051744 100644 --- a/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.spec.ts @@ -29,55 +29,47 @@ import { getElementFromFixture } from '@alfa-client/test-utils'; import { getDataTestClassOf } from 'libs/tech-shared/test/data-test'; import { PostfachIconComponent } from './postfach-icon.component'; - describe('PostfachIconComponent', () => { - let component: PostfachIconComponent; - let fixture: ComponentFixture<PostfachIconComponent>; + let component: PostfachIconComponent; + let fixture: ComponentFixture<PostfachIconComponent>; - const postfachIcon: string = getDataTestClassOf('postfach-icon-mat-icon'); + const postfachIcon: string = getDataTestClassOf('postfach-icon-mat-icon'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MatIcon, - PostfachIconComponent, - MatBadge, - ], - imports: [ - MatIconTestingModule, - MatBadgeModule, - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [MatIcon, PostfachIconComponent, MatBadge], + imports: [MatIconTestingModule, MatBadgeModule], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(PostfachIconComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(PostfachIconComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('mail icon', () => { - it('should show mail icon', () => { - component.showBadge = false; - fixture.detectChanges(); + describe('mail icon', () => { + it('should show mail icon', () => { + component.showBadge = false; + fixture.detectChanges(); - const icon: HTMLElement = getElementFromFixture(fixture, postfachIcon); + const icon: HTMLElement = getElementFromFixture(fixture, postfachIcon); - expect(icon).toHaveClass('mat-icon'); - expect(icon).toHaveClass('mat-badge-hidden'); - }); + expect(icon).toHaveClass('mat-icon'); + expect(icon).toHaveClass('mat-badge-hidden'); + }); - it('should show mail icon with badge', () => { - component.showBadge = true; - fixture.detectChanges(); + it('should show mail icon with badge', () => { + component.showBadge = true; + fixture.detectChanges(); - const icon: HTMLElement = getElementFromFixture(fixture, postfachIcon); + const icon: HTMLElement = getElementFromFixture(fixture, postfachIcon); - expect(icon).toHaveClass('mat-badge'); - }); - }); + expect(icon).toHaveClass('mat-badge'); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.ts b/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.ts index 0bc56357ee24c4d6320bc116e6b74e8c614131b2..420e4e773e38d09d670ed556a2a4cfd74232cbae 100644 --- a/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.ts +++ b/alfa-client/libs/ui/src/lib/icon/postfach-icon/postfach-icon.component.ts @@ -24,12 +24,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-postfach-icon', - templateUrl: './postfach-icon.component.html', - styleUrls: ['./postfach-icon.component.scss'], + selector: 'ozgcloud-postfach-icon', + templateUrl: './postfach-icon.component.html', + styleUrls: ['./postfach-icon.component.scss'], }) export class PostfachIconComponent { - - @Input() showBadge: boolean = false; - + @Input() showBadge: boolean = false; } diff --git a/alfa-client/libs/ui/src/lib/interceptor/http-connection-timeout.interceptor.spec.ts b/alfa-client/libs/ui/src/lib/interceptor/http-connection-timeout.interceptor.spec.ts index 7582f70a54a6a7beb70857a92c1fa3b2874324fd..45b9c7a02494acf7ce70ac6cd0ea65e45086cee4 100644 --- a/alfa-client/libs/ui/src/lib/interceptor/http-connection-timeout.interceptor.spec.ts +++ b/alfa-client/libs/ui/src/lib/interceptor/http-connection-timeout.interceptor.spec.ts @@ -29,148 +29,144 @@ import { RetryInTimeDialog } from '../ui/dialog/retry-in-time.dialog'; import { HttpConnectionTimeoutInterceptor } from './http-connection-timeout.interceptor'; describe('HttpConnectionTimeoutInterceptor', () => { + let interceptor: HttpConnectionTimeoutInterceptor; + const dialogService = mock(DialogService); + const errorHandler = mock(HttpErrorHandler); + const tokenExtractor = <any>{ getToken: () => jest.fn }; - let interceptor: HttpConnectionTimeoutInterceptor - const dialogService = mock(DialogService); - const errorHandler = mock(HttpErrorHandler); - const tokenExtractor = <any>{ getToken: () => jest.fn }; + const request: HttpRequest<unknown> = <any>{}; + const next: HttpHandler = <any>{}; + const retryDialog = mock(RetryInTimeDialog); - const request: HttpRequest<unknown> = <any>{}; - const next: HttpHandler = <any>{}; - const retryDialog = mock(RetryInTimeDialog); + beforeAll(() => { + interceptor = new HttpConnectionTimeoutInterceptor( + useFromMock(dialogService), + useFromMock(errorHandler), + tokenExtractor, + ); - beforeAll(() => { - interceptor = new HttpConnectionTimeoutInterceptor(useFromMock(dialogService), useFromMock(errorHandler), tokenExtractor); + dialogService.getRetryDialog.mockReturnValue(retryDialog); + }); - dialogService.getRetryDialog.mockReturnValue(retryDialog); - }) + describe('handle error', () => { + it('should initRetryDialog', () => { + interceptor.retryDialog = null; - describe('handle error', () => { + executeHandleError(HttpStatusCode.ServiceUnavailable); - it('should initRetryDialog', () => { - interceptor.retryDialog = null; + expect(interceptor.retryDialog).not.toBeNull(); + }); - executeHandleError(HttpStatusCode.ServiceUnavailable); + it('shouldCallService', () => { + executeHandleError(); - expect(interceptor.retryDialog).not.toBeNull(); - }) + expect(dialogService.getRetryDialog).toHaveBeenCalled(); + }); - it('shouldCallService', () => { - executeHandleError(); + it('should not call service if already initiated', () => { + dialogService.getRetryDialog.mockClear(); + interceptor.doRetry = jest.fn(); + interceptor.retryDialog = <any>{ shouldRetry: () => true }; - expect(dialogService.getRetryDialog).toHaveBeenCalled(); - }) + executeHandleError(); - it('should not call service if already initiated', () => { - dialogService.getRetryDialog.mockClear(); - interceptor.doRetry = jest.fn(); - interceptor.retryDialog = <any>{ shouldRetry: () => true }; + expect(dialogService.getRetryDialog).not.toHaveBeenCalled(); + }); - executeHandleError(); + it('should do nothing on no connection timeout status', () => { + dialogService.getRetryDialog.mockClear(); - expect(dialogService.getRetryDialog).not.toHaveBeenCalled(); - }) + executeHandleError(HttpStatusCode.InternalServerError); - it('should do nothing on no connection timeout status', () => { - dialogService.getRetryDialog.mockClear(); + expect(dialogService.getRetryDialog).not.toHaveBeenCalled(); + }); - executeHandleError(HttpStatusCode.InternalServerError); + it('should do retry', () => { + interceptor.retryDialog = <any>{ shouldRetry: () => true }; + interceptor.doRetry = jest.fn(); - expect(dialogService.getRetryDialog).not.toHaveBeenCalled(); - }) + executeHandleError(); - it('should do retry', () => { - interceptor.retryDialog = <any>{ shouldRetry: () => true }; - interceptor.doRetry = jest.fn(); + expect(interceptor.doRetry).toHaveBeenCalled(); + }); - executeHandleError(); + function executeHandleError(status: number = HttpStatusCode.ServiceUnavailable) { + interceptor.handleError(request, next, <HttpErrorResponse>{ status }, true); + } + }); - expect(interceptor.doRetry).toHaveBeenCalled(); - }) + describe('handleErrorRetry', () => { + describe('on connection timeout error', () => { + const retryDialog = <any>{ shouldRetry: () => true, finish: () => jest.fn() }; - function executeHandleError(status: number = HttpStatusCode.ServiceUnavailable) { - interceptor.handleError(request, next, <HttpErrorResponse>{ status }, true); - } - }) + it('should do retry if condition fits', () => { + interceptor.retryDialog = retryDialog; + interceptor.doRetry = jest.fn(); - describe('handleErrorRetry', () => { + executeHandleErrorRetry(); - describe('on connection timeout error', () => { + expect(interceptor.doRetry).toHaveBeenCalledWith(request, next); + }); - const retryDialog = <any>{ shouldRetry: () => true, finish: () => jest.fn() }; + it('should unset retryDialog if condition does not fit', () => { + interceptor.retryDialog = { ...retryDialog, shouldRetry: () => false }; - it('should do retry if condition fits', () => { - interceptor.retryDialog = retryDialog; - interceptor.doRetry = jest.fn(); + executeHandleErrorRetry(); - executeHandleErrorRetry(); + expect(interceptor.retryDialog).toBeNull(); + }); - expect(interceptor.doRetry).toHaveBeenCalledWith(request, next); - }) + it('should call stop retry if condition does not fit', () => { + interceptor.retryDialog = { ...retryDialog, shouldRetry: () => false }; + interceptor.stopRetry = jest.fn(); - it('should unset retryDialog if condition does not fit', () => { - interceptor.retryDialog = { ...retryDialog, shouldRetry: () => false }; + executeHandleErrorRetry(); - executeHandleErrorRetry(); + expect(interceptor.stopRetry).toHaveBeenCalled(); + }); - expect(interceptor.retryDialog).toBeNull(); - }) + function executeHandleErrorRetry(status: number = HttpStatusCode.ServiceUnavailable) { + interceptor.handleErrorRetry(request, next, <HttpErrorResponse>{ status }); + } + }); + }); - it('should call stop retry if condition does not fit', () => { - interceptor.retryDialog = { ...retryDialog, shouldRetry: () => false }; - interceptor.stopRetry = jest.fn(); + describe('handleResponse', () => { + const retryDialog = <any>{}; - executeHandleErrorRetry(); + describe('on valid response', () => { + const response = { type: 4, ok: true }; - expect(interceptor.stopRetry).toHaveBeenCalled(); - }) + it('should close all retry dialogs if response is valid', () => { + interceptor.handleResponse(response); - function executeHandleErrorRetry(status: number = HttpStatusCode.ServiceUnavailable) { - interceptor.handleErrorRetry(request, next, <HttpErrorResponse>{ status }); - } - }) - }) + expect(dialogService.closeById).toHaveBeenCalledWith(RetryInTimeDialog.ID); + }); - describe('handleResponse', () => { + it('should unset retryDialog', () => { + interceptor.retryDialog = retryDialog; - const retryDialog = <any>{}; + interceptor.handleResponse(response); - describe('on valid response', () => { + expect(interceptor.retryDialog).toBeNull(); + }); + }); - const response = { type: 4, ok: true }; + describe('on invalid response', () => { + const response = { type: 0 }; - it('should close all retry dialogs if response is valid', () => { - interceptor.handleResponse(response); + beforeEach(() => { + dialogService.closeById.mockClear(); + }); - expect(dialogService.closeById).toHaveBeenCalledWith(RetryInTimeDialog.ID); - }) + it('should do nothing on invalid response', () => { + interceptor.retryDialog = retryDialog; - it('should unset retryDialog', () => { - interceptor.retryDialog = retryDialog; + interceptor.handleResponse(response); - interceptor.handleResponse(response); - - expect(interceptor.retryDialog).toBeNull(); - }) - }) - - describe('on invalid response', () => { - - const response = { type: 0 }; - - beforeEach(() => { - dialogService.closeById.mockClear(); - }) - - it('should do nothing on invalid response', () => { - interceptor.retryDialog = retryDialog; - - interceptor.handleResponse(response); - - expect(dialogService.closeById).not.toHaveBeenCalled(); - expect(interceptor.retryDialog).toStrictEqual(retryDialog); - }) - }) - - }) -}) \ No newline at end of file + expect(dialogService.closeById).not.toHaveBeenCalled(); + expect(interceptor.retryDialog).toStrictEqual(retryDialog); + }); + }); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/interceptor/http-connection-timeout.interceptor.ts b/alfa-client/libs/ui/src/lib/interceptor/http-connection-timeout.interceptor.ts index 2c8dc186466dd2332a4bffc14184e582845f4a8f..3fb027d251d8830c197a362da4f04a7118234b38 100644 --- a/alfa-client/libs/ui/src/lib/interceptor/http-connection-timeout.interceptor.ts +++ b/alfa-client/libs/ui/src/lib/interceptor/http-connection-timeout.interceptor.ts @@ -21,9 +21,21 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpXsrfTokenExtractor } from '@angular/common/http'; +import { + HttpErrorResponse, + HttpEvent, + HttpHandler, + HttpInterceptor, + HttpRequest, + HttpXsrfTokenExtractor, +} from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { addRequestHeader, HttpErrorHandler, isConnectionTimeout, sleep } from '@alfa-client/tech-shared'; +import { + addRequestHeader, + HttpErrorHandler, + isConnectionTimeout, + sleep, +} from '@alfa-client/tech-shared'; import { HttpXsrfInterceptor } from 'libs/tech-shared/src/lib/interceptor/http-xsrf.interceptor'; import { isNull } from 'lodash-es'; import { Observable, throwError } from 'rxjs'; @@ -33,80 +45,97 @@ import { RetryInTimeDialog } from '../ui/dialog/retry-in-time.dialog'; @Injectable() export class HttpConnectionTimeoutInterceptor implements HttpInterceptor { + readonly RETRY_IN_MS = 1000; + retryDialog: RetryInTimeDialog = null; - readonly RETRY_IN_MS = 1000; - retryDialog: RetryInTimeDialog = null; + constructor( + private dialogService: DialogService, + private errorHandler: HttpErrorHandler, + private tokenExtractor: HttpXsrfTokenExtractor, + ) {} - constructor(private dialogService: DialogService, private errorHandler: HttpErrorHandler, private tokenExtractor: HttpXsrfTokenExtractor) { } + intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { + const defaultHandling: boolean = this.errorHandler.shouldDoRetry(); + return next.handle(request).pipe( + catchError((error: HttpErrorResponse) => + this.handleError(request, next, error, defaultHandling), + ), + finalize(() => this.errorHandler.enableRetry()), + ); + } - intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { - const defaultHandling: boolean = this.errorHandler.shouldDoRetry(); - return next.handle(request).pipe( - catchError((error: HttpErrorResponse) => this.handleError(request, next, error, defaultHandling)), - finalize(() => this.errorHandler.enableRetry()) - ) - } + handleError( + request: HttpRequest<unknown>, + next: HttpHandler, + response: HttpErrorResponse, + defaultHandling: boolean, + ): Observable<any> { + if (defaultHandling) { + if (isConnectionTimeout(response.status)) { + this.initRetry(); - handleError(request: HttpRequest<unknown>, next: HttpHandler, response: HttpErrorResponse, defaultHandling: boolean): Observable<any> { - if (defaultHandling) { - if (isConnectionTimeout(response.status)) { - this.initRetry(); + if (this.retryDialog.shouldRetry()) { + return this.doRetry(request, next); + } + } + } + return throwError({ response }); + } - if (this.retryDialog.shouldRetry()) { - return this.doRetry(request, next); - } - } - } - return throwError({ response }); - } + initRetry(): void { + if (isNull(this.retryDialog)) { + this.retryDialog = this.dialogService.getRetryDialog(); + this.retryDialog.show(); + } + } - initRetry(): void { - if (isNull(this.retryDialog)) { - this.retryDialog = this.dialogService.getRetryDialog(); - this.retryDialog.show(); - } - } + doRetry(request: HttpRequest<unknown>, next: HttpHandler): Observable<any> { + this.sleepUntilRetry(); + return next + .handle(addRequestHeader(request, HttpXsrfInterceptor.X_XSRF_TOKEN_HEADER, this.getToken())) + .pipe( + catchError((error: HttpErrorResponse) => this.handleErrorRetry(request, next, error)), + tap((response) => this.handleResponse(response)), + finalize(() => this.errorHandler.enableRetry()), + ); + } - doRetry(request: HttpRequest<unknown>, next: HttpHandler): Observable<any> { - this.sleepUntilRetry(); - return next.handle(addRequestHeader(request, HttpXsrfInterceptor.X_XSRF_TOKEN_HEADER, this.getToken())).pipe( - catchError((error: HttpErrorResponse) => this.handleErrorRetry(request, next, error)), - tap(response => this.handleResponse(response)), - finalize(() => this.errorHandler.enableRetry())) - } + sleepUntilRetry(): void { + sleep(this.RETRY_IN_MS); + } - sleepUntilRetry(): void { - sleep(this.RETRY_IN_MS); - } + handleErrorRetry( + request: HttpRequest<unknown>, + next: HttpHandler, + response: HttpErrorResponse, + ): Observable<any> { + if (isConnectionTimeout(response.status)) { + if (this.retryDialog.shouldRetry()) { + return this.doRetry(request, next); + } else { + this.stopRetry(); + } + } + return throwError({ response }); + } - handleErrorRetry(request: HttpRequest<unknown>, next: HttpHandler, response: HttpErrorResponse): Observable<any> { - if (isConnectionTimeout(response.status)) { - if (this.retryDialog.shouldRetry()) { - return this.doRetry(request, next); - } else { - this.stopRetry(); - } - } - return throwError({ response }); - } + stopRetry(): void { + this.retryDialog.finish(); + this.retryDialog = null; + } - stopRetry(): void { - this.retryDialog.finish(); - this.retryDialog = null; - } + private getToken(): string { + return this.tokenExtractor.getToken(); + } - private getToken(): string { - return this.tokenExtractor.getToken(); - } + handleResponse(response: any): void { + if (this.isValidResponse(response)) { + this.dialogService.closeById(RetryInTimeDialog.ID); + this.retryDialog = null; + } + } - handleResponse(response: any): void { - if (this.isValidResponse(response)) { - this.dialogService.closeById(RetryInTimeDialog.ID); - this.retryDialog = null; - } - } - - isValidResponse(response: any): boolean { - return response.type !== 0 && response.ok; - } -} \ No newline at end of file + isValidResponse(response: any): boolean { + return response.type !== 0 && response.ok; + } +} diff --git a/alfa-client/libs/ui/src/lib/interceptor/http-error.interceptor.spec.ts b/alfa-client/libs/ui/src/lib/interceptor/http-error.interceptor.spec.ts index 356d40f28a200d5ccd4e40b98e9e37581e7cf3f3..eadb558bd963acf460bcdd5797b3017e582527a7 100644 --- a/alfa-client/libs/ui/src/lib/interceptor/http-error.interceptor.spec.ts +++ b/alfa-client/libs/ui/src/lib/interceptor/http-error.interceptor.spec.ts @@ -35,150 +35,157 @@ import { Messages } from '../ui/messages'; import { HttpErrorInterceptor } from './http-error.interceptor'; describe('HttpErrorInterceptor', () => { - let interceptor: HttpErrorInterceptor; - - const dialogService: Mock<DialogService> = mock(DialogService); - const snackbarService: Mock<SnackBarService> = mock(SnackBarService); - const httpErrorHandler: Mock<HttpErrorHandler> = mock(HttpErrorHandler); - const authService: Mock<AuthService> = mock(AuthService); - - beforeEach(() => TestBed.configureTestingModule({ - imports: [ - MatDialogModule - ], - providers: [ - HttpErrorInterceptor, - { - provide: DialogService, - useValue: dialogService - }, - { - provide: SnackBarService, - useValue: snackbarService - }, - { - provide: HttpErrorHandler, - useValue: httpErrorHandler - }, - { - provide: AuthService, - useValue: authService - } - ] - })); + let interceptor: HttpErrorInterceptor; + + const dialogService: Mock<DialogService> = mock(DialogService); + const snackbarService: Mock<SnackBarService> = mock(SnackBarService); + const httpErrorHandler: Mock<HttpErrorHandler> = mock(HttpErrorHandler); + const authService: Mock<AuthService> = mock(AuthService); + + beforeEach(() => + TestBed.configureTestingModule({ + imports: [MatDialogModule], + providers: [ + HttpErrorInterceptor, + { + provide: DialogService, + useValue: dialogService, + }, + { + provide: SnackBarService, + useValue: snackbarService, + }, + { + provide: HttpErrorHandler, + useValue: httpErrorHandler, + }, + { + provide: AuthService, + useValue: authService, + }, + ], + }), + ); + + beforeEach(() => { + interceptor = TestBed.inject(HttpErrorInterceptor); + }); + + it('should be created', () => { + expect(interceptor).toBeTruthy(); + }); + + describe('intercept', () => { + const response = new HttpErrorResponse({}); + const error = { response }; + const subject: Subject<any> = new Subject(); + const httpHandler = { handle: () => subject }; + const request: HttpRequest<unknown> = new HttpRequest('GET', '/test'); + + it('should call http error handler', () => { + interceptor.handleErrorResponse = jest.fn(); + + interceptor.intercept(request, <any>httpHandler).subscribe(); + subject.error(error); + + expect(httpErrorHandler.shouldDoDefaultHandling).toHaveBeenCalled(); + }); + + it('should call handleErrorResponse with error', () => { + httpErrorHandler.shouldDoDefaultHandling.mockReturnValue(true); + interceptor.handleErrorResponse = jest.fn(); + + interceptor.intercept(request, <any>httpHandler).subscribe(); + subject.error(error); + + expect(interceptor.handleErrorResponse).toHaveBeenCalledWith({ response }, true); + }); + }); + + describe('handleErrorResponse', () => { + const response: HttpErrorResponse = new HttpErrorResponse({ + error: createApiError(), + status: 500, + }); + const error = { response }; + + beforeEach(() => { + interceptor.handleError = jest.fn(); + }); + + it('should call handleError if defaultHandling is enabled', () => { + interceptor.handleErrorResponse(error, true); + + expect(interceptor.handleError).toHaveBeenCalledWith(error); + }); + + it('should not call handleError if defaultHandling is disabled', () => { + interceptor.handleErrorResponse(error, false); + + expect(interceptor.handleError).not.toHaveBeenCalled(); + }); + }); + + describe('handleError', () => { + it('should open dialog on server error', () => { + const response: HttpErrorResponse = new HttpErrorResponse({ + error: createApiError(), + status: 500, + }); + const error = { response }; + interceptor.handleError(error); + + expect(dialogService.openApiErrorInfo).toHaveBeenCalledWith(response.error); + }); + + it('should logout on error 401', () => { + const response: HttpErrorResponse = new HttpErrorResponse({ + error: createApiError(), + status: HttpStatusCode.Unauthorized, + }); + const error = { response }; + + interceptor.handleError(error); + + expect(authService.logoutWithConfirmation).toHaveBeenCalled(); + }); + + it('should call handleForbiddenError on error 403', () => { + interceptor.handleForbiddenError = jest.fn(); + const response: HttpErrorResponse = new HttpErrorResponse({ + status: HttpStatusCode.Forbidden, + }); + const error = { response }; + + interceptor.handleError(error); + + expect(interceptor.handleForbiddenError).toHaveBeenCalled(); + }); + + describe('for forbidden, ', () => { + it('should NOT call snackbarService if already visible', () => { + snackbarService.isVisible.mockReturnValue(true); - beforeEach(() => { - interceptor = TestBed.inject(HttpErrorInterceptor); - }) + interceptor.handleForbiddenError(); - it('should be created', () => { - expect(interceptor).toBeTruthy(); - }); + expect(snackbarService.showError).not.toHaveBeenCalled(); + }); - describe('intercept', () => { + it('should call snackbarService if not visible', () => { + snackbarService.isVisible.mockReturnValue(false); - const response = new HttpErrorResponse({}); - const error = {response}; - const subject: Subject<any> = new Subject(); - const httpHandler = { handle: () => subject }; - const request: HttpRequest<unknown> = new HttpRequest('GET', '/test'); + interceptor.handleForbiddenError(); - it('should call http error handler', () => { - interceptor.handleErrorResponse = jest.fn(); + expect(snackbarService.showError).toHaveBeenCalledWith(Messages.HTTP_STATUS_FORBIDDEN); + }); + }); + }); - interceptor.intercept(request, <any>httpHandler).subscribe(); - subject.error(error); + describe('handleUnauthorizedError', () => { + it('should call authService.logOut', () => { + interceptor.handleUnauthorizedError(); - expect(httpErrorHandler.shouldDoDefaultHandling).toHaveBeenCalled(); - }) - - it('should call handleErrorResponse with error', () => { - httpErrorHandler.shouldDoDefaultHandling.mockReturnValue(true); - interceptor.handleErrorResponse = jest.fn(); - - interceptor.intercept(request, <any>httpHandler).subscribe(); - subject.error(error); - - expect(interceptor.handleErrorResponse).toHaveBeenCalledWith({response}, true); - }) - }) - - describe('handleErrorResponse', () => { - - const response: HttpErrorResponse = new HttpErrorResponse({ error: createApiError(), status: 500 }); - const error = {response}; - - beforeEach(() => { - interceptor.handleError = jest.fn(); - }) - - it('should call handleError if defaultHandling is enabled', () => { - interceptor.handleErrorResponse(error, true); - - expect(interceptor.handleError).toHaveBeenCalledWith(error); - }) - - it('should not call handleError if defaultHandling is disabled', () => { - interceptor.handleErrorResponse(error, false); - - expect(interceptor.handleError).not.toHaveBeenCalled(); - }) - }) - - describe('handleError', () => { - - it('should open dialog on server error', () => { - const response: HttpErrorResponse = new HttpErrorResponse({ error: createApiError(), status: 500 }); - const error = {response}; - interceptor.handleError(error); - - expect(dialogService.openApiErrorInfo).toHaveBeenCalledWith(response.error); - }) - - it('should logout on error 401', () => { - const response: HttpErrorResponse = new HttpErrorResponse({ error: createApiError(), status: HttpStatusCode.Unauthorized }); - const error = {response}; - - interceptor.handleError(error); - - expect(authService.logoutWithConfirmation).toHaveBeenCalled(); - }) - - it('should call handleForbiddenError on error 403', () => { - interceptor.handleForbiddenError = jest.fn(); - const response: HttpErrorResponse = new HttpErrorResponse({ status: HttpStatusCode.Forbidden }); - const error = {response}; - - interceptor.handleError(error); - - expect(interceptor.handleForbiddenError).toHaveBeenCalled(); - }) - - describe('for forbidden, ',() => { - - it('should NOT call snackbarService if already visible', () => { - snackbarService.isVisible.mockReturnValue(true); - - interceptor.handleForbiddenError(); - - expect(snackbarService.showError).not.toHaveBeenCalled(); - }) - - it('should call snackbarService if not visible', () => { - snackbarService.isVisible.mockReturnValue(false); - - interceptor.handleForbiddenError(); - - expect(snackbarService.showError).toHaveBeenCalledWith(Messages.HTTP_STATUS_FORBIDDEN); - }) - }) - }) - - describe('handleUnauthorizedError', () => { - it('should call authService.logOut', () => { - interceptor.handleUnauthorizedError(); - - expect(authService.logoutWithConfirmation).toHaveBeenCalled(); - }) - }) -}); \ No newline at end of file + expect(authService.logoutWithConfirmation).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/interceptor/http-error.interceptor.ts b/alfa-client/libs/ui/src/lib/interceptor/http-error.interceptor.ts index fe01ef7125348978a1326a09ad8a53532ac81dba..1b97fc4a92675b57365dc4dd992ca6f1e548963c 100644 --- a/alfa-client/libs/ui/src/lib/interceptor/http-error.interceptor.ts +++ b/alfa-client/libs/ui/src/lib/interceptor/http-error.interceptor.ts @@ -21,74 +21,88 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http'; +import { + HttpErrorResponse, + HttpEvent, + HttpHandler, + HttpInterceptor, + HttpRequest, +} from '@angular/common/http'; import { Injectable } from '@angular/core'; import { AuthService } from '@alfa-client/app-shared'; -import { ApiError, HttpErrorHandler, isForbidden, isServerError, isUnauthorized } from '@alfa-client/tech-shared'; +import { + ApiError, + HttpErrorHandler, + isForbidden, + isServerError, + isUnauthorized, +} from '@alfa-client/tech-shared'; import { DialogService, Messages, SnackBarService } from 'libs/ui/src'; import { EMPTY, Observable, throwError } from 'rxjs'; import { catchError, finalize } from 'rxjs/operators'; @Injectable() export class HttpErrorInterceptor implements HttpInterceptor { + constructor( + private dialogService: DialogService, + private snackbarService: SnackBarService, + private errorHandler: HttpErrorHandler, + private authService: AuthService, + ) {} - constructor( - private dialogService: DialogService, - private snackbarService: SnackBarService, - private errorHandler: HttpErrorHandler, - private authService: AuthService - ) { } + public intercept( + request: HttpRequest<unknown>, + next: HttpHandler, + ): Observable<HttpEvent<unknown>> { + const defaultHandling: boolean = this.errorHandler.shouldDoDefaultHandling(); + return next.handle(request).pipe( + catchError((error: any) => this.handleErrorResponse(error, defaultHandling)), + finalize(() => this.errorHandler.enableDefaultHandling()), + ); + } - public intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { - const defaultHandling: boolean = this.errorHandler.shouldDoDefaultHandling(); - return next.handle(request).pipe( - catchError((error: any) => this.handleErrorResponse(error, defaultHandling)), - finalize(() => this.errorHandler.enableDefaultHandling()) - ); - } + handleErrorResponse(error: any, defaultHandling: boolean): Observable<any> { + if (defaultHandling && this.hasResponse(error)) { + return this.handleError(error); + } - handleErrorResponse(error: any, defaultHandling: boolean): Observable<any> { - if (defaultHandling && this.hasResponse(error)) { - return this.handleError(error); - } + return throwError({ error: error.response }); + } - return throwError({ error: error.response }); - } + //TODO: Add test for return value + handleError(error: any): Observable<any> { + const errorResponse: HttpErrorResponse = error.response; - //TODO: Add test for return value - handleError(error: any): Observable<any> { - const errorResponse: HttpErrorResponse = error.response; + if (isServerError(errorResponse.status)) { + this.handleServerError(errorResponse.error); + return EMPTY; + } + if (isUnauthorized(errorResponse.status)) { + this.handleUnauthorizedError(); + return EMPTY; + } + if (isForbidden(errorResponse.status)) { + this.handleForbiddenError(); + // return EMPTY; + } + return throwError({ error: errorResponse }); + } - if (isServerError(errorResponse.status)) { - this.handleServerError(errorResponse.error); - return EMPTY; - } - if (isUnauthorized(errorResponse.status)) { - this.handleUnauthorizedError(); - return EMPTY; - } - if (isForbidden(errorResponse.status)) { - this.handleForbiddenError(); - // return EMPTY; - } - return throwError({ error: errorResponse }); - } + private handleServerError(error: ApiError): void { + this.dialogService.openApiErrorInfo(error); + } - private handleServerError(error: ApiError): void { - this.dialogService.openApiErrorInfo(error); - } + handleUnauthorizedError(): void { + this.authService.logoutWithConfirmation(); + } - handleUnauthorizedError(): void { - this.authService.logoutWithConfirmation(); - } + handleForbiddenError(): void { + if (!this.snackbarService.isVisible()) { + this.snackbarService.showError(Messages.HTTP_STATUS_FORBIDDEN); + } + } - handleForbiddenError(): void { - if(!this.snackbarService.isVisible()){ - this.snackbarService.showError(Messages.HTTP_STATUS_FORBIDDEN); - } - } - - private hasResponse(error: any): boolean { - return error.hasOwnProperty('response'); - } + private hasResponse(error: any): boolean { + return error.hasOwnProperty('response'); + } } diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.html b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.html index 884a13e5abff08fbf6a235d3ea2a9be5b7c33e44..b637a545cb261c839ad04702390edd617a1446ac 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.html +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.html @@ -24,5 +24,5 @@ --> <button mat-icon-button (click)="close.emit()" data-test-id="snackbar-close-button"> - <mat-icon data-test-class="icon">clear</mat-icon> -</button> \ No newline at end of file + <mat-icon data-test-class="icon">clear</mat-icon> +</button> diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.scss b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.scss index 9a97723219a6d633dc7bba4c8cfc0531941fd209..9048136e51a60b04ddedda4ef0c4369b2579ee40 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.scss +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.scss @@ -26,11 +26,11 @@ @import 'variables'; :host { - height: 24px; + height: 24px; } .mat-mdc-icon-button.mat-mdc-button-base { - width: 24px; - height: 24px; - padding: 0; + width: 24px; + height: 24px; + padding: 0; } diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts index 2a2fdd4fe342c15aa5dd96a6a5c1c60f97f89d0a..82b41397c33bd9df3eca6f4588f24be53a0bd405 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.spec.ts @@ -29,34 +29,31 @@ import { EventEmitter } from 'stream'; import { SnackbarCloseButtonComponent } from './snackbar-close-button.component'; describe('SnackbarCloseButtonComponent', () => { - let component: SnackbarCloseButtonComponent; - let fixture: ComponentFixture<SnackbarCloseButtonComponent>; + let component: SnackbarCloseButtonComponent; + let fixture: ComponentFixture<SnackbarCloseButtonComponent>; - const closeButton: string = getDataTestIdOf('snackbar-close-button'); + const closeButton: string = getDataTestIdOf('snackbar-close-button'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MatIcon, - SnackbarCloseButtonComponent - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [MatIcon, SnackbarCloseButtonComponent], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(SnackbarCloseButtonComponent); - component = fixture.componentInstance; - component.close = { ...<any>mock(EventEmitter), emit: jest.fn() }; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(SnackbarCloseButtonComponent); + component = fixture.componentInstance; + component.close = { ...(<any>mock(EventEmitter)), emit: jest.fn() }; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('click should emit action', () => { - dispatchEventFromFixture(fixture, closeButton, 'click'); + it('click should emit action', () => { + dispatchEventFromFixture(fixture, closeButton, 'click'); - expect(component.close.emit).toHaveBeenCalled(); - }) + expect(component.close.emit).toHaveBeenCalled(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts index 433f320a8b966c7b7d727a5ea4ab6e22312c5821..f395f4d1fb20df44101978bd7754fa8a5cf43af3 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-close-button/snackbar-close-button.component.ts @@ -24,11 +24,10 @@ import { Component, EventEmitter, Output } from '@angular/core'; @Component({ - selector: 'ozgcloud-snackbar-close-button', - templateUrl: './snackbar-close-button.component.html', - styleUrls: ['./snackbar-close-button.component.scss'] + selector: 'ozgcloud-snackbar-close-button', + templateUrl: './snackbar-close-button.component.html', + styleUrls: ['./snackbar-close-button.component.scss'], }) export class SnackbarCloseButtonComponent { - - @Output() close: EventEmitter<void> = new EventEmitter(); + @Output() close: EventEmitter<void> = new EventEmitter(); } diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.html b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.html index c40c7e851234474b13808b0d24040ddfa7f8d9c2..21eacea61d3461c4678e9f24c64761935f5d5fc8 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.html +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.html @@ -23,6 +23,8 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<div data-test-id="snackbar-message" class="message">{{ message }}</div> +<div data-test-id="snackbar-message" class="message"> + {{ message }} +</div> <ozgcloud-snackbar-close-button (close)="close()"></ozgcloud-snackbar-close-button> diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.scss b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.scss index 8e3d25d7a59ec997571f367ee0e333f8192c7d35..7302d092254da36ff20bb480e0d612e32b30170c 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.scss +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.scss @@ -22,11 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .message { - white-space: pre-wrap + white-space: pre-wrap; } :host { - display: flex; - align-items: center; - justify-content: space-between; + display: flex; + align-items: center; + justify-content: space-between; } diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts index 089f49b7b3d7c7ebb29972f0983f3fb4d8c939c0..eb3102e07b3831d0132cde436e55ea28bb8bf36c 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts @@ -31,49 +31,44 @@ import { SnackBarData } from '../snackbar.model'; import { SnackbarErrorComponent } from './snackbar-error.component'; describe('SnackbarErrorComponent', () => { - let component: SnackbarErrorComponent; - let fixture: ComponentFixture<SnackbarErrorComponent>; + let component: SnackbarErrorComponent; + let fixture: ComponentFixture<SnackbarErrorComponent>; - const snackBarData: SnackBarData = { message: 'Message' }; - const snackBarRef = { ...mock(MatSnackBarRef), dissmis: jest.fn(), dismissWithAction: jest.fn() }; + const snackBarData: SnackBarData = { message: 'Message' }; + const snackBarRef = { ...mock(MatSnackBarRef), dissmis: jest.fn(), dismissWithAction: jest.fn() }; - beforeEach(async () => { - TestBed.configureTestingModule({ - imports: [ - MatIconModule - ], - declarations: [ - SnackbarErrorComponent, - MockComponent(SnackbarCloseButtonComponent) - ], - providers: [ - { - provide: MAT_SNACK_BAR_DATA, - useValue: { data: snackBarData } - }, - { - provide: MatSnackBarRef, - useValue: snackBarRef - } - ] - }).compileComponents(); - }); + beforeEach(async () => { + TestBed.configureTestingModule({ + imports: [MatIconModule], + declarations: [SnackbarErrorComponent, MockComponent(SnackbarCloseButtonComponent)], + providers: [ + { + provide: MAT_SNACK_BAR_DATA, + useValue: { data: snackBarData }, + }, + { + provide: MatSnackBarRef, + useValue: snackBarRef, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(SnackbarErrorComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(SnackbarErrorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('close button', () => { - it('should close the snackbar', () => { - component.close(); + describe('close button', () => { + it('should close the snackbar', () => { + component.close(); - expect(snackBarRef.dismiss).toHaveBeenCalled(); - }) - }) + expect(snackBarRef.dismiss).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts index 5c8770b7367a506f0324e21a8fcdced8ee2932e8..9511bd6fa352bea5a6fec69467dddeb857691635 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts @@ -26,22 +26,21 @@ import { MAT_SNACK_BAR_DATA, MatSnackBarRef } from '@angular/material/snack-bar' import { SnackBarData } from '../snackbar.model'; @Component({ - selector: 'ozgcloud-snackbar-error', - templateUrl: './snackbar-error.component.html', - styleUrls: ['./snackbar-error.component.scss'] + selector: 'ozgcloud-snackbar-error', + templateUrl: './snackbar-error.component.html', + styleUrls: ['./snackbar-error.component.scss'], }) export class SnackbarErrorComponent { + constructor( + @Inject(MAT_SNACK_BAR_DATA) public data: SnackBarData, + public snackBarRef: MatSnackBarRef<SnackbarErrorComponent>, + ) {} - constructor( - @Inject(MAT_SNACK_BAR_DATA) public data: SnackBarData, - public snackBarRef: MatSnackBarRef<SnackbarErrorComponent>, - ) { } + get message(): string { + return this.data.message; + } - get message(): string { - return this.data.message; - } - - close(): void { - this.snackBarRef.dismiss(); - } + close(): void { + this.snackBarRef.dismiss(); + } } diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html index d5d894573d947f46d111503a974ee65a3824ed03..0d7405f83f569d12be20f77c677440ad573d3acc 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.html @@ -25,11 +25,14 @@ --> <div data-test-id="snackbar-message">{{ message }}</div> -<button *ngIf="showRevokeButton()" data-test-id="snackbar-revoke-button" - mat-button - color="primary" - (click)="revoke()"> - Rückgängig +<button + *ngIf="showRevokeButton()" + data-test-id="snackbar-revoke-button" + mat-button + color="primary" + (click)="revoke()" +> + Rückgängig </button> -<ozgcloud-snackbar-close-button (close)="close()"></ozgcloud-snackbar-close-button> \ No newline at end of file +<ozgcloud-snackbar-close-button (close)="close()"></ozgcloud-snackbar-close-button> diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.scss b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.scss index e48375ba020059e5d93760c965e90862d788376d..afca9000ddc699cecf83a9bc69079daa1d8000df 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.scss +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.scss @@ -22,7 +22,7 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - align-items: center; - justify-content: space-between; -} \ No newline at end of file + display: flex; + align-items: center; + justify-content: space-between; +} diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts index a90d25144f5d5bf0aa10e56d97f908fafd0841fd..485b0e25d802ac31a22fdde7aab1baf88f5be074 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts @@ -34,78 +34,78 @@ import { SnackBarData } from '../snackbar.model'; import { SnackbarInfoComponent } from './snackbar-info.component'; describe('SnackbarInfoComponent', () => { - let component: SnackbarInfoComponent; - let fixture: ComponentFixture<SnackbarInfoComponent>; - - const snackBarData: SnackBarData = { message: 'Message', commandResource: createCommandResource() }; - const snackBarRef = { ...mock(MatSnackBarRef), dissmis: jest.fn(), dismissWithAction: jest.fn() }; - - const revokeButton: string = getDataTestIdOf('snackbar-revoke-button'); - - beforeEach(async () => { - TestBed.configureTestingModule({ - imports: [ - MatSnackBarModule, - MatIconModule - ], - declarations: [ - SnackbarInfoComponent, - MockComponent(SnackbarCloseButtonComponent) - ], - providers: [ - { - provide: MAT_SNACK_BAR_DATA, - useValue: { data: snackBarData } - }, - { - provide: MatSnackBarRef, - useValue: snackBarRef - } - ] - }) - }); - - beforeEach(() => { - fixture = TestBed.createComponent(SnackbarInfoComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('close button', () => { - it('should close the snackbar', () => { - component.close(); - - expect(snackBarRef.dismiss).toHaveBeenCalled(); - }) - }) - - describe('revoke button', () => { - it('should be visible', () => { - component.data = { message: 'Message', commandResource: createCommandResource([CommandLinkRel.REVOKE]) }; - - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(revokeButton); - - expect(button).toBeInstanceOf(HTMLElement); - }) - - it('should be hidden', () => { - component.data = { message: 'Message', commandResource: createCommandResource() }; - - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(revokeButton); - - expect(button).not.toBeInstanceOf(HTMLElement); - }) - - it('should close the snackbar with action', () => { - component.revoke(); - - expect(snackBarRef.dismissWithAction).toHaveBeenCalled(); - }) - }) + let component: SnackbarInfoComponent; + let fixture: ComponentFixture<SnackbarInfoComponent>; + + const snackBarData: SnackBarData = { + message: 'Message', + commandResource: createCommandResource(), + }; + const snackBarRef = { ...mock(MatSnackBarRef), dissmis: jest.fn(), dismissWithAction: jest.fn() }; + + const revokeButton: string = getDataTestIdOf('snackbar-revoke-button'); + + beforeEach(async () => { + TestBed.configureTestingModule({ + imports: [MatSnackBarModule, MatIconModule], + declarations: [SnackbarInfoComponent, MockComponent(SnackbarCloseButtonComponent)], + providers: [ + { + provide: MAT_SNACK_BAR_DATA, + useValue: { data: snackBarData }, + }, + { + provide: MatSnackBarRef, + useValue: snackBarRef, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(SnackbarInfoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('close button', () => { + it('should close the snackbar', () => { + component.close(); + + expect(snackBarRef.dismiss).toHaveBeenCalled(); + }); + }); + + describe('revoke button', () => { + it('should be visible', () => { + component.data = { + message: 'Message', + commandResource: createCommandResource([CommandLinkRel.REVOKE]), + }; + + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(revokeButton); + + expect(button).toBeInstanceOf(HTMLElement); + }); + + it('should be hidden', () => { + component.data = { message: 'Message', commandResource: createCommandResource() }; + + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(revokeButton); + + expect(button).not.toBeInstanceOf(HTMLElement); + }); + + it('should close the snackbar with action', () => { + component.revoke(); + + expect(snackBarRef.dismissWithAction).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts index 083ff10b1249dd8bcce98b2633dc9a22912af477..676fb8d8d4a28055570e6da1f1f86dd534e3b681 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts @@ -28,34 +28,33 @@ import { isUndefined } from 'lodash-es'; import { SnackBarData } from '../snackbar.model'; @Component({ - selector: 'ozgcloud-snackbar-info', - templateUrl: './snackbar-info.component.html', - styleUrls: ['./snackbar-info.component.scss'] + selector: 'ozgcloud-snackbar-info', + templateUrl: './snackbar-info.component.html', + styleUrls: ['./snackbar-info.component.scss'], }) export class SnackbarInfoComponent { + constructor( + @Inject(MAT_SNACK_BAR_DATA) public data: SnackBarData, + public snackBarRef: MatSnackBarRef<SnackbarInfoComponent>, + ) {} - constructor( - @Inject(MAT_SNACK_BAR_DATA) public data: SnackBarData, - public snackBarRef: MatSnackBarRef<SnackbarInfoComponent>, - ) { } + get message(): string { + return this.data.message; + } - get message(): string { - return this.data.message; - } + showRevokeButton(): boolean { + if (isUndefined(this.data.commandResource)) { + return false; + } else { + return isRevokeable(this.data.commandResource); + } + } - showRevokeButton(): boolean { - if (isUndefined(this.data.commandResource)) { - return false; - } else { - return isRevokeable(this.data.commandResource); - } - } + revoke(): void { + this.snackBarRef.dismissWithAction(); + } - revoke(): void { - this.snackBarRef.dismissWithAction(); - } - - close(): void { - this.snackBarRef.dismiss(); - } -} \ No newline at end of file + close(): void { + this.snackBarRef.dismiss(); + } +} diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar.model.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar.model.ts index 68eb9a7154f9ca6df96b97b0e03d654edc788004..ce22fbd5e7107402df424d6c69f024057bb9ac19 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar.model.ts +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar.model.ts @@ -1,6 +1,6 @@ import { CommandResource } from '@alfa-client/command-shared'; export interface SnackBarData { - message: string, - commandResource?: CommandResource + message: string; + commandResource?: CommandResource; } diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts index 475354518325999e4c38bb5b0efc66df1e15ca56..bfbd86b6a9fe6d3b368d9acd234bbd0ff0ba18da 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts @@ -33,188 +33,184 @@ import { SnackbarInfoComponent } from './snackbar-info/snackbar-info.component'; import { SnackBarService } from './snackbar.service'; describe('SnackBarService', () => { - let service: SnackBarService; - let matSnackBar: MatSnackBar; + let service: SnackBarService; + let matSnackBar: MatSnackBar; + + const mockMatSnackBar = { + openFromComponent: jest.fn(), + }; + + const commandResource: CommandResource = createCommandResource(); + const message: string = faker.lorem.words(5); + + beforeEach(async () => { + TestBed.configureTestingModule({ + providers: [{ provide: MatSnackBar, useValue: mockMatSnackBar }], + }).compileComponents(); + service = TestBed.inject(SnackBarService); + matSnackBar = TestBed.inject(MatSnackBar); + }); + + it('should create', () => { + expect(service).toBeDefined(); + }); + + describe('show', () => { + beforeEach(() => { + service.listenOnRevokeAction = jest.fn(); + service.listenOnAfterDismissed = jest.fn(); + service.closeSnackBarIfVisible = jest.fn(); + }); + + it('should close snackbar if exists', () => { + service.show(commandResource, message); + + expect(service.closeSnackBarIfVisible).toHaveBeenCalled(); + }); - const mockMatSnackBar = { - openFromComponent: jest.fn() - }; + it('should open from component', () => { + service.show(commandResource, message); - const commandResource: CommandResource = createCommandResource(); - const message: string = faker.lorem.words(5); + expect(matSnackBar.openFromComponent).toHaveBeenCalledWith(SnackbarInfoComponent, { + data: { message, commandResource }, + duration: 10000, + }); + }); - beforeEach(async () => { - TestBed.configureTestingModule({ - providers: [ - { provide: MatSnackBar, useValue: mockMatSnackBar }, - ], - }).compileComponents(); - service = TestBed.inject(SnackBarService); - matSnackBar = TestBed.inject(MatSnackBar); - }); + it('should listen to snackbar revoke action', () => { + service.show(commandResource, message, null); - it('should create', () => { - expect(service).toBeDefined(); - }) + expect(service.listenOnRevokeAction).toHaveBeenCalledWith(null); + }); - describe('show', () => { + it('should listen to snackbar after dismissed', () => { + service.show(commandResource, message, null); - beforeEach(() => { - service.listenOnRevokeAction = jest.fn(); - service.listenOnAfterDismissed = jest.fn(); - service.closeSnackBarIfVisible = jest.fn(); - }) + expect(service.listenOnAfterDismissed).toHaveBeenCalled(); + }); - it('should close snackbar if exists', () => { - service.show(commandResource, message); + it('should open error snackbar when status is ERROR', () => { + const commandWithError = { ...commandResource, status: CommandStatus.ERROR }; + service.show(commandWithError, message, null); - expect(service.closeSnackBarIfVisible).toHaveBeenCalled(); - }) + expect(matSnackBar.openFromComponent).toHaveBeenCalledWith(SnackbarErrorComponent, { + data: { message }, + duration: 10000, + panelClass: 'error', + }); + }); + }); - it('should open from component', () => { - service.show(commandResource, message); + describe('show error', () => { + beforeEach(() => { + service.listenOnAfterDismissed = jest.fn(); + service.closeSnackBarIfVisible = jest.fn(); + }); - expect(matSnackBar.openFromComponent).toHaveBeenCalledWith(SnackbarInfoComponent, { - data: { message, commandResource }, duration: 10000 - }); - }) + it('should close snackbar if exists', () => { + service.showError(message); - it('should listen to snackbar revoke action', () => { - service.show(commandResource, message, null); + expect(service.closeSnackBarIfVisible).toHaveBeenCalled(); + }); - expect(service.listenOnRevokeAction).toHaveBeenCalledWith(null); - }) + it('should open from component', () => { + service.showError(message); - it('should listen to snackbar after dismissed', () => { - service.show(commandResource, message, null); + expect(matSnackBar.openFromComponent).toHaveBeenCalledWith(SnackbarErrorComponent, { + data: { message }, + duration: 10000, + panelClass: 'error', + }); + }); - expect(service.listenOnAfterDismissed).toHaveBeenCalled(); - }) + it('should listen to snackbar after dismissed', () => { + service.showError(message); - it('should open error snackbar when status is ERROR', () => { - const commandWithError = { ...commandResource, status: CommandStatus.ERROR } - service.show(commandWithError, message, null); + expect(service.listenOnAfterDismissed).toHaveBeenCalled(); + }); + }); - expect(matSnackBar.openFromComponent).toHaveBeenCalledWith(SnackbarErrorComponent, { - data: { message }, duration: 10000, panelClass: 'error' - }); - }); - }) + describe('show info', () => { + beforeEach(() => { + service.listenOnAfterDismissed = jest.fn(); + service.closeSnackBarIfVisible = jest.fn(); + }); - describe('show error', () => { + it('should close snackbar if exists', () => { + service.showInfo(message); - beforeEach(() => { - service.listenOnAfterDismissed = jest.fn(); - service.closeSnackBarIfVisible = jest.fn(); - }) + expect(service.closeSnackBarIfVisible).toHaveBeenCalled(); + }); - it('should close snackbar if exists', () => { - service.showError(message); + it('should open from component', () => { + service.showInfo(message); - expect(service.closeSnackBarIfVisible).toHaveBeenCalled(); - }) + const config: MatSnackBarConfig = { data: { message }, duration: 10000 }; + expect(matSnackBar.openFromComponent).toHaveBeenCalledWith(SnackbarInfoComponent, config); + }); + it('should listen to snackbar after dismissed', () => { + service.showInfo(message); - it('should open from component', () => { - service.showError(message); + expect(service.listenOnAfterDismissed).toHaveBeenCalled(); + }); + }); - expect(matSnackBar.openFromComponent).toHaveBeenCalledWith(SnackbarErrorComponent, { - data: { message }, duration: 10000, panelClass: 'error' - }); - }) + describe('close snackbar if visible', () => { + beforeEach(() => { + service.closeSnackBar = jest.fn(); + }); - it('should listen to snackbar after dismissed', () => { - service.showError(message); + it('should dismiss snack bar if ref exists ', () => { + service.snackBarRef = <any>{}; - expect(service.listenOnAfterDismissed).toHaveBeenCalled(); - }) - }) + service.closeSnackBarIfVisible(); - describe('show info', () => { + expect(service.closeSnackBar).toHaveBeenCalled(); + }); - beforeEach(() => { - service.listenOnAfterDismissed = jest.fn(); - service.closeSnackBarIfVisible = jest.fn(); - }) + it('should do nothing if ref not exists ', () => { + service.snackBarRef = undefined; - it('should close snackbar if exists', () => { - service.showInfo(message); + service.closeSnackBarIfVisible(); - expect(service.closeSnackBarIfVisible).toHaveBeenCalled(); - }) + expect(service.closeSnackBar).not.toHaveBeenCalled(); + }); + }); - it('should open from component', () => { - service.showInfo(message); + describe('isVisible', () => { + it('should return true if snackBarRef is not undefined', () => { + service.snackBarRef = undefined; - const config: MatSnackBarConfig = { data: { message }, duration: 10000 }; - expect(matSnackBar.openFromComponent).toHaveBeenCalledWith(SnackbarInfoComponent, config); - }) + const isVisible: boolean = service.isVisible(); - it('should listen to snackbar after dismissed', () => { - service.showInfo(message); + expect(isVisible).toBeFalsy(); + }); - expect(service.listenOnAfterDismissed).toHaveBeenCalled(); - }) - }) + it('should return false if snackBarRef is defined', () => { + service.snackBarRef = useFromMock(mock(MatSnackBarRef<SnackbarInfoComponent>)); - describe('close snackbar if visible', () => { + const isVisible: boolean = service.isVisible(); - beforeEach(() => { - service.closeSnackBar = jest.fn(); - }) + expect(isVisible).toBeTruthy(); + }); + }); - it('should dismiss snack bar if ref exists ', () => { - service.snackBarRef = <any>{}; + describe('isNotVisible', () => { + it('should return false if snackBarRef is not undefined', () => { + service.snackBarRef = undefined; - service.closeSnackBarIfVisible(); + const isVisible: boolean = service.isNotVisible(); - expect(service.closeSnackBar).toHaveBeenCalled(); - }) + expect(isVisible).toBeTruthy(); + }); - it('should do nothing if ref not exists ', () => { - service.snackBarRef = undefined; + it('should return true if snackBarRef is defined', () => { + service.snackBarRef = useFromMock(mock(MatSnackBarRef<SnackbarInfoComponent>)); - service.closeSnackBarIfVisible(); + const isVisible: boolean = service.isNotVisible(); - expect(service.closeSnackBar).not.toHaveBeenCalled(); - }) - }) - - describe('isVisible', () => { - - it('should return true if snackBarRef is not undefined', () => { - service.snackBarRef = undefined; - - const isVisible: boolean = service.isVisible(); - - expect(isVisible).toBeFalsy(); - }) - - it('should return false if snackBarRef is defined', () => { - service.snackBarRef = useFromMock(mock(MatSnackBarRef<SnackbarInfoComponent>)); - - const isVisible: boolean = service.isVisible(); - - expect(isVisible).toBeTruthy(); - }) - }) - - describe('isNotVisible', () => { - - it('should return false if snackBarRef is not undefined', () => { - service.snackBarRef = undefined; - - const isVisible: boolean = service.isNotVisible(); - - expect(isVisible).toBeTruthy(); - }) - - it('should return true if snackBarRef is defined', () => { - service.snackBarRef = useFromMock(mock(MatSnackBarRef<SnackbarInfoComponent>)); - - const isVisible: boolean = service.isNotVisible(); - - expect(isVisible).toBeFalsy(); - }) - }) -}) + expect(isVisible).toBeFalsy(); + }); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.ts b/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.ts index 258e6fac5c340f99d063e9593850155e55e39fac..a990a6183a8b98eae688e07e06d0aa19accf12df 100644 --- a/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.ts +++ b/alfa-client/libs/ui/src/lib/snackbar/snackbar.service.ts @@ -33,73 +33,80 @@ import { SnackbarInfoComponent } from './snackbar-info/snackbar-info.component'; @Injectable({ providedIn: 'root' }) export class SnackBarService { - - private subscription: Subscription; - - snackBarRef: MatSnackBarRef<SnackbarInfoComponent | SnackbarErrorComponent>; - - private durationTime: number = 10000; - - constructor(private snackBar: MatSnackBar) { } - - public show(commandResource: CommandResource, message: string, revokeAction?: () => void): void { - if (commandResource.status === CommandStatus.ERROR) { - this.showError(message); - } else { - this.openFromComponent(SnackbarInfoComponent, { data: { message, commandResource } }); - } - this.handleRevokeAction(revokeAction); - } - - private handleRevokeAction(revokeAction?: () => void): void { - if (isNotUndefined(revokeAction)) { - this.listenOnRevokeAction(revokeAction); - } - } - - public showError(message: string): void { - this.openFromComponent(SnackbarErrorComponent, { data: { message }, panelClass: 'error' }); - } - - public showInfo(message: string): void { - this.openFromComponent(SnackbarInfoComponent, { data: { message }}); - } - - private openFromComponent(component: ComponentType<SnackbarInfoComponent | SnackbarErrorComponent>, config: MatSnackBarConfig): void { - this.closeSnackBarIfVisible(); - this.snackBarRef = this.snackBar.openFromComponent(component, { ...config, duration: this.durationTime }); - this.listenOnAfterDismissed(); - } - - public isVisible(): boolean { - return isNotUndefined(this.snackBarRef); - } - - public isNotVisible(): boolean { - return isUndefined(this.snackBarRef); - } - - closeSnackBarIfVisible(): void { - if (isNotUndefined(this.snackBarRef)) this.closeSnackBar(); - } - - listenOnRevokeAction(revokeAction: () => void): void { - this.subscription.add(this.snackBarRef.onAction().subscribe(() => { - revokeAction(); - this.closeSnackBar(); - })); - } - - listenOnAfterDismissed(): void { - this.subscription = this.snackBarRef.afterDismissed().subscribe(() => this.closeSnackBar()); - } - - closeSnackBar(): void { - this.snackBarRef.dismiss(); - this.unsubscribe(); - } - - private unsubscribe(): void { - if (isNotUndefined(this.subscription)) this.subscription.unsubscribe(); - } -} \ No newline at end of file + private subscription: Subscription; + + snackBarRef: MatSnackBarRef<SnackbarInfoComponent | SnackbarErrorComponent>; + + private durationTime: number = 10000; + + constructor(private snackBar: MatSnackBar) {} + + public show(commandResource: CommandResource, message: string, revokeAction?: () => void): void { + if (commandResource.status === CommandStatus.ERROR) { + this.showError(message); + } else { + this.openFromComponent(SnackbarInfoComponent, { data: { message, commandResource } }); + } + this.handleRevokeAction(revokeAction); + } + + private handleRevokeAction(revokeAction?: () => void): void { + if (isNotUndefined(revokeAction)) { + this.listenOnRevokeAction(revokeAction); + } + } + + public showError(message: string): void { + this.openFromComponent(SnackbarErrorComponent, { data: { message }, panelClass: 'error' }); + } + + public showInfo(message: string): void { + this.openFromComponent(SnackbarInfoComponent, { data: { message } }); + } + + private openFromComponent( + component: ComponentType<SnackbarInfoComponent | SnackbarErrorComponent>, + config: MatSnackBarConfig, + ): void { + this.closeSnackBarIfVisible(); + this.snackBarRef = this.snackBar.openFromComponent(component, { + ...config, + duration: this.durationTime, + }); + this.listenOnAfterDismissed(); + } + + public isVisible(): boolean { + return isNotUndefined(this.snackBarRef); + } + + public isNotVisible(): boolean { + return isUndefined(this.snackBarRef); + } + + closeSnackBarIfVisible(): void { + if (isNotUndefined(this.snackBarRef)) this.closeSnackBar(); + } + + listenOnRevokeAction(revokeAction: () => void): void { + this.subscription.add( + this.snackBarRef.onAction().subscribe(() => { + revokeAction(); + this.closeSnackBar(); + }), + ); + } + + listenOnAfterDismissed(): void { + this.subscription = this.snackBarRef.afterDismissed().subscribe(() => this.closeSnackBar()); + } + + closeSnackBar(): void { + this.snackBarRef.dismiss(); + this.unsubscribe(); + } + + private unsubscribe(): void { + if (isNotUndefined(this.subscription)) this.subscription.unsubscribe(); + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.html b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.html index 26a3a7bbd09770b1e7c96a6225f52c23fcec0ee3..7fb641582e67db573b680cbe5ead9a58b2ef6991 100644 --- a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.html +++ b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.html @@ -24,5 +24,5 @@ --> <mat-accordion displayMode="flat" multi> - <ng-content></ng-content> -</mat-accordion> \ No newline at end of file + <ng-content></ng-content> +</mat-accordion> diff --git a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.scss b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.scss index 86e14516c34fa09bee546a46b3e3c69dd2ec0dbe..b2549633b88686c4759c7de5637702275ecff6e0 100644 --- a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.scss @@ -24,12 +24,12 @@ @import 'variables'; ul { - margin-top: 0; - padding-left: 0; - width: 100%; + margin-top: 0; + padding-left: 0; + width: 100%; - li { - border-bottom: 1px solid $greyLight; - padding: 0.75rem 0; - } -} \ No newline at end of file + li { + border-bottom: 1px solid $greyLight; + padding: 0.75rem 0; + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.spec.ts index 48b2d03b869cdb11be83ce7e98f668b139819c49..81bffb6716d20fa535b8a3fc31fb488a189661ad 100644 --- a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.spec.ts @@ -26,22 +26,22 @@ import { MatAccordion } from '@angular/material/expansion'; import { AccordionComponent } from './accordion.component'; describe('AccordionComponent', () => { - let component: AccordionComponent; - let fixture: ComponentFixture<AccordionComponent>; + let component: AccordionComponent; + let fixture: ComponentFixture<AccordionComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [AccordionComponent, MatAccordion], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [AccordionComponent, MatAccordion], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(AccordionComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(AccordionComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.ts b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.ts index 65349355f994ec36eac30ad6e874251a5b3d32d3..a35216a5e251ddd4fa6076c2e299aa7f7d6fa778 100644 --- a/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/accordion/accordion.component.ts @@ -24,11 +24,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-accordion', - templateUrl: './accordion.component.html', - styleUrls: ['./accordion.component.scss'], + selector: 'ozgcloud-accordion', + templateUrl: './accordion.component.html', + styleUrls: ['./accordion.component.scss'], }) export class AccordionComponent { - - @Input() multi: boolean = false; + @Input() multi: boolean = false; } diff --git a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.html b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.html index df0260a18c096ac54c3fbe71112e166984f2065b..802722b5b0dcd0c992eecdfe43ba128d8797589e 100644 --- a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.html +++ b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.html @@ -1,6 +1,10 @@ -<a [routerLink]="linkTo" mat-icon-button data-test-id="back-button" - class="back-button" - [attr.aria-label]="label" - [matTooltip]="label"> - <mat-icon>arrow_back</mat-icon> +<a + [routerLink]="linkTo" + mat-icon-button + data-test-id="back-button" + class="back-button" + [attr.aria-label]="label" + [matTooltip]="label" +> + <mat-icon>arrow_back</mat-icon> </a> diff --git a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.spec.ts index be3785413b857d9c89554b5d074e54dd45edd032..14637e0618c43f0124d8462b7e2a848fcb4375da 100644 --- a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.spec.ts @@ -8,88 +8,82 @@ import { MatTooltipDirective } from 'libs/ui/src/lib/ui/mattooltip/mattooltip.di import { BackButtonComponent } from './back-button.component'; describe('BackButtonComponent', () => { - let component: BackButtonComponent; - let fixture: ComponentFixture<BackButtonComponent>; + let component: BackButtonComponent; + let fixture: ComponentFixture<BackButtonComponent>; - const backButton: string = getDataTestIdOf('back-button'); - const linkToAsArray: string[] = [ faker.word.adverb(), faker.word.adverb() ]; - const linkToAsString: string = '/' + linkToAsArray.join('/'); + const backButton: string = getDataTestIdOf('back-button'); + const linkToAsArray: string[] = [faker.word.adverb(), faker.word.adverb()]; + const linkToAsString: string = '/' + linkToAsArray.join('/'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - BackButtonComponent, - MatIcon, - MatTooltipDirective, - ], - imports: [ - RouterTestingModule - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [BackButtonComponent, MatIcon, MatTooltipDirective], + imports: [RouterTestingModule], + }).compileComponents(); - fixture = TestBed.createComponent(BackButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(BackButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('label', () => { - beforeEach(() => { - component.label = faker.lorem.sentence(); - fixture.detectChanges(); - }) + describe('label', () => { + beforeEach(() => { + component.label = faker.lorem.sentence(); + fixture.detectChanges(); + }); - it('should set aria-label attribute', () => { - const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); + it('should set aria-label attribute', () => { + const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); - expect(backButtonElement).toHaveAttribute('aria-label', component.label); - }) + expect(backButtonElement).toHaveAttribute('aria-label', component.label); + }); - it('should set title attribute', () => { - const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); + it('should set title attribute', () => { + const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); - expect(backButtonElement).toHaveAttribute('title', component.label); - }) - }) + expect(backButtonElement).toHaveAttribute('title', component.label); + }); + }); - describe('linkTo', () => { - it('string path should set href attribute', () => { - component.linkTo = linkToAsString; - fixture.detectChanges(); + describe('linkTo', () => { + it('string path should set href attribute', () => { + component.linkTo = linkToAsString; + fixture.detectChanges(); - const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); + const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); - expect(backButtonElement).toHaveAttribute('href', component.linkTo); - }) + expect(backButtonElement).toHaveAttribute('href', component.linkTo); + }); - it('empty string path should set href attribute to base url', () => { - component.linkTo = ''; - fixture.detectChanges(); + it('empty string path should set href attribute to base url', () => { + component.linkTo = ''; + fixture.detectChanges(); - const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); + const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); - expect(backButtonElement).toHaveAttribute('href', '/'); - }) + expect(backButtonElement).toHaveAttribute('href', '/'); + }); - it('array path should set href attribute', () => { - component.linkTo = linkToAsArray; - fixture.detectChanges(); + it('array path should set href attribute', () => { + component.linkTo = linkToAsArray; + fixture.detectChanges(); - const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); + const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); - expect(backButtonElement).toHaveAttribute('href', linkToAsString); - }) + expect(backButtonElement).toHaveAttribute('href', linkToAsString); + }); - it('empty array path should href attribute to base url', () => { - component.linkTo = []; - fixture.detectChanges(); + it('empty array path should href attribute to base url', () => { + component.linkTo = []; + fixture.detectChanges(); - const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); + const backButtonElement: HTMLAnchorElement = getElementFromFixture(fixture, backButton); - expect(backButtonElement).toHaveAttribute('href', '/'); - }) - }) + expect(backButtonElement).toHaveAttribute('href', '/'); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.ts b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.ts index 6a1d338d5c114a8e072aec67ec524c73f33274c8..50ffa9ee13c42ae178694da0956d2591ee37925e 100644 --- a/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/back-button/back-button.component.ts @@ -1,13 +1,11 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-back-button', - templateUrl: './back-button.component.html', - styleUrls: ['./back-button.component.scss'], + selector: 'ozgcloud-back-button', + templateUrl: './back-button.component.html', + styleUrls: ['./back-button.component.scss'], }) export class BackButtonComponent { - - @Input() label: string; - @Input() linkTo: string | any[]; - + @Input() label: string; + @Input() linkTo: string | any[]; } diff --git a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog-data.model.ts b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog-data.model.ts index 1b8833cfb3d26293b201d88f3c1dad77770b734a..cd38153a161705b7c283c18baa1cd4ed4356b38e 100644 --- a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog-data.model.ts +++ b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog-data.model.ts @@ -1,6 +1,6 @@ export interface BasicDialogData { - title: string; - message: string; - okText: string; - okSvgIcon: string; -} \ No newline at end of file + title: string; + message: string; + okText: string; + okSvgIcon: string; +} diff --git a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.html b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.html index a90044aa60aa1d1710f461973d4b765892811016..84c8a2c09e52c4b3098ffa6335bae53ad2010698 100644 --- a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.html +++ b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.html @@ -1,19 +1,22 @@ -<h1 mat-dialog-title data-test-id="dialog-header">{{ data.title }}</h1> +<h1 mat-dialog-title data-test-id="dialog-header"> + {{ data.title }} +</h1> <div mat-dialog-content> - <p data-test-id="dialog-message">{{ data.message }}</p> + <p data-test-id="dialog-message">{{ data.message }}</p> </div> <div mat-dialog-actions> - <ozgcloud-stroked-button-with-spinner - dataTestId="dialog-confirmation-button" - [mat-dialog-close]="true" - svgIcon="{{ data.okSvgIcon }}" - text="{{ data.okText }}"> - </ozgcloud-stroked-button-with-spinner> + <ozgcloud-stroked-button-with-spinner + dataTestId="dialog-confirmation-button" + [mat-dialog-close]="true" + svgIcon="{{ data.okSvgIcon }}" + text="{{ data.okText }}" + > + </ozgcloud-stroked-button-with-spinner> - <ozgcloud-stroked-button-with-spinner - dataTestId="dialog-cancel-button" - (click)="onNoClick()" - text="Abbrechen"> - </ozgcloud-stroked-button-with-spinner> - -</div> \ No newline at end of file + <ozgcloud-stroked-button-with-spinner + dataTestId="dialog-cancel-button" + (click)="onNoClick()" + text="Abbrechen" + > + </ozgcloud-stroked-button-with-spinner> +</div> diff --git a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.scss b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.scss index 6cb84a4770ab1b41fe6e94d95e35091f5c9a5201..51b84d53b61eb690cbabea688c48e6a43dc95680 100644 --- a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.scss @@ -3,10 +3,11 @@ $primaryPalette: mat.define-palette(mat.$blue-palette, 800, 500, 900); -button, h1 { - color: mat.get-color-from-palette($primaryPalette); +button, +h1 { + color: mat.get-color-from-palette($primaryPalette); } ozgcloud-stroked-button-with-spinner { - margin-left: 1rem; -} \ No newline at end of file + margin-left: 1rem; +} diff --git a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.spec.ts index af919ee3a1831b31996e6414436964d1d89294b3..a4086d0e4487719245fa46e680bae676f02fb4a0 100644 --- a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.spec.ts @@ -1,53 +1,54 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog'; import { MatIcon } from '@angular/material/icon'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { MockComponent } from 'ng-mocks'; import { BasicDialogComponent } from './basic-dialog.component'; describe('BasicDialogComponent', () => { - let component: BasicDialogComponent; - let fixture: ComponentFixture<BasicDialogComponent>; + let component: BasicDialogComponent; + let fixture: ComponentFixture<BasicDialogComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - MatDialogModule - ], - declarations: [ - BasicDialogComponent, - MatIcon, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent), - ], - providers: [ - { - provide: MatDialogRef, - useValue: {} - }, - { - provide: MAT_DIALOG_DATA, - useValue: { } - } - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MatDialogModule], + declarations: [ + BasicDialogComponent, + MatIcon, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + providers: [ + { + provide: MatDialogRef, + useValue: {}, + }, + { + provide: MAT_DIALOG_DATA, + useValue: {}, + }, + ], + }).compileComponents(); - fixture = TestBed.createComponent(BasicDialogComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(BasicDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('onNoClick', () => { - it('should call dialogRef.close', () => { - component.dialogRef.close = jest.fn(); + describe('onNoClick', () => { + it('should call dialogRef.close', () => { + component.dialogRef.close = jest.fn(); - component.onNoClick(); + component.onNoClick(); - expect(component.dialogRef.close).toHaveBeenCalled(); - }) - }) + expect(component.dialogRef.close).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.ts b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.ts index 625b40e90374571ab8fab25fccf5b0db376d917b..012ebb35f07fa21e9cdef6150dd3e861fe145c57 100644 --- a/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/basic-dialog/basic-dialog.component.ts @@ -3,17 +3,17 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { BasicDialogData } from './basic-dialog-data.model'; @Component({ - selector: 'ozgcloud-basic-dialog', - templateUrl: './basic-dialog.component.html', - styleUrls: ['./basic-dialog.component.scss'], + selector: 'ozgcloud-basic-dialog', + templateUrl: './basic-dialog.component.html', + styleUrls: ['./basic-dialog.component.scss'], }) export class BasicDialogComponent { - constructor( - public dialogRef: MatDialogRef<BasicDialogComponent>, - @Inject(MAT_DIALOG_DATA) public data: BasicDialogData, - ) {} + constructor( + public dialogRef: MatDialogRef<BasicDialogComponent>, + @Inject(MAT_DIALOG_DATA) public data: BasicDialogData, + ) {} - onNoClick(): void { - this.dialogRef.close(); - } + onNoClick(): void { + this.dialogRef.close(); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.html b/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.html index b108642ab942a6ae6263981fac819588ad9116a5..68b79b7c386d6c3a92a3222437f99f681eddff4a 100644 --- a/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.html +++ b/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.html @@ -1,3 +1,3 @@ <mat-button-toggle-group #group="matButtonToggleGroup" name="groupOfButtonToggles" value="alle"> - <ng-content></ng-content> -</mat-button-toggle-group> \ No newline at end of file + <ng-content></ng-content> +</mat-button-toggle-group> diff --git a/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.spec.ts index 7c2d9f11bce84ad50025bc941829dbc26561f9e4..56a6c81bfa66f12105dbeebfb815c41ad5159037 100644 --- a/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.spec.ts @@ -3,23 +3,20 @@ import { MatButtonToggleGroup } from '@angular/material/button-toggle'; import { ButtonToggleGroupComponent } from './button-toggle-group.component'; describe('ButtonToggleGroupComponent', () => { - let component: ButtonToggleGroupComponent; - let fixture: ComponentFixture<ButtonToggleGroupComponent>; + let component: ButtonToggleGroupComponent; + let fixture: ComponentFixture<ButtonToggleGroupComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - ButtonToggleGroupComponent, - MatButtonToggleGroup - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ButtonToggleGroupComponent, MatButtonToggleGroup], + }).compileComponents(); - fixture = TestBed.createComponent(ButtonToggleGroupComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(ButtonToggleGroupComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.ts b/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.ts index de2c4eba10350ef8756ae32c32a4fa0da11d28f0..6619434fc208df22859b0f1e23f4b17f57a7a291 100644 --- a/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/button-toggle-group/button-toggle-group.component.ts @@ -1,26 +1,34 @@ -import { AfterContentInit, Component, ContentChildren, Input, QueryList, ViewChild } from '@angular/core'; +import { + AfterContentInit, + Component, + ContentChildren, + Input, + QueryList, + ViewChild, +} from '@angular/core'; import { MatButtonToggleGroup } from '@angular/material/button-toggle'; import { ButtonToggleComponent } from '../button-toggle/button-toggle.component'; @Component({ - selector: 'ozgcloud-button-toggle-group', - templateUrl: './button-toggle-group.component.html', - styleUrls: ['./button-toggle-group.component.scss'], + selector: 'ozgcloud-button-toggle-group', + templateUrl: './button-toggle-group.component.html', + styleUrls: ['./button-toggle-group.component.scss'], }) export class ButtonToggleGroupComponent implements AfterContentInit { + @Input() name: string; + @Input() default: string; - @Input() name: string; - @Input() default: string; + @ViewChild('group', { static: true }) buttonToggleGroup: MatButtonToggleGroup; - @ViewChild('group', { static: true }) buttonToggleGroup: MatButtonToggleGroup; + @ContentChildren(ButtonToggleComponent) componentAInstances: QueryList<ButtonToggleComponent>; - @ContentChildren(ButtonToggleComponent) componentAInstances: QueryList<ButtonToggleComponent>; + ngAfterContentInit(): void { + this.addButtonsToGroup(); + } - ngAfterContentInit(): void { - this.addButtonsToGroup(); - } - - addButtonsToGroup(): void { - this.componentAInstances.forEach(component => component.matButtonToggle.buttonToggleGroup = this.buttonToggleGroup); - } -} \ No newline at end of file + addButtonsToGroup(): void { + this.componentAInstances.forEach( + (component) => (component.matButtonToggle.buttonToggleGroup = this.buttonToggleGroup), + ); + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/button-toggle/_button-toogle.theme.scss b/alfa-client/libs/ui/src/lib/ui/button-toggle/_button-toogle.theme.scss index 7afd0fa5ce394316ad28695e578889a490b2293d..24882f2b5523fb6cdab480c1e15425f2272546c0 100644 --- a/alfa-client/libs/ui/src/lib/ui/button-toggle/_button-toogle.theme.scss +++ b/alfa-client/libs/ui/src/lib/ui/button-toggle/_button-toogle.theme.scss @@ -1,9 +1,9 @@ ozgcloud-button-toggle { - .mat-button-toggle-standalone.mat-button-toggle-appearance-standard, - .mat-button-toggle-appearance-standard { - border-radius: 20px; - .mat-button-toggle-label-content { - line-height: 2rem; - } - } + .mat-button-toggle-standalone.mat-button-toggle-appearance-standard, + .mat-button-toggle-appearance-standard { + border-radius: 20px; + .mat-button-toggle-label-content { + line-height: 2rem; + } + } } diff --git a/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.html b/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.html index 00658e849ab981333a09f83b9fca3e7777946aed..76ed2304e23b54997a856e8d4e3396ae4172437c 100644 --- a/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.html +++ b/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.html @@ -1,3 +1,3 @@ <mat-button-toggle [value]="value" #buttonToggle="matButtonToggle"> - <ng-content></ng-content> -</mat-button-toggle> \ No newline at end of file + <ng-content></ng-content> +</mat-button-toggle> diff --git a/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.spec.ts index 2e4d6552ebbcb4616ffcfffa943c6ee4b0b5e2be..e8c3d744fbee497f9819c5d46519d630111e8778 100644 --- a/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.spec.ts @@ -4,24 +4,20 @@ import { MatRipple } from '@angular/material/core'; import { ButtonToggleComponent } from './button-toggle.component'; describe('ButtonToggleComponent', () => { - let component: ButtonToggleComponent; - let fixture: ComponentFixture<ButtonToggleComponent>; + let component: ButtonToggleComponent; + let fixture: ComponentFixture<ButtonToggleComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - ButtonToggleComponent, - MatButtonToggle, - MatRipple - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ButtonToggleComponent, MatButtonToggle, MatRipple], + }).compileComponents(); - fixture = TestBed.createComponent(ButtonToggleComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(ButtonToggleComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.ts b/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.ts index 136adf953ae31184212ecef6b87febb5f0e433b7..9d8b7710e13eb279e87ab8cfc3e156f936cbcbe0 100644 --- a/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/button-toggle/button-toggle.component.ts @@ -2,18 +2,17 @@ import { Component, Input, OnInit, ViewChild } from '@angular/core'; import { MatButtonToggle, MatButtonToggleGroup } from '@angular/material/button-toggle'; @Component({ - selector: 'ozgcloud-button-toggle', - templateUrl: './button-toggle.component.html', - styleUrls: ['./button-toggle.component.scss'], + selector: 'ozgcloud-button-toggle', + templateUrl: './button-toggle.component.html', + styleUrls: ['./button-toggle.component.scss'], }) export class ButtonToggleComponent implements OnInit { + @Input() value: string; + @Input() buttonToggleGroup: MatButtonToggleGroup; - @Input() value: string; - @Input() buttonToggleGroup: MatButtonToggleGroup; + @ViewChild('buttonToggle', { static: true }) matButtonToggle: MatButtonToggle; - @ViewChild('buttonToggle', { static: true }) matButtonToggle: MatButtonToggle; - - ngOnInit(): void { - this.matButtonToggle.buttonToggleGroup = this.buttonToggleGroup; - } + ngOnInit(): void { + this.matButtonToggle.buttonToggleGroup = this.buttonToggleGroup; + } } diff --git a/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.spec.ts b/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.spec.ts index 0d8971c102cb97f3cb7538c6881146a5b0088c47..a5de885464a7f6a99fa9694ddd9405d45e89a09e 100644 --- a/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.spec.ts @@ -31,102 +31,107 @@ import { FixedDialogComponent } from '../fixed-dialog/fixed-dialog.component'; import { InternalServerErrorDialogComponent } from '../notification/internal-server-error-dialog/internal-server-error-dialog.component'; describe('DialogService', () => { - let service: DialogService; - - const component = <any>{ name: 'RepraesentantEinerComponent' }; - const dialog = { - open: jest.fn(), - getDialogById: jest.fn(), - closeAll: jest.fn() - } - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - { - provide: MatDialog, - useValue: dialog - } - ] - }); - service = TestBed.inject(DialogService); - }); - - it('should be created', () => { - expect(service).toBeTruthy(); - }); - - - describe('open', () => { - - const config = <any>{ id: 'ZumBeispiel' }; - - it('should call dialog open with config', () => { - service.open(component, config); - - expect(dialog.open).toHaveBeenCalledWith(component, config); - }) - }) - - describe('openFixed', () => { - - const data: any = {}; - - it('should call dialog open with config', () => { - service.openFixed(data); - - expect(dialog.open).toHaveBeenCalledWith(FixedDialogComponent, { ...service.FIXED_DIALOG_CONFIG, data }); - }) - - it('should close refs if defined', () => { - const refMock = <any>{ close: jest.fn() }; - service.fixedSingleDialogRef = refMock; - - service.openFixed(data); - - expect(refMock.close).toHaveBeenCalled(); - }) - }) - - describe('openBasic', () => { - - const data: any = {}; - - it('should call dialog open with config', () => { - service.openBasic(data); - - expect(dialog.open).toHaveBeenCalledWith(BasicDialogComponent, { ...service.BASIC_DIALOG_CONFIG, data }); - }) - }) - - describe('openApiError', () => { - - const apiError: ApiError = createApiError(); - - it('should call dialog open with config', () => { - service.openApiErrorInfo(apiError); - - expect(dialog.open).toHaveBeenCalledWith(InternalServerErrorDialogComponent, { ...service.SERVER_ERROR_DIALOG_CONFIG, data: apiError }); - }) - }) - - describe('closeAll', () => { - - it('should close all open dialogs', () => { - service.closeAll(); - - expect(dialog.closeAll).toHaveBeenCalled(); - }) - }) - - describe('openWidely', () => { - const config = <any>{ id: 'ZumBeispiel' }; - - it('should call dialog open with conifg', () => { - service.openWidely(component, config); - - expect(dialog.open).toHaveBeenCalledWith(component, { ...config, ...service.WIDE_DIALOG_CONFIG }); - }) - - }) + let service: DialogService; + + const component = <any>{ name: 'RepraesentantEinerComponent' }; + const dialog = { + open: jest.fn(), + getDialogById: jest.fn(), + closeAll: jest.fn(), + }; + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + { + provide: MatDialog, + useValue: dialog, + }, + ], + }); + service = TestBed.inject(DialogService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); + + describe('open', () => { + const config = <any>{ id: 'ZumBeispiel' }; + + it('should call dialog open with config', () => { + service.open(component, config); + + expect(dialog.open).toHaveBeenCalledWith(component, config); + }); + }); + + describe('openFixed', () => { + const data: any = {}; + + it('should call dialog open with config', () => { + service.openFixed(data); + + expect(dialog.open).toHaveBeenCalledWith(FixedDialogComponent, { + ...service.FIXED_DIALOG_CONFIG, + data, + }); + }); + + it('should close refs if defined', () => { + const refMock = <any>{ close: jest.fn() }; + service.fixedSingleDialogRef = refMock; + + service.openFixed(data); + + expect(refMock.close).toHaveBeenCalled(); + }); + }); + + describe('openBasic', () => { + const data: any = {}; + + it('should call dialog open with config', () => { + service.openBasic(data); + + expect(dialog.open).toHaveBeenCalledWith(BasicDialogComponent, { + ...service.BASIC_DIALOG_CONFIG, + data, + }); + }); + }); + + describe('openApiError', () => { + const apiError: ApiError = createApiError(); + + it('should call dialog open with config', () => { + service.openApiErrorInfo(apiError); + + expect(dialog.open).toHaveBeenCalledWith(InternalServerErrorDialogComponent, { + ...service.SERVER_ERROR_DIALOG_CONFIG, + data: apiError, + }); + }); + }); + + describe('closeAll', () => { + it('should close all open dialogs', () => { + service.closeAll(); + + expect(dialog.closeAll).toHaveBeenCalled(); + }); + }); + + describe('openWidely', () => { + const config = <any>{ id: 'ZumBeispiel' }; + + it('should call dialog open with conifg', () => { + service.openWidely(component, config); + + expect(dialog.open).toHaveBeenCalledWith(component, { + ...config, + ...service.WIDE_DIALOG_CONFIG, + }); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.ts b/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.ts index 42be04313bbc80e62ccb2e6d47d3efc1facfb589..029adb637d8827e9d22e65162ceaec4353b08b14 100644 --- a/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.ts +++ b/alfa-client/libs/ui/src/lib/ui/dialog/dialog.service.ts @@ -22,82 +22,92 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { NoopScrollStrategy } from '@angular/cdk/overlay'; -import { ComponentType } from "@angular/cdk/portal"; -import { Injectable } from "@angular/core"; +import { ComponentType } from '@angular/cdk/portal'; +import { Injectable } from '@angular/core'; import { MatDialog, MatDialogConfig, MatDialogRef } from '@angular/material/dialog'; -import { ApiError, isNotUndefined } from "@alfa-client/tech-shared"; -import { BasicDialogComponent, BasicDialogData, FixedDialogComponent, FixedDialogData } from "@alfa-client/ui"; -import { InternalServerErrorDialogComponent } from "../notification/internal-server-error-dialog/internal-server-error-dialog.component"; +import { ApiError, isNotUndefined } from '@alfa-client/tech-shared'; +import { + BasicDialogComponent, + BasicDialogData, + FixedDialogComponent, + FixedDialogData, +} from '@alfa-client/ui'; +import { InternalServerErrorDialogComponent } from '../notification/internal-server-error-dialog/internal-server-error-dialog.component'; import { RetryInTimeDialog } from './retry-in-time.dialog'; @Injectable({ providedIn: 'root' }) export class DialogService { + fixedSingleDialogRef: MatDialogRef<FixedDialogComponent>; - fixedSingleDialogRef: MatDialogRef<FixedDialogComponent>; + readonly FIXED_DIALOG_CONFIG: MatDialogConfig = { + width: '520px', + position: { bottom: '0', right: '30px' }, + hasBackdrop: false, + panelClass: 'fixed-dialog', + disableClose: true, + autoFocus: false, + scrollStrategy: new NoopScrollStrategy(), + }; - readonly FIXED_DIALOG_CONFIG: MatDialogConfig = { - width: '520px', - position: { bottom: '0', right: '30px' }, - hasBackdrop: false, - panelClass: 'fixed-dialog', - disableClose: true, - autoFocus: false, - scrollStrategy: new NoopScrollStrategy() - }; + readonly SERVER_ERROR_DIALOG_CONFIG: MatDialogConfig = { + width: '440px', + disableClose: true, + panelClass: 'notification-dialog', + }; - readonly SERVER_ERROR_DIALOG_CONFIG: MatDialogConfig = { - width: '440px', - disableClose: true, - panelClass: 'notification-dialog' - }; + readonly BASIC_DIALOG_CONFIG: MatDialogConfig = { + width: 'auto', + hasBackdrop: true, + autoFocus: true, + scrollStrategy: new NoopScrollStrategy(), + }; - readonly BASIC_DIALOG_CONFIG: MatDialogConfig = { - width: 'auto', - hasBackdrop: true, - autoFocus: true, - scrollStrategy: new NoopScrollStrategy() - }; + readonly WIDE_DIALOG_CONFIG: MatDialogConfig = { + width: '610px', + restoreFocus: false, + }; - readonly WIDE_DIALOG_CONFIG: MatDialogConfig = { - width: '610px', - restoreFocus: false, - }; + constructor(private dialog: MatDialog) {} - constructor(private dialog: MatDialog) { } + public openWidely<T>(component: ComponentType<T>, config?: MatDialogConfig): MatDialogRef<T> { + return this.open<T>(component, { ...config, ...this.WIDE_DIALOG_CONFIG }); + } - public openWidely<T>(component: ComponentType<T>, config?: MatDialogConfig): MatDialogRef<T> { - return this.open<T>(component, { ...config, ...this.WIDE_DIALOG_CONFIG }); - } + public open<T>(component: ComponentType<T>, config?: MatDialogConfig): MatDialogRef<T> { + return this.dialog.open<T>(component, config); + } - public open<T>(component: ComponentType<T>, config?: MatDialogConfig): MatDialogRef<T> { - return this.dialog.open<T>(component, config); - } + public openApiErrorInfo<T>(apiError: ApiError): MatDialogRef<InternalServerErrorDialogComponent> { + return this.dialog.open(InternalServerErrorDialogComponent, { + ...this.SERVER_ERROR_DIALOG_CONFIG, + data: apiError, + }); + } - public openApiErrorInfo<T>(apiError: ApiError): MatDialogRef<InternalServerErrorDialogComponent> { - return this.dialog.open(InternalServerErrorDialogComponent, { ...this.SERVER_ERROR_DIALOG_CONFIG, data: apiError }); - } + public openFixed(data: FixedDialogData): MatDialogRef<FixedDialogComponent> { + if (isNotUndefined(this.fixedSingleDialogRef)) { + this.fixedSingleDialogRef.close(); + } + this.fixedSingleDialogRef = this.dialog.open(FixedDialogComponent, { + ...this.FIXED_DIALOG_CONFIG, + data, + }); + return this.fixedSingleDialogRef; + } - public openFixed(data: FixedDialogData): MatDialogRef<FixedDialogComponent> { - if (isNotUndefined(this.fixedSingleDialogRef)) { - this.fixedSingleDialogRef.close(); - } - this.fixedSingleDialogRef = this.dialog.open(FixedDialogComponent, { ...this.FIXED_DIALOG_CONFIG, data }); - return this.fixedSingleDialogRef; - } + public openBasic(data: BasicDialogData): MatDialogRef<BasicDialogComponent> { + return this.dialog.open(BasicDialogComponent, { ...this.BASIC_DIALOG_CONFIG, data }); + } - public openBasic(data: BasicDialogData): MatDialogRef<BasicDialogComponent> { - return this.dialog.open(BasicDialogComponent, { ...this.BASIC_DIALOG_CONFIG, data }); - } + public getRetryDialog(): RetryInTimeDialog { + return new RetryInTimeDialog(this); + } - public getRetryDialog(): RetryInTimeDialog { - return new RetryInTimeDialog(this); - } + public closeAll(): void { + this.dialog.closeAll(); + } - public closeAll(): void { - this.dialog.closeAll(); - } - - public closeById(dialogId: string): void { - this.dialog.getDialogById(dialogId).close(); - } -} \ No newline at end of file + public closeById(dialogId: string): void { + this.dialog.getDialogById(dialogId).close(); + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/dialog/retry-in-time.dialog.ts b/alfa-client/libs/ui/src/lib/ui/dialog/retry-in-time.dialog.ts index 76e9090e1daaf4af769a753b5b9679ed2a2df7f4..18d77a9348857a1d21f5ac2dbd8d74e28c9bcdca 100644 --- a/alfa-client/libs/ui/src/lib/ui/dialog/retry-in-time.dialog.ts +++ b/alfa-client/libs/ui/src/lib/ui/dialog/retry-in-time.dialog.ts @@ -21,51 +21,50 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { isNotUndefined } from "@alfa-client/tech-shared"; -import { DialogService } from "@alfa-client/ui"; -import { ConnectionTimeoutRetryDialogComponent } from "../http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component"; -import { ConnectionTimeoutRetryFailDialogComponent } from "../http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component"; +import { isNotUndefined } from '@alfa-client/tech-shared'; +import { DialogService } from '@alfa-client/ui'; +import { ConnectionTimeoutRetryDialogComponent } from '../http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component'; +import { ConnectionTimeoutRetryFailDialogComponent } from '../http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component'; export class RetryInTimeDialog { + public static ID = 'RETRY_DIALOG_ID'; - public static ID = 'RETRY_DIALOG_ID'; + readonly RETRY_DIALOG_CONFIG = { + disableClose: true, + id: RetryInTimeDialog.ID, + }; - readonly RETRY_DIALOG_CONFIG = { - disableClose: true, - id: RetryInTimeDialog.ID - }; + private readonly retryTime = 300000; // = 5min + private startTime: number | undefined; - private readonly retryTime = 300000;// = 5min - private startTime: number | undefined; + constructor(private dialogService: DialogService) {} - constructor(private dialogService: DialogService) { } + public show(): void { + this.startTimer(); + this.open(); + } - public show(): void { - this.startTimer(); - this.open(); - } + private startTimer(): void { + this.startTime = new Date().getTime(); + } - private startTimer(): void { - this.startTime = new Date().getTime(); - } + private open(): void { + this.dialogService.open(ConnectionTimeoutRetryDialogComponent, this.RETRY_DIALOG_CONFIG); + } - private open(): void { - this.dialogService.open(ConnectionTimeoutRetryDialogComponent, this.RETRY_DIALOG_CONFIG); - } + public shouldRetry(): boolean { + return !this.isTimeOver(); + } - public shouldRetry(): boolean { - return !this.isTimeOver(); - } + private isTimeOver(): boolean { + if (isNotUndefined(this.startTime)) { + return new Date().getTime() > this.startTime + this.retryTime; + } + return true; + } - private isTimeOver(): boolean { - if (isNotUndefined(this.startTime)) { - return new Date().getTime() > (this.startTime + this.retryTime); - } - return true; - } - - public finish(): void { - this.dialogService.closeById(RetryInTimeDialog.ID); - this.dialogService.open(ConnectionTimeoutRetryFailDialogComponent); - } -} \ No newline at end of file + public finish(): void { + this.dialogService.closeById(RetryInTimeDialog.ID); + this.dialogService.open(ConnectionTimeoutRetryFailDialogComponent); + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.html b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.html index bd0c79bda09319602491ccfbed29c0ecd719ce46..2d3bb50998667c75d6e563071d9de2a9ab088eb6 100644 --- a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.html +++ b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.html @@ -1,9 +1,12 @@ -<a mat-button data-test-id="open-url-in-new-window" - [href]="url" - [attr.aria-label]="text" - [matTooltip]="text" - [download]="targetName" - [color]="'primary'"> +<a + mat-button + data-test-id="open-url-in-new-window" + [href]="url" + [attr.aria-label]="text" + [matTooltip]="text" + [download]="targetName" + [color]="'primary'" +> <mat-icon>save_alt</mat-icon> <span>{{ text }}</span> -</a> \ No newline at end of file +</a> diff --git a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.scss b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.scss index 0a99fb3418e543df0aec2bb285645dded123f24a..b93b9abafd0e579ef34ffd50f46c30fd6725fda7 100644 --- a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.scss @@ -1,3 +1,3 @@ a { - padding: 0 15px; -} \ No newline at end of file + padding: 0 15px; +} diff --git a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.spec.ts index e7ac1208059e27d605df938427c908e0ff4c1afa..3724cb85c1e6a6a827ccc49c58b5034956a323f5 100644 --- a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.spec.ts @@ -1,26 +1,23 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { DownloadButtonComponent } from './download-button.component'; -import { MockComponent } from "ng-mocks"; +import { MockComponent } from 'ng-mocks'; describe('DownloadButtonComponent', () => { - let component: DownloadButtonComponent; - let fixture: ComponentFixture<DownloadButtonComponent>; + let component: DownloadButtonComponent; + let fixture: ComponentFixture<DownloadButtonComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - DownloadButtonComponent, - MockComponent(DownloadButtonComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [DownloadButtonComponent, MockComponent(DownloadButtonComponent)], + }).compileComponents(); - fixture = TestBed.createComponent(DownloadButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(DownloadButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.ts b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.ts index faea193711d590c3364573b70677a87e972b02fa..3e22d4435e3f7c11fc15c03bbf99c9c8f40b8bfc 100644 --- a/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/download-button/download-button.component.ts @@ -1,15 +1,13 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-download-button', - templateUrl: './download-button.component.html', - styleUrls: ['./download-button.component.scss'], + selector: 'ozgcloud-download-button', + templateUrl: './download-button.component.html', + styleUrls: ['./download-button.component.scss'], }) export class DownloadButtonComponent { - - @Input() icon: string; - @Input() url: string; - @Input() text: string; - @Input() targetName: string; - + @Input() icon: string; + @Input() url: string; + @Input() text: string; + @Input() targetName: string; } diff --git a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html index 05b5f5532de6fc5069b6cfd10e008e4e0c1f0769..3ca3c2d4caaf053deff6cf5101213c93be36e68d 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.html @@ -24,27 +24,38 @@ --> <mat-form-field appearance="outline"> - <mat-label>{{label}}</mat-label> - - <input #autocompleteInput [attr.data-test-id]="(label | convertForDataTest) + '-autocomplete-input'" - type="text" matInput [matAutocomplete]="auto" - [formControl]="fieldControl" [name]="label" - (keyup)="keyUp($event)" (keyup.enter)="onEnter()"> - - <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete"> - <mat-option *ngFor="let value of values" [attr.data-test-id]="(value.label | convertForDataTest) + '-autocomplete-option'" - [value]="value.value" - (keyup.enter)="onSelection(value)" - (onSelectionChange)="onSelection(value)"> - {{value.label}} - </mat-option> - </mat-autocomplete> - - <mat-error> - <ozgcloud-validation-error [attr.data-test-id]="(label | convertForDataTest) + '-autocomplete-error'" - [issues]="issues" - [label]="label"> - </ozgcloud-validation-error> - </mat-error> - -</mat-form-field> \ No newline at end of file + <mat-label>{{ label }}</mat-label> + + <input + #autocompleteInput + [attr.data-test-id]="(label | convertForDataTest) + '-autocomplete-input'" + type="text" + matInput + [matAutocomplete]="auto" + [formControl]="fieldControl" + [name]="label" + (keyup)="keyUp($event)" + (keyup.enter)="onEnter()" + /> + + <mat-autocomplete autoActiveFirstOption #auto="matAutocomplete"> + <mat-option + *ngFor="let value of values" + [attr.data-test-id]="(value.label | convertForDataTest) + '-autocomplete-option'" + [value]="value.value" + (keyup.enter)="onSelection(value)" + (onSelectionChange)="onSelection(value)" + > + {{ value.label }} + </mat-option> + </mat-autocomplete> + + <mat-error> + <ozgcloud-validation-error + [attr.data-test-id]="(label | convertForDataTest) + '-autocomplete-error'" + [issues]="issues" + [label]="label" + > + </ozgcloud-validation-error> + </mat-error> +</mat-form-field> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.spec.ts index bbe0ba4d999392988f4ae18f985c6b2072a7daad..9d2a8f74d1597fbdd35a865e70551f4e3a7bb89f 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.spec.ts @@ -33,39 +33,39 @@ import { ValidationErrorComponent } from '../../validation-error/validation-erro import { AutocompleteEditorComponent } from './autocomplete-editor.component'; describe('AutocompleteEditorComponent', () => { - let component: AutocompleteEditorComponent; - let fixture: ComponentFixture<AutocompleteEditorComponent>; + let component: AutocompleteEditorComponent; + let fixture: ComponentFixture<AutocompleteEditorComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - AutocompleteEditorComponent, - ConvertForDataTestPipe, - MockComponent(ValidationErrorComponent) - ], - imports: [ - MatAutocompleteModule, - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule, - BrowserAnimationsModule - ], - providers: [ - { - provide: NgControl, - useValue: new UntypedFormControl() - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + AutocompleteEditorComponent, + ConvertForDataTestPipe, + MockComponent(ValidationErrorComponent), + ], + imports: [ + MatAutocompleteModule, + MatFormFieldModule, + MatInputModule, + ReactiveFormsModule, + BrowserAnimationsModule, + ], + providers: [ + { + provide: NgControl, + useValue: new UntypedFormControl(), + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(AutocompleteEditorComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(AutocompleteEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts index ec7d991895cbc6340590f2f260c9431829fba535..1d1a10a12d85f394d6702db756abb6bb81aad810 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/autocomplete-editor/autocomplete-editor.component.ts @@ -21,62 +21,74 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { AfterViewInit, Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core'; +import { + AfterViewInit, + Component, + ElementRef, + EventEmitter, + Input, + Output, + ViewChild, +} from '@angular/core'; import { ResourceUri } from '@ngxp/rest'; import { isEmpty, isEqual, isNil } from 'lodash-es'; import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component'; @Component({ - selector: 'ozgcloud-autocomplete-editor', - templateUrl: './autocomplete-editor.component.html', - styleUrls: ['./autocomplete-editor.component.scss'] + selector: 'ozgcloud-autocomplete-editor', + templateUrl: './autocomplete-editor.component.html', + styleUrls: ['./autocomplete-editor.component.scss'], }) -export class AutocompleteEditorComponent extends FormControlEditorAbstractComponent implements AfterViewInit { +export class AutocompleteEditorComponent + extends FormControlEditorAbstractComponent + implements AfterViewInit +{ + @Input() label: string; + @Input() values: Selectable[] = []; - @Input() label: string; - @Input() values: Selectable[] = []; + @Output() onKeyUp: EventEmitter<void> = new EventEmitter(); + @Output() onOptionSelected: EventEmitter<Selectable> = new EventEmitter(); + @Output() enterOnNoSelection: EventEmitter<void> = new EventEmitter(); - @Output() onKeyUp: EventEmitter<void> = new EventEmitter(); - @Output() onOptionSelected: EventEmitter<Selectable> = new EventEmitter(); - @Output() enterOnNoSelection: EventEmitter<void> = new EventEmitter(); + @ViewChild('autocompleteInput', { static: true }) public autocompleteInputElement: ElementRef; - @ViewChild('autocompleteInput', { static: true }) public autocompleteInputElement: ElementRef; + ngAfterViewInit(): void { + setTimeout(() => this.setFocus(), 50); + } - ngAfterViewInit(): void { - setTimeout(() => this.setFocus(), 50); - } + private setFocus(): void { + this.autocompleteInputElement.nativeElement.focus(); + } - private setFocus(): void { - this.autocompleteInputElement.nativeElement.focus(); - } + onEnter(): void { + const selectedValue: ResourceUri = this.fieldControl.value; - onEnter(): void { - const selectedValue: ResourceUri = this.fieldControl.value; + isEmpty(selectedValue) ? + this.enterOnNoSelection.emit() + : this.onSelection(this.getUserProfile()); + } - isEmpty(selectedValue) - ? this.enterOnNoSelection.emit() - : this.onSelection(this.getUserProfile()); - } + private getUserProfile(): Selectable { + const userProfilesFiltered: Selectable[] = this.values.filter((selectable) => + isEqual(selectable.value, this.fieldControl.value), + ); + return isNil(userProfilesFiltered[0]) ? null : userProfilesFiltered[0]; + } - private getUserProfile(): Selectable { - const userProfilesFiltered: Selectable[] = this.values.filter(selectable => isEqual(selectable.value, this.fieldControl.value)); - return isNil(userProfilesFiltered[0]) ? null : userProfilesFiltered[0]; - } + onSelection(userProfile: Selectable): void { + this.onOptionSelected.emit(userProfile); + } - onSelection(userProfile: Selectable): void { - this.onOptionSelected.emit(userProfile); - } + keyUp(event: KeyboardEvent): void { + if (!this.isArrow(event)) this.onKeyUp.emit(); + } - keyUp(event: KeyboardEvent): void { - if (!this.isArrow(event)) this.onKeyUp.emit(); - } - - private isArrow(event: KeyboardEvent): boolean { - return isEqual(event.key, 'ArrowUp') || isEqual(event.key, 'ArrowDown') - } + private isArrow(event: KeyboardEvent): boolean { + return isEqual(event.key, 'ArrowUp') || isEqual(event.key, 'ArrowDown'); + } } export interface Selectable { - label: string; - value: any; + label: string; + value: any; } diff --git a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.html index 8997db3c5cd31ed694c3f492b18c8611367346b7..4d9a6cd7f6c56983ce65590fcae495e88c34e42d 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.html @@ -24,16 +24,25 @@ --> <mat-form-field> - <mat-label>{{ label }}</mat-label> - <input matInput [matDatepicker]="picker" [formControl]="fieldControl" (blur)="touch()" - [attr.data-test-id]="(label | convertForDataTest) + '-date-input'" - (dateInput)="inputEvent($event)"> - <mat-datepicker-toggle matSuffix [for]="picker"> - <mat-icon matDatepickerToggleIcon attr.aria-label="xxx">update</mat-icon> - </mat-datepicker-toggle> - <mat-datepicker #picker></mat-datepicker> + <mat-label>{{ label }}</mat-label> + <input + matInput + [matDatepicker]="picker" + [formControl]="fieldControl" + (blur)="touch()" + [attr.data-test-id]="(label | convertForDataTest) + '-date-input'" + (dateInput)="inputEvent($event)" + /> + <mat-datepicker-toggle matSuffix [for]="picker"> + <mat-icon matDatepickerToggleIcon attr.aria-label="xxx">update</mat-icon> + </mat-datepicker-toggle> + <mat-datepicker #picker></mat-datepicker> - <mat-error> - <ozgcloud-validation-error [attr.data-test-id]="(label | convertForDataTest) + '-date-error'" [issues]="issues" [label]="label"></ozgcloud-validation-error> - </mat-error> + <mat-error> + <ozgcloud-validation-error + [attr.data-test-id]="(label | convertForDataTest) + '-date-error'" + [issues]="issues" + [label]="label" + ></ozgcloud-validation-error> + </mat-error> </mat-form-field> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.spec.ts index 78e85242d5e9b2ab6a959072837877547ab757b0..0bfe30ef97c28aa38ac80510a09def0f312841c6 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.spec.ts @@ -35,47 +35,48 @@ import { ValidationErrorComponent } from '../../validation-error/validation-erro import { DateEditorComponent } from './date-editor.component'; describe('DateEditorComponent', () => { - let component: DateEditorComponent; - let fixture: ComponentFixture<DateEditorComponent>; + let component: DateEditorComponent; + let fixture: ComponentFixture<DateEditorComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - DateEditorComponent, - ConvertForDataTestPipe, - MockComponent(ValidationErrorComponent) - ], - imports: [ - MatFormFieldModule, - MatInputModule, - MatIconModule, - MatDatepickerModule, - MatNativeDateModule, - ReactiveFormsModule, - BrowserAnimationsModule, - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + DateEditorComponent, + ConvertForDataTestPipe, + MockComponent(ValidationErrorComponent), + ], + imports: [ + MatFormFieldModule, + MatInputModule, + MatIconModule, + MatDatepickerModule, + MatNativeDateModule, + ReactiveFormsModule, + BrowserAnimationsModule, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(DateEditorComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(DateEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('data test id', () => { + describe('data test id', () => { + it('should exist for input', () => { + component.label = 'Ein Label'; + fixture.detectChanges(); - it('should exist for input', () => { - component.label = 'Ein Label'; - fixture.detectChanges(); + const element: HTMLElement = fixture.nativeElement.querySelector( + '[data-test-id="Ein_Label-date-input"]', + ); - const element: HTMLElement = fixture.nativeElement.querySelector('[data-test-id="Ein_Label-date-input"]'); - - expect(element).toBeInstanceOf(HTMLElement); - }) - }) -}); \ No newline at end of file + expect(element).toBeInstanceOf(HTMLElement); + }); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts index 2781658b22ea62aed6a192c5e972e543f1934647..d3288eabcb3db70e110084e9a8ed3e26f47dde5d 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/date-editor/date-editor.component.ts @@ -26,15 +26,14 @@ import { MatDatepickerInputEvent } from '@angular/material/datepicker'; import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component'; @Component({ - selector: 'ozgcloud-date-editor', - templateUrl: './date-editor.component.html', - styleUrls: ['./date-editor.component.scss'], + selector: 'ozgcloud-date-editor', + templateUrl: './date-editor.component.html', + styleUrls: ['./date-editor.component.scss'], }) export class DateEditorComponent extends FormControlEditorAbstractComponent { + @Input() label: string; - @Input() label: string; - - inputEvent(event: MatDatepickerInputEvent<Date>): void { - this.onChange(event.value); - } + inputEvent(event: MatDatepickerInputEvent<Date>): void { + this.onChange(event.value); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.html index 84c93470aebf751c0df5ee4c23fa4604802baf11..6425e1981f23a3da1574b2b3e35af4c723c5e693 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.html @@ -24,26 +24,32 @@ --> <ozgcloud-icon-button-with-spinner - [icon]="selectedItem.icon" - [svgIcon]="selectedItem.svgIcon" - [matMenuTriggerFor]="menu.matMenu" - toolTip="Antworten erlauben/unterbinden" - class="reply-toggle"> + [icon]="selectedItem.icon" + [svgIcon]="selectedItem.svgIcon" + [matMenuTriggerFor]="menu.matMenu" + toolTip="Antworten erlauben/unterbinden" + class="reply-toggle" +> </ozgcloud-icon-button-with-spinner> <ozgcloud-menu #menu class="reply-option-menu"> - <button *ngFor="let item of itemList;" - mat-menu-item - (click)="setSelectedEnumItem(item)" - [attr.data-test-id]="(item.type | convertForDataTest) + '-enum-item'" - [attr.aria-label]="item.text"> - <mat-icon *ngIf="item.svgIcon" [svgIcon]="item.svgIcon"></mat-icon> - <mat-icon *ngIf="!item.svgIcon">{{ item.icon }}</mat-icon> - <span> {{ item.text }}</span> - </button> + <button + *ngFor="let item of itemList" + mat-menu-item + (click)="setSelectedEnumItem(item)" + [attr.data-test-id]="(item.type | convertForDataTest) + '-enum-item'" + [attr.aria-label]="item.text" + > + <mat-icon *ngIf="item.svgIcon" [svgIcon]="item.svgIcon"></mat-icon> + <mat-icon *ngIf="!item.svgIcon">{{ item.icon }}</mat-icon> + <span> {{ item.text }}</span> + </button> </ozgcloud-menu> <mat-label>{{ label }}</mat-label> -<input [formControl]="fieldControl" [attr.data-test-id]="(label | convertForDataTest) + '-enum-input'" - type="hidden" - (blur)="touch()"> +<input + [formControl]="fieldControl" + [attr.data-test-id]="(label | convertForDataTest) + '-enum-input'" + type="hidden" + (blur)="touch()" +/> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.scss b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.scss index d60b847e83a4cbbc6262bff546c13d221109fcde..a466b34c67234bfdb18110117fc9b2905c7f1d45 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.scss @@ -22,15 +22,15 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .reply-toggle { - display: block; + display: block; } mat-label { - display: none; + display: none; } ::ng-deep { - .mat-mdc-menu-panel.reply-option-menu { - margin-left: -8px; - } + .mat-mdc-menu-panel.reply-option-menu { + margin-left: -8px; + } } diff --git a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.spec.ts index 0d597c9e0a1c5d93e12eb752a3c7c70da8665a69..ebde58c7f1f2ec23c6e1ae272b409eb10355e2de 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.spec.ts @@ -32,35 +32,30 @@ import { MockComponent } from 'ng-mocks'; import { EnumEditorComponent } from './enum-editor.component'; describe('EnumEditorComponent', () => { - let component: EnumEditorComponent; - let fixture: ComponentFixture<EnumEditorComponent>; + let component: EnumEditorComponent; + let fixture: ComponentFixture<EnumEditorComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - EnumEditorComponent, - MatIcon, - ConvertForDataTestPipe, - MockComponent(IconButtonWithSpinnerComponent) - ], - imports: [ - UiModule, - MatFormFieldModule, - ReactiveFormsModule, - BrowserAnimationsModule - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + EnumEditorComponent, + MatIcon, + ConvertForDataTestPipe, + MockComponent(IconButtonWithSpinnerComponent), + ], + imports: [UiModule, MatFormFieldModule, ReactiveFormsModule, BrowserAnimationsModule], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(EnumEditorComponent); - component = fixture.componentInstance; - component.defaultItem = { type: 'enumType', icon: 'x', text: 'y' }; - component.itemList = [{ type: 'enumType', icon: 'x', text: 'y' }]; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(EnumEditorComponent); + component = fixture.componentInstance; + component.defaultItem = { type: 'enumType', icon: 'x', text: 'y' }; + component.itemList = [{ type: 'enumType', icon: 'x', text: 'y' }]; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.ts index df5c8393e33119843a54555486e0d1fce2ec7fa0..58a4a6f3413d95da58da14ec6b0cf0126eecfa76 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.component.ts @@ -26,24 +26,23 @@ import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstra import { EnumEditorItem } from './enum-editor.model'; @Component({ - selector: 'ozgcloud-enum-editor', - templateUrl: './enum-editor.component.html', - styleUrls: ['./enum-editor.component.scss'] + selector: 'ozgcloud-enum-editor', + templateUrl: './enum-editor.component.html', + styleUrls: ['./enum-editor.component.scss'], }) export class EnumEditorComponent extends FormControlEditorAbstractComponent implements OnInit { + @Input() label: string; + @Input() itemList: EnumEditorItem[]; + @Input() defaultItem: EnumEditorItem; - @Input() label: string; - @Input() itemList: EnumEditorItem[]; - @Input() defaultItem: EnumEditorItem; + selectedItem: EnumEditorItem; - selectedItem: EnumEditorItem; + override ngOnInit(): void { + this.selectedItem = this.defaultItem; + } - override ngOnInit(): void { - this.selectedItem = this.defaultItem; - } - - setSelectedEnumItem(item: EnumEditorItem): void { - this.selectedItem = item; - this.writeValue(item.type); - } + setSelectedEnumItem(item: EnumEditorItem): void { + this.selectedItem = item; + this.writeValue(item.type); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.model.ts b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.model.ts index 5214ae1b48504b364c4dd1485b72f98e440e9b11..58fd5c1a67813433c98971903b6fb2f09921ef81 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.model.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/enum-editor/enum-editor.model.ts @@ -22,8 +22,8 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export interface EnumEditorItem { - type: any; - text: string; - icon?: string; - svgIcon?: string; -} \ No newline at end of file + type: any; + text: string; + icon?: string; + svgIcon?: string; +} diff --git a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html index 2d8b704ed35e895f15b9e1e446a61911bc0c2fb3..9f11af432fe250422e57e13a3344a067bc80955b 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.html @@ -24,21 +24,32 @@ --> <ng-container formArrayName="attachments"> - <ng-container *ngFor="let hiddenInput of fileLinkControls.controls; let i = index"> - <input id="file-link-{{ i }}" type="hidden" [formControlName]="i" /> - </ng-container> + <ng-container *ngFor="let hiddenInput of fileLinkControls.controls; let i = index"> + <input id="file-link-{{ i }}" type="hidden" [formControlName]="i" /> + </ng-container> </ng-container> -<input #inputElement type="file" [id]="uploadFileId" [accept]="accept" [attr.data-test-id]="(label | convertForDataTest) + '-file-upload-input'" (click)="resetInput()" /> +<input + #inputElement + type="file" + [id]="uploadFileId" + [accept]="accept" + [attr.data-test-id]="(label | convertForDataTest) + '-file-upload-input'" + (click)="resetInput()" +/> <label [attr.for]="uploadFileId" matRipple [attr.aria-label]="label"> - <mat-icon *ngIf="!uploadInProgress.loading">attach_file</mat-icon> + <mat-icon *ngIf="!uploadInProgress.loading">attach_file</mat-icon> - <ozgcloud-spinner [stateResource]="uploadInProgress" [diameter]="22" padding="0"> </ozgcloud-spinner> + <ozgcloud-spinner [stateResource]="uploadInProgress" [diameter]="22" padding="0"> + </ozgcloud-spinner> </label> <mat-error> - <ozgcloud-validation-error [attr.data-test-id]="(label | convertForDataTest) + '-file-upload-error'" - [issues]="issues" [label]="label"> - </ozgcloud-validation-error> + <ozgcloud-validation-error + [attr.data-test-id]="(label | convertForDataTest) + '-file-upload-error'" + [issues]="issues" + [label]="label" + > + </ozgcloud-validation-error> </mat-error> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.scss b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.scss index eb99fb673cfd4315e47aa9b930393d28647136e7..1545d28ea340682843ef6dfb948386c8bd39fba5 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.scss @@ -24,46 +24,46 @@ $size: 40px; :host { - margin: 4px 0; - display: block; - position: relative; + margin: 4px 0; + display: block; + position: relative; } input { - opacity: 0; - width: $size; - height: $size; - position: absolute; + opacity: 0; + width: $size; + height: $size; + position: absolute; } label { - background-color: rgba(#000, 0.04); - width: $size; - height: $size; - border-radius: 50%; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; + background-color: rgba(#000, 0.04); + width: $size; + height: $size; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; } label:hover, :host:focus-within label { - background-color: rgba(#000, 0.16); + background-color: rgba(#000, 0.16); } [disabled] { - background-color: rgba(#000, 0.08); + background-color: rgba(#000, 0.08); } ozgcloud-spinner { - position: absolute; - top: 0; - left: 0; - display: flex; - height: 100%; - width: 100%; - justify-content: center; - align-items: center; - pointer-events: none; + position: absolute; + top: 0; + left: 0; + display: flex; + height: 100%; + width: 100%; + justify-content: center; + align-items: center; + pointer-events: none; } diff --git a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.spec.ts index 7eb1a68b82d3846fe872c8f080ec9bd53ae4f131..13b3502743cc02602d9bcd2631fdc1b75644038d 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.spec.ts @@ -22,7 +22,12 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { AbstractControl, FormGroupDirective, ReactiveFormsModule, UntypedFormBuilder } from '@angular/forms'; +import { + AbstractControl, + FormGroupDirective, + ReactiveFormsModule, + UntypedFormBuilder, +} from '@angular/forms'; import { MatNativeDateModule } from '@angular/material/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatIconModule } from '@angular/material/icon'; @@ -36,82 +41,82 @@ import { ValidationErrorComponent } from '../../validation-error/validation-erro import { FileUploadEditorComponent } from './file-upload-editor.component'; describe('FileUploadEditorComponent', () => { - let component: FileUploadEditorComponent; - let fixture: ComponentFixture<FileUploadEditorComponent>; - const fb = new UntypedFormBuilder(); - const formGroupDirective = new FormGroupDirective([], []); - formGroupDirective.form = fb.group({ - attachments: fb.control(null) - }); + let component: FileUploadEditorComponent; + let fixture: ComponentFixture<FileUploadEditorComponent>; + const fb = new UntypedFormBuilder(); + const formGroupDirective = new FormGroupDirective([], []); + formGroupDirective.form = fb.group({ + attachments: fb.control(null), + }); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - FileUploadEditorComponent, - ConvertForDataTestPipe, - MockComponent(ValidationErrorComponent), - MockComponent(SpinnerComponent) - ], - imports: [ - MatFormFieldModule, - MatInputModule, - MatIconModule, - MatDatepickerModule, - MatNativeDateModule, - ReactiveFormsModule, - BrowserAnimationsModule, - ], - providers: [ - FormGroupDirective, - UntypedFormBuilder, - { - provide: FormGroupDirective, - useValue: formGroupDirective - } - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + FileUploadEditorComponent, + ConvertForDataTestPipe, + MockComponent(ValidationErrorComponent), + MockComponent(SpinnerComponent), + ], + imports: [ + MatFormFieldModule, + MatInputModule, + MatIconModule, + MatDatepickerModule, + MatNativeDateModule, + ReactiveFormsModule, + BrowserAnimationsModule, + ], + providers: [ + FormGroupDirective, + UntypedFormBuilder, + { + provide: FormGroupDirective, + useValue: formGroupDirective, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(FileUploadEditorComponent); - component = fixture.componentInstance; - component.parentFormArrayName = 'attachments'; - component.uploadInProgress = createEmptyStateResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(FileUploadEditorComponent); + component = fixture.componentInstance; + component.parentFormArrayName = 'attachments'; + component.uploadInProgress = createEmptyStateResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('after OnInit', () => { - it('should get fileLinkControls', () => { - expect(component.fileLinkControls).toBeInstanceOf(AbstractControl); - }) - }) + describe('after OnInit', () => { + it('should get fileLinkControls', () => { + expect(component.fileLinkControls).toBeInstanceOf(AbstractControl); + }); + }); - describe('data test id', () => { + describe('data test id', () => { + it('should exist for input', () => { + component.label = 'Ein Label'; + fixture.detectChanges(); - it('should exist for input', () => { - component.label = 'Ein Label'; - fixture.detectChanges(); + const element: HTMLElement = fixture.nativeElement.querySelector( + '[data-test-id="Ein_Label-file-upload-input"]', + ); - const element: HTMLElement = fixture.nativeElement.querySelector('[data-test-id="Ein_Label-file-upload-input"]'); + expect(element).toBeInstanceOf(HTMLElement); + }); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) - }) + describe('click at file input', () => { + it('should call resetInput()', () => { + component.resetInput = jest.fn(); + const fileInput = fixture.nativeElement.querySelector('[data-test-id="-file-upload-input"]'); - describe('click at file input', () => { - it('should call resetInput()', () => { - component.resetInput = jest.fn(); - const fileInput = fixture.nativeElement.querySelector('[data-test-id="-file-upload-input"]'); + fileInput.click(); + fixture.detectChanges(); - fileInput.click(); - fixture.detectChanges(); - - expect(component.resetInput).toHaveBeenCalled(); - }) - }) + expect(component.resetInput).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts index de16a7d41ec924bc92aa1448e8bead20aac5ee24..172a8deb368e10e86648c95cd7ddb40d18d51d86 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/file-upload-editor/file-upload-editor.component.ts @@ -21,59 +21,77 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Component, ElementRef, EventEmitter, HostListener, Input, OnInit, Output, ViewChild } from '@angular/core'; -import { ControlContainer, UntypedFormArray, UntypedFormControl, FormGroupDirective } from '@angular/forms'; +import { + Component, + ElementRef, + EventEmitter, + HostListener, + Input, + OnInit, + Output, + ViewChild, +} from '@angular/core'; +import { + ControlContainer, + UntypedFormArray, + UntypedFormControl, + FormGroupDirective, +} from '@angular/forms'; import { StateResource } from '@alfa-client/tech-shared'; import { uniqueId } from 'lodash-es'; import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component'; @Component({ - selector: 'ozgcloud-file-upload-editor', - templateUrl: './file-upload-editor.component.html', - styleUrls: ['./file-upload-editor.component.scss'], - viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], + selector: 'ozgcloud-file-upload-editor', + templateUrl: './file-upload-editor.component.html', + styleUrls: ['./file-upload-editor.component.scss'], + viewProviders: [{ provide: ControlContainer, useExisting: FormGroupDirective }], }) -export class FileUploadEditorComponent extends FormControlEditorAbstractComponent implements OnInit { +export class FileUploadEditorComponent + extends FormControlEditorAbstractComponent + implements OnInit +{ + @Input() label: string = ''; + @Input() parentFormArrayName: string; + @Input() accept: string = '*/*'; + @Input() uploadInProgress: StateResource<any>; + @Input() set fileLinkList(value: string[]) { + this.buildFormArray(value); + } - @Input() label: string = ''; - @Input() parentFormArrayName: string; - @Input() accept: string = '*/*'; - @Input() uploadInProgress: StateResource<any>; - @Input() set fileLinkList(value: string[]) { - this.buildFormArray(value); - } + @ViewChild('inputElement') inputElement: ElementRef; + @Output() public newFile: EventEmitter<File> = new EventEmitter<File>(); - @ViewChild('inputElement') inputElement: ElementRef; - @Output() public newFile: EventEmitter<File> = new EventEmitter<File>(); + fileLinkControls: UntypedFormArray = new UntypedFormArray([]); - fileLinkControls: UntypedFormArray = new UntypedFormArray([]); + readonly uploadFileId: string = uniqueId(); - readonly uploadFileId: string = uniqueId(); + @HostListener('change', ['$event.target.files']) emitFiles(event: FileList): void { + const file = event && event.item(0); + this.upload(file); + this.setErrors(); + } - @HostListener('change', ['$event.target.files']) emitFiles(event: FileList): void { - const file = event && event.item(0); - this.upload(file); - this.setErrors(); - } + constructor(public parentForm: FormGroupDirective) { + super(null); + } - constructor(public parentForm: FormGroupDirective) { - super(null); - } + override ngOnInit(): void { + this.fileLinkControls = this.parentForm.form.get(this.parentFormArrayName) as UntypedFormArray; + } - override ngOnInit(): void { - this.fileLinkControls = this.parentForm.form.get(this.parentFormArrayName) as UntypedFormArray; - } + buildFormArray(fileLinkList: string[]): void { + this.fileLinkControls.clear(); + fileLinkList.forEach((link: string) => + this.fileLinkControls.push(new UntypedFormControl(link)), + ); + } - buildFormArray(fileLinkList: string[]): void { - this.fileLinkControls.clear(); - fileLinkList.forEach((link: string) => this.fileLinkControls.push(new UntypedFormControl(link))); - } + resetInput(): void { + this.inputElement.nativeElement.value = ''; + } - resetInput(): void { - this.inputElement.nativeElement.value = ''; - } - - upload(file: File): void { - this.newFile.emit(file); - } + upload(file: File): void { + this.newFile.emit(file); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/editor/formcontrol-editor.abstract.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/formcontrol-editor.abstract.component.ts index 294b7a6fb8309dedd1b636e5e7131cff0dc49228..345cf7de9e8bc26499a742b344023b7b0ec018d2 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/formcontrol-editor.abstract.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/formcontrol-editor.abstract.component.ts @@ -28,66 +28,68 @@ import { isEmpty } from 'lodash-es'; import { Subscription } from 'rxjs'; @Component({ - template: 'NO UI' + template: 'NO UI', }) export abstract class FormControlEditorAbstractComponent implements ControlValueAccessor { + readonly fieldControl: UntypedFormControl = new UntypedFormControl(); + public onChange = (text: string | Date) => undefined; + public onTouched = () => undefined; - readonly fieldControl: UntypedFormControl = new UntypedFormControl(); - public onChange = (text: string | Date) => undefined; - public onTouched = () => undefined; + private changesSubscr: Subscription; + private statusSubscr: Subscription; - private changesSubscr: Subscription; - private statusSubscr: Subscription; + disabled: boolean = false; - disabled: boolean = false; + constructor(@Self() @Optional() public control: NgControl) { + if (this.control) this.control.valueAccessor = this; - constructor(@Self() @Optional() public control: NgControl) { - if (this.control) this.control.valueAccessor = this; + this.changesSubscr = this.fieldControl.valueChanges.subscribe((val) => { + val = isEmpty(val) ? null : val; + this.onChange(val); + this.setErrors(); + }); + } - this.changesSubscr = this.fieldControl.valueChanges.subscribe(val => { - val = isEmpty(val) ? null : val; - this.onChange(val); - this.setErrors(); - }); - } + ngOnInit(): void { + if (!this.statusSubscr && this.control) + this.statusSubscr = this.control.statusChanges.subscribe(() => { + this.setErrors(); + }); + } - ngOnInit(): void { - if (!this.statusSubscr && this.control) this.statusSubscr = this.control.statusChanges.subscribe(() => { - this.setErrors(); - }); - } + touch(): void { + this.onTouched(); + } - touch(): void { - this.onTouched(); - } + writeValue(text: string): void { + this.fieldControl.setValue(text); + this.setErrors(); + } + registerOnChange(fn: (text: string | Date) => {}): void { + this.onChange = fn; + } + registerOnTouched(fn: () => {}): void { + this.onTouched = fn; + } + setDisabledState?(isDisabled: boolean): void { + this.disabled = isDisabled; + } - writeValue(text: string): void { - this.fieldControl.setValue(text); - this.setErrors(); - } - registerOnChange(fn: (text: string | Date) => {}): void { - this.onChange = fn; - } - registerOnTouched(fn: () => {}): void { - this.onTouched = fn; - } - setDisabledState?(isDisabled: boolean): void { - this.disabled = isDisabled; - } + ngOnDestroy(): void { + if (this.changesSubscr) this.changesSubscr.unsubscribe(); + if (this.statusSubscr) this.statusSubscr.unsubscribe(); + } - ngOnDestroy(): void { - if (this.changesSubscr) this.changesSubscr.unsubscribe(); - if (this.statusSubscr) this.statusSubscr.unsubscribe(); - } + setErrors() { + if (this.control) { + this.fieldControl.setErrors(this.control.errors); + if (this.control.invalid) this.fieldControl.markAsTouched(); + } + } - setErrors() { - if (this.control) { - this.fieldControl.setErrors(this.control.errors); - if (this.control.invalid) this.fieldControl.markAsTouched(); - } - } - - get issues(): Issue[] { - return this.fieldControl.errors ? Object.keys(this.fieldControl.errors).map(key => <Issue>this.fieldControl.errors[key]) : []; - } -} \ No newline at end of file + get issues(): Issue[] { + return this.fieldControl.errors ? + Object.keys(this.fieldControl.errors).map((key) => <Issue>this.fieldControl.errors[key]) + : []; + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html index ceefda1d6518547a8bfa71029b54a97835a028c6..9087fe250f23f35de30bf35cd57e9dcdc014bc57 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.html @@ -23,31 +23,42 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<mat-form-field [subscriptSizing]="subscriptSizing" class="compact-input" appearance="{{appearance}}" [floatLabel]="readOnly || autoFocus ? 'always' : 'auto'"> - <mat-label>{{ label }}</mat-label> - <div class="wrapper"> - <input #inputElement - matInput - placeholder="{{ placeholder }}" - [formControl]="fieldControl" - [autocomplete]="autocomplete" - [readonly]="readOnly" - (blur)="touch()" - [attr.data-test-id]="(label | convertForDataTest) + '-text-input'" - [class.with-clear-button]="showClearButton$ | async" - /> - <button *ngIf="showClearButton$ | async" - data-test-id="clear-button" - class="clear-button" - type="button" - (click)="onClear()" - mat-icon-button aria-label="Leeren"> - <mat-icon>close</mat-icon> - </button> - - </div> - <mat-error> - <ozgcloud-validation-error [attr.data-test-id]="(getPlaceholderLabel() | convertForDataTest) + '-text-error'" [issues]="issues" - [label]="getPlaceholderLabel()"></ozgcloud-validation-error> - </mat-error> +<mat-form-field + [subscriptSizing]="subscriptSizing" + class="compact-input" + appearance="{{ appearance }}" + [floatLabel]="readOnly || autoFocus ? 'always' : 'auto'" +> + <mat-label>{{ label }}</mat-label> + <div class="wrapper"> + <input + #inputElement + matInput + placeholder="{{ placeholder }}" + [formControl]="fieldControl" + [autocomplete]="autocomplete" + [readonly]="readOnly" + (blur)="touch()" + [attr.data-test-id]="(label | convertForDataTest) + '-text-input'" + [class.with-clear-button]="showClearButton$ | async" + /> + <button + *ngIf="showClearButton$ | async" + data-test-id="clear-button" + class="clear-button" + type="button" + (click)="onClear()" + mat-icon-button + aria-label="Leeren" + > + <mat-icon>close</mat-icon> + </button> + </div> + <mat-error> + <ozgcloud-validation-error + [attr.data-test-id]="(getPlaceholderLabel() | convertForDataTest) + '-text-error'" + [issues]="issues" + [label]="getPlaceholderLabel()" + ></ozgcloud-validation-error> + </mat-error> </mat-form-field> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.scss b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.scss index 5e12390456282d60fa7e2449e64f1ee14247558d..f13f5f40fd3953f02ec8edf802cb11f375155fb9 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.scss @@ -23,21 +23,21 @@ */ .wrapper { - position: relative; + position: relative; } .clear-button { - position: absolute; - margin: auto 0; - bottom: 0; - top: 0; - right: 0; + position: absolute; + margin: auto 0; + bottom: 0; + top: 0; + right: 0; - .mat-icon { - opacity: 0.4; - } + .mat-icon { + opacity: 0.4; + } } .with-clear-button { - width: calc(100% - 48px); -} \ No newline at end of file + width: calc(100% - 48px); +} diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts index 615d7c06fa01f92bb5a5d4f55e58046ce186b5ec..7b0052fa5f4fdfaba331500fc37bc399ca3b7aef 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.spec.ts @@ -32,51 +32,46 @@ import { ValidationErrorComponent } from '../../validation-error/validation-erro import { TextEditorComponent } from './text-editor.component'; describe('TextEditorComponent', () => { - let component: TextEditorComponent; - let fixture: ComponentFixture<TextEditorComponent>; + let component: TextEditorComponent; + let fixture: ComponentFixture<TextEditorComponent>; - const input: string = '[data-test-id="Ein_Label-text-input"]'; + const input: string = '[data-test-id="Ein_Label-text-input"]'; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - TextEditorComponent, - ConvertForDataTestPipe, - MockComponent(ValidationErrorComponent) - ], - imports: [ - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule, - BrowserAnimationsModule - ], - providers: [ - { - provide: NgControl, - useValue: new UntypedFormControl() - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + TextEditorComponent, + ConvertForDataTestPipe, + MockComponent(ValidationErrorComponent), + ], + imports: [MatFormFieldModule, MatInputModule, ReactiveFormsModule, BrowserAnimationsModule], + providers: [ + { + provide: NgControl, + useValue: new UntypedFormControl(), + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(TextEditorComponent); - component = fixture.componentInstance; - component.label = 'Ein Label'; - fixture.detectChanges(); - }) + beforeEach(() => { + fixture = TestBed.createComponent(TextEditorComponent); + component = fixture.componentInstance; + component.label = 'Ein Label'; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }) + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should exist for input', () => { - const element: HTMLElement = fixture.nativeElement.querySelector(input); + it('should exist for input', () => { + const element: HTMLElement = fixture.nativeElement.querySelector(input); - expect(element).toBeInstanceOf(HTMLElement); - }) + expect(element).toBeInstanceOf(HTMLElement); + }); - it('should use fixed subscription sizing by default', () => { - expect(component.subscriptSizing).toBe('fixed'); - }) + it('should use fixed subscription sizing by default', () => { + expect(component.subscriptSizing).toBe('fixed'); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts index c122ccd41cd214b7f1ef71951cd754de4284b8e0..a64326dcbad46ccca353328cf70477fe653e4b29 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/text-editor/text-editor.component.ts @@ -28,44 +28,46 @@ import { hasContent } from '@alfa-client/tech-shared'; import { SubscriptSizing } from '@angular/material/form-field'; @Component({ - selector: 'ozgcloud-text-editor', - templateUrl: './text-editor.component.html', - styleUrls: ['./text-editor.component.scss'] + selector: 'ozgcloud-text-editor', + templateUrl: './text-editor.component.html', + styleUrls: ['./text-editor.component.scss'], }) -export class TextEditorComponent extends FormControlEditorAbstractComponent implements OnInit, AfterViewInit { +export class TextEditorComponent + extends FormControlEditorAbstractComponent + implements OnInit, AfterViewInit +{ + @ViewChild('inputElement') inputElement: ElementRef; - @ViewChild('inputElement') inputElement: ElementRef; + @Input() label: string; + @Input() placeholder: string; + @Input() placeholderLabel: string = null; + @Input() autocomplete: 'off' | 'email' = 'off'; + @Input() appearance: 'outline' | 'fill' = 'fill'; + @Input() readOnly: boolean; + @Input() autoFocus: boolean; + @Input() clearable = false; + @Input() subscriptSizing: SubscriptSizing = 'fixed'; - @Input() label: string; - @Input() placeholder: string; - @Input() placeholderLabel: string = null; - @Input() autocomplete: 'off' | 'email' = 'off'; - @Input() appearance: 'outline' | 'fill' = 'fill'; - @Input() readOnly: boolean; - @Input() autoFocus: boolean; - @Input() clearable = false; - @Input() subscriptSizing: SubscriptSizing = 'fixed'; + showClearButton$: Observable<boolean>; - showClearButton$: Observable<boolean>; + ngOnInit() { + super.ngOnInit(); + this.showClearButton$ = this.fieldControl.valueChanges + .pipe(startWith(this.fieldControl.value)) + .pipe(map((value) => hasContent(value) && this.clearable)); + } - ngOnInit() { - super.ngOnInit(); - this.showClearButton$ = this.fieldControl.valueChanges - .pipe(startWith(this.fieldControl.value)) - .pipe(map(value => hasContent(value) && this.clearable)); - } + ngAfterViewInit(): void { + window.setTimeout(() => { + if (this.autoFocus) this.inputElement.nativeElement.focus(); + }); + } - ngAfterViewInit(): void { - window.setTimeout(() => { - if (this.autoFocus) this.inputElement.nativeElement.focus(); - }) - } + getPlaceholderLabel(): string { + return this.placeholderLabel ? this.placeholderLabel : this.label; + } - getPlaceholderLabel(): string { - return this.placeholderLabel ? this.placeholderLabel : this.label; - } - - onClear(): void { - this.writeValue(null); - } + onClear(): void { + this.writeValue(null); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.html b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.html index be19f0528399e99e7b5a974ab021c1ca10f3f9d0..c40765078be75b0b8a038ffa7896f82dafed9a54 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.html +++ b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.html @@ -24,24 +24,24 @@ --> <mat-form-field [appearance]="appearance"> - - <mat-label>{{ label }}</mat-label> - - <textarea - #autosize="cdkTextareaAutosize" - placeholder="{{ placeholder }}" - matInput - cdkTextareaAutosize - [formControl]="fieldControl" - [attr.data-test-id]="(label | convertForDataTest) + '-textarea-input'" - (blur)="touch()"></textarea> - - <mat-error> - <ozgcloud-validation-error - [issues]="issues" - [label]="label" - [attr.data-test-id]="(label | convertForDataTest) + '-textarea-error'"> - </ozgcloud-validation-error> - </mat-error> - + <mat-label>{{ label }}</mat-label> + + <textarea + #autosize="cdkTextareaAutosize" + placeholder="{{ placeholder }}" + matInput + cdkTextareaAutosize + [formControl]="fieldControl" + [attr.data-test-id]="(label | convertForDataTest) + '-textarea-input'" + (blur)="touch()" + ></textarea> + + <mat-error> + <ozgcloud-validation-error + [issues]="issues" + [label]="label" + [attr.data-test-id]="(label | convertForDataTest) + '-textarea-error'" + > + </ozgcloud-validation-error> + </mat-error> </mat-form-field> diff --git a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.scss b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.scss index f8cb59db080754cf47556281bead56ebb4f396ad..74de01a17b59b978249a2b4f6292590b0763b1b4 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.scss @@ -22,10 +22,10 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ mat-form-field { - width: 100%; + width: 100%; } textarea { - box-sizing: content-box !important; // entfernt den Scrollbalken der Textarea bei cdkTextareaAutosize - line-height: 1.25; + box-sizing: content-box !important; // entfernt den Scrollbalken der Textarea bei cdkTextareaAutosize + line-height: 1.25; } diff --git a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.spec.ts index 3e97a89a35bd04390f765cf4584fed52603d6404..a5aa59f6096ece4de95af6f538b502a6d07988b2 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.spec.ts @@ -32,48 +32,45 @@ import { ValidationErrorComponent } from '../../validation-error/validation-erro import { TextAreaEditorComponent } from './textarea-editor.component'; describe('TextAreaEditorComponent', () => { - let component: TextAreaEditorComponent; - let fixture: ComponentFixture<TextAreaEditorComponent>; + let component: TextAreaEditorComponent; + let fixture: ComponentFixture<TextAreaEditorComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - TextAreaEditorComponent, - ConvertForDataTestPipe, - MockComponent(ValidationErrorComponent) - ], - imports: [ - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule, - BrowserAnimationsModule - ], - providers: [ - { - provide: NgControl, - useValue: new UntypedFormControl() - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + TextAreaEditorComponent, + ConvertForDataTestPipe, + MockComponent(ValidationErrorComponent), + ], + imports: [MatFormFieldModule, MatInputModule, ReactiveFormsModule, BrowserAnimationsModule], + providers: [ + { + provide: NgControl, + useValue: new UntypedFormControl(), + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(TextAreaEditorComponent); - component = fixture.componentInstance; - component.label = 'Ein Label'; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(TextAreaEditorComponent); + component = fixture.componentInstance; + component.label = 'Ein Label'; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should exist for input', () => { - component.label = 'Ein Label'; - fixture.detectChanges(); + it('should exist for input', () => { + component.label = 'Ein Label'; + fixture.detectChanges(); - const element: HTMLElement = fixture.nativeElement.querySelector('[data-test-id="Ein_Label-textarea-input"]'); + const element: HTMLElement = fixture.nativeElement.querySelector( + '[data-test-id="Ein_Label-textarea-input"]', + ); - expect(element).toBeInstanceOf(HTMLElement); - }) + expect(element).toBeInstanceOf(HTMLElement); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts index 15857c48888918e5f8da9ba86b8ebf6f696dd5f3..b5c876ac008f4fa926459a7cefeba05a185b657c 100644 --- a/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/editor/textarea-editor/textarea-editor.component.ts @@ -26,19 +26,21 @@ import { AfterViewInit, Component, Input, ViewChild } from '@angular/core'; import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component'; @Component({ - selector: 'ozgcloud-textarea-editor', - templateUrl: './textarea-editor.component.html', - styleUrls: ['./textarea-editor.component.scss'] + selector: 'ozgcloud-textarea-editor', + templateUrl: './textarea-editor.component.html', + styleUrls: ['./textarea-editor.component.scss'], }) -export class TextAreaEditorComponent extends FormControlEditorAbstractComponent implements AfterViewInit { +export class TextAreaEditorComponent + extends FormControlEditorAbstractComponent + implements AfterViewInit +{ + @ViewChild('autosize') autosize: CdkTextareaAutosize; - @ViewChild('autosize') autosize: CdkTextareaAutosize; + @Input() placeholder: string; + @Input() label: string = ''; + @Input() appearance: 'outline' | 'fill' = 'fill'; - @Input() placeholder: string; - @Input() label: string = ''; - @Input() appearance: 'outline' | 'fill' = 'fill' - - ngAfterViewInit() { - this.autosize.resizeToFitContent(true); - } + ngAfterViewInit() { + this.autosize.resizeToFitContent(true); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/expansion-panel/_expansion-panel.theme.scss b/alfa-client/libs/ui/src/lib/ui/expansion-panel/_expansion-panel.theme.scss index a4e2f1f00d8307aae363a3554220b27a1c770d87..b95454800cbbf5eb92398084d7be20d6ca75019a 100644 --- a/alfa-client/libs/ui/src/lib/ui/expansion-panel/_expansion-panel.theme.scss +++ b/alfa-client/libs/ui/src/lib/ui/expansion-panel/_expansion-panel.theme.scss @@ -25,69 +25,68 @@ @use '@angular/material' as mat; @mixin expansion-panel($theme) { - $color-config: mat.get-color-config($theme); - $primary-palette: map.get($color-config, 'primary'); + $color-config: mat.get-color-config($theme); + $primary-palette: map.get($color-config, 'primary'); - ozgcloud-expansion-panel h3 { - color: mat.get-color-from-palette($primary-palette); - } + ozgcloud-expansion-panel h3 { + color: mat.get-color-from-palette($primary-palette); + } } - body.mat-typography ozgcloud-expansion-panel { - .mat-expansion-panel-header { - padding: 0 !important; - height: 44px !important; - } + .mat-expansion-panel-header { + padding: 0 !important; + height: 44px !important; + } - h3 { - margin-bottom: 0; - font-weight: 500; - margin-left: 8px; - font-size: 16px; - } + h3 { + margin-bottom: 0; + font-weight: 500; + margin-left: 8px; + font-size: 16px; + } - .mat-expansion-panel-body { - padding: 0 0 16px 56px; - } + .mat-expansion-panel-body { + padding: 0 0 16px 56px; + } - ozgcloud-expansion-panel { - .mat-expansion-panel-header { - height: 40px !important; - } + ozgcloud-expansion-panel { + .mat-expansion-panel-header { + height: 40px !important; + } - h3 { - color: inherit; - font-size: 14px !important; - font-weight: 500 !important; - margin-left: 0; - } + h3 { + color: inherit; + font-size: 14px !important; + font-weight: 500 !important; + margin-left: 0; + } - .mat-expansion-panel-header-title { - flex-direction: row-reverse; - justify-content: flex-end; - } + .mat-expansion-panel-header-title { + flex-direction: row-reverse; + justify-content: flex-end; + } - .mat-expansion-panel-body { - padding: 0 0 0 16px; - } - } + .mat-expansion-panel-body { + padding: 0 0 0 16px; + } + } } body.mat-typography alfa-expansion-panel-with-user { - .mat-expansion-panel-body { - padding: 0 0 0 32px; - } + .mat-expansion-panel-body { + padding: 0 0 0 32px; + } } .section.wiedervorlagen { - .mat-expansion-panel-body .mat-expansion-panel-body { - padding: 0 0 0 24px; - } + .mat-expansion-panel-body .mat-expansion-panel-body { + padding: 0 0 0 24px; + } } .dark ozgcloud-expansion-panel { - h3 { - color: mat.get-color-from-palette($primaryPalette, lighter); - } + h3 { + color: mat.get-color-from-palette($primaryPalette, lighter); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.html b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.html index f04bd26b7bc8c97053a5bed22f20ea0247d3e729..6ecd90474519e1ebd69a2e1935124d83a8a014e2 100644 --- a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.html +++ b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.html @@ -24,22 +24,29 @@ --> <mat-accordion displayMode="flat" hideToggle> - - <mat-expansion-panel [expanded]="expanded" data-test-class="expansion-panel" #expansionPanel> - - <mat-expansion-panel-header> - <mat-panel-title data-test-class="panel-title"> - <button mat-icon-button tabindex="-1" [attr.aria-label]="'Bereich ' + (expansionPanel.expanded? 'reduzieren': 'erweitern')"> - <mat-icon>chevron_right</mat-icon> - </button> - <h3>{{ headline }}</h3> - </mat-panel-title> - </mat-expansion-panel-header> - - <!-- expandable start --> - <div [ngStyle]="{visibility: expansionPanel.expanded ? 'visible' : 'hidden', display: expansionPanel.expanded ? 'block' : 'none'}"><ng-content></ng-content></div> - <!-- expandable end --> - - </mat-expansion-panel> - + <mat-expansion-panel [expanded]="expanded" data-test-class="expansion-panel" #expansionPanel> + <mat-expansion-panel-header> + <mat-panel-title data-test-class="panel-title"> + <button + mat-icon-button + tabindex="-1" + [attr.aria-label]="'Bereich ' + (expansionPanel.expanded ? 'reduzieren' : 'erweitern')" + > + <mat-icon>chevron_right</mat-icon> + </button> + <h3>{{ headline }}</h3> + </mat-panel-title> + </mat-expansion-panel-header> + + <!-- expandable start --> + <div + [ngStyle]="{ + visibility: expansionPanel.expanded ? 'visible' : 'hidden', + display: expansionPanel.expanded ? 'block' : 'none' + }" + > + <ng-content></ng-content> + </div> + <!-- expandable end --> + </mat-expansion-panel> </mat-accordion> diff --git a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.scss b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.scss index 6e0a66fd3c4725b056f1cfad5f754219c9fe98fc..6bfc5ee6b93d64d47e7bdddd86b16ddb5b45291f 100644 --- a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.scss @@ -22,41 +22,40 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .mat-accordion { - .mat-expansion-panel-header { + .mat-expansion-panel-header { + &:hover, + &.cdk-focused { + background-color: inherit !important; + } - &:hover, - &.cdk-focused { - background-color: inherit !important; - } + &.cdk-focused { + button { + background-color: rgba(#777, 0.16); + } + } - &.cdk-focused { - button { - background-color: rgba(#777, 0.16); - } - } + mat-icon { + transition: transform 0.1s ease-in-out; + padding-right: 4px; + } - mat-icon { - transition: transform 0.1s ease-in-out; - padding-right: 4px; - } + &.mat-expanded { + mat-icon { + transform: rotate(90deg); + } + } + } - &.mat-expanded { - mat-icon { - transform: rotate(90deg); - } - } - } + .mat-expansion-panel-header-title { + align-items: center; + white-space: nowrap; + overflow: hidden; + } - .mat-expansion-panel-header-title { - align-items: center; - white-space: nowrap; - overflow: hidden; - } - - mat-expansion-panel { - background-color: inherit; - box-shadow: none; - margin-right: -12px; - padding-right: 12px; - } + mat-expansion-panel { + background-color: inherit; + box-shadow: none; + margin-right: -12px; + padding-right: 12px; + } } diff --git a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.spec.ts index 0404de90787264dd680dbf1e85e127c91500f810..dc7d5d86b61542444588704bfa6e82d646553dfe 100644 --- a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.spec.ts @@ -23,39 +23,41 @@ */ import { PortalModule } from '@angular/cdk/portal'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MatAccordion, MatExpansionPanel, MatExpansionPanelHeader, MatExpansionPanelTitle } from '@angular/material/expansion'; +import { + MatAccordion, + MatExpansionPanel, + MatExpansionPanelHeader, + MatExpansionPanelTitle, +} from '@angular/material/expansion'; import { MatIcon } from '@angular/material/icon'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { ExpansionPanelComponent } from './expansion-panel.component'; describe('VorgangDetailExpansionPanelComponent', () => { - let component: ExpansionPanelComponent; - let fixture: ComponentFixture<ExpansionPanelComponent>; + let component: ExpansionPanelComponent; + let fixture: ComponentFixture<ExpansionPanelComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - BrowserAnimationsModule, - PortalModule - ], - declarations: [ - ExpansionPanelComponent, - MatExpansionPanel, - MatExpansionPanelTitle, - MatAccordion, - MatIcon, - MatExpansionPanelHeader - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [BrowserAnimationsModule, PortalModule], + declarations: [ + ExpansionPanelComponent, + MatExpansionPanel, + MatExpansionPanelTitle, + MatAccordion, + MatIcon, + MatExpansionPanelHeader, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(ExpansionPanelComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ExpansionPanelComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.ts b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.ts index addd753088e354e24e08034a85414ec554e448a3..040a74254894d3d8f00f700fc585870baa0d1b65 100644 --- a/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/expansion-panel/expansion-panel.component.ts @@ -24,14 +24,11 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-expansion-panel', - templateUrl: './expansion-panel.component.html', - styleUrls: ['./expansion-panel.component.scss'] + selector: 'ozgcloud-expansion-panel', + templateUrl: './expansion-panel.component.html', + styleUrls: ['./expansion-panel.component.scss'], }) export class ExpansionPanelComponent { - - @Input() headline: string; - @Input() expanded: boolean = true; - - + @Input() headline: string; + @Input() expanded: boolean = true; } diff --git a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.html b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.html index 7c7d499ebe09ffc4cf51a7a1fa658ac987177275..dbf373e674e643bec0a2ddd34f097d1cf79c9880 100644 --- a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.html +++ b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.html @@ -24,16 +24,17 @@ --> <ng-container *ngIf="uploadInProgress$ | async as uploadInProgress"> - <input data-test-id="file-upload-input" - [id]="myId" type="file" [accept]="accept" - (change)="onFileChanged($event)"> - <label [attr.for]="myId" matRipple aria-label="Anhang hinzufügen"> - <mat-icon *ngIf="!uploadInProgress.loading">attach_file</mat-icon> + <input + data-test-id="file-upload-input" + [id]="myId" + type="file" + [accept]="accept" + (change)="onFileChanged($event)" + /> + <label [attr.for]="myId" matRipple aria-label="Anhang hinzufügen"> + <mat-icon *ngIf="!uploadInProgress.loading">attach_file</mat-icon> - <ozgcloud-spinner - [stateResource]="uploadInProgress" - [diameter]="22" - padding="0"> - </ozgcloud-spinner> - </label> + <ozgcloud-spinner [stateResource]="uploadInProgress" [diameter]="22" padding="0"> + </ozgcloud-spinner> + </label> </ng-container> diff --git a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.scss b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.scss index eb99fb673cfd4315e47aa9b930393d28647136e7..1545d28ea340682843ef6dfb948386c8bd39fba5 100644 --- a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.scss @@ -24,46 +24,46 @@ $size: 40px; :host { - margin: 4px 0; - display: block; - position: relative; + margin: 4px 0; + display: block; + position: relative; } input { - opacity: 0; - width: $size; - height: $size; - position: absolute; + opacity: 0; + width: $size; + height: $size; + position: absolute; } label { - background-color: rgba(#000, 0.04); - width: $size; - height: $size; - border-radius: 50%; - display: flex; - justify-content: center; - align-items: center; - cursor: pointer; + background-color: rgba(#000, 0.04); + width: $size; + height: $size; + border-radius: 50%; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; } label:hover, :host:focus-within label { - background-color: rgba(#000, 0.16); + background-color: rgba(#000, 0.16); } [disabled] { - background-color: rgba(#000, 0.08); + background-color: rgba(#000, 0.08); } ozgcloud-spinner { - position: absolute; - top: 0; - left: 0; - display: flex; - height: 100%; - width: 100%; - justify-content: center; - align-items: center; - pointer-events: none; + position: absolute; + top: 0; + left: 0; + display: flex; + height: 100%; + width: 100%; + justify-content: center; + align-items: center; + pointer-events: none; } diff --git a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.spec.ts index c2ffba3e80e6641c014e2a150a9899537fb54c65..78095b51b1154758d968109ca6525fe1ddd8aa3b 100644 --- a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.spec.ts @@ -34,13 +34,8 @@ describe('FileUploadComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ - FileUploadComponent, - MatIcon, - MockComponent(SpinnerComponent) - ] - }) - .compileComponents(); + declarations: [FileUploadComponent, MatIcon, MockComponent(SpinnerComponent)], + }).compileComponents(); }); beforeEach(() => { diff --git a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.ts b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.ts index 9b0ea54ce095d8f7b88326519a32266cc3c675eb..55579d2e66515082dd38a437148f1c8390d1b463 100644 --- a/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/file-upload/file-upload.component.ts @@ -27,20 +27,20 @@ import { uniqueId } from 'lodash-es'; import { Observable } from 'rxjs'; @Component({ - selector: 'ozgcloud-file-upload', - templateUrl: './file-upload.component.html', - styleUrls: ['./file-upload.component.scss'] + selector: 'ozgcloud-file-upload', + templateUrl: './file-upload.component.html', + styleUrls: ['./file-upload.component.scss'], }) export class FileUploadComponent { - @Input() accept: string = '*/*'; - @Input() uploadInProgress$: Observable<StateResource<any>>; + @Input() accept: string = '*/*'; + @Input() uploadInProgress$: Observable<StateResource<any>>; - @Output() fileChanged: EventEmitter<File> = new EventEmitter(); + @Output() fileChanged: EventEmitter<File> = new EventEmitter(); - readonly myId: string = uniqueId(); + readonly myId: string = uniqueId(); - onFileChanged($event: Event): void { - const files: FileList = (<HTMLInputElement>$event.target).files; - this.fileChanged.emit(files[0]); - } -} \ No newline at end of file + onFileChanged($event: Event): void { + const files: FileList = (<HTMLInputElement>$event.target).files; + this.fileChanged.emit(files[0]); + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/_fixed-dialog.theme.scss b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/_fixed-dialog.theme.scss index 0b4c18dfae3bbfe602477119799a5a2b7bee7b18..f71cbc89bc0ca6eccd4030537e653e21b0ef83b2 100644 --- a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/_fixed-dialog.theme.scss +++ b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/_fixed-dialog.theme.scss @@ -22,100 +22,97 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .fixed-dialog { + .mat-mdc-dialog-container { + padding: 0; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + position: relative; + .mat-mdc-dialog-title { + display: flex; + background-color: $dark-background; + margin: 0; + padding: 0 4px 0 16px; + color: #fff; + font-size: 16px; + font-weight: normal; + justify-content: space-between; + align-items: center; + } + .mdc-dialog__title::before { + display: none; + } + .mat-mdc-icon-button.mat-mdc-button-base { + padding: 0; + width: 40px; + height: 40px; + } + .mdc-text-field, + .mat-mdc-form-field-hint-wrapper, + .mat-mdc-form-field-error-wrapper { + padding: 0; + } + .mat-mdc-form-field-error { + font-size: 12px; + } + .mdc-dialog__content { + line-height: 20px; + } + .mat-mdc-dialog-content { + max-height: 50vh; + min-height: 200px; + margin: 0 0 58px 0; + padding: 8px 16px; - .mat-mdc-dialog-container { - padding: 0; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - position: relative; - .mat-mdc-dialog-title { - display: flex; - background-color: $dark-background; - margin: 0; - padding: 0 4px 0 16px; - color: #fff; - font-size: 16px; - font-weight: normal; - justify-content: space-between; - align-items: center; - } - .mdc-dialog__title::before { - display: none; - } - .mat-mdc-icon-button.mat-mdc-button-base { - padding: 0; - width: 40px; - height: 40px; - } - .mdc-text-field, - .mat-mdc-form-field-hint-wrapper, - .mat-mdc-form-field-error-wrapper { - padding: 0; - } - .mat-mdc-form-field-error { - font-size: 12px; - } - .mdc-dialog__content { - line-height: 20px; - } - .mat-mdc-dialog-content { - max-height: 50vh; - min-height: 200px; - margin: 0 0 58px 0; - padding: 8px 16px; + > * { + background-color: inherit; + } - > * { - background-color: inherit; - } + &.minimized { + max-height: 0; + min-height: initial; + overflow: hidden; + margin: 0; + padding: 0 !important; - &.minimized { - max-height: 0; - min-height: initial; - overflow: hidden; - margin: 0; - padding: 0 !important; + .button-bar-bottom { + height: 0; + overflow: hidden; + padding: 0; + } + } + } - .button-bar-bottom { - height: 0; - overflow: hidden; - padding: 0; - } - } - } + .mat-mdc-dialog-actions { + min-height: initial; + margin-bottom: 0; + } - .mat-mdc-dialog-actions { - min-height: initial; - margin-bottom: 0; - } - - .button-bar .mat-icon { - padding: 8px 0; - } - - .minimized .mat-icon { - transform: rotate(180deg); - padding: 0; - } - - .button-bar-bottom { - position: absolute; - bottom: 0; - left: 0; - right: 0; - padding: 0 16px 16px 16px; - display: flex; - align-items: center; - } - } + .button-bar .mat-icon { + padding: 8px 0; + } + .minimized .mat-icon { + transform: rotate(180deg); + padding: 0; + } + .button-bar-bottom { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: 0 16px 16px 16px; + display: flex; + align-items: center; + } + } } body.dark { - .fixed-dialog { - .mat-mdc-dialog-title { - background-color: $background; - color: $dark-background; - } - } + .fixed-dialog { + .mat-mdc-dialog-title { + background-color: $background; + color: $dark-background; + } + } } diff --git a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog-data.model.ts b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog-data.model.ts index f46ec2bb6aae45274db3e9bd580c476ff072a029..b755995e474367de8a0577a906ab513f138f19f5 100644 --- a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog-data.model.ts +++ b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog-data.model.ts @@ -25,7 +25,7 @@ import { ComponentType } from '@angular/cdk/overlay'; import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; export interface FixedDialogData { - title: string, - component: ComponentType<any>, - vorgang?: VorgangWithEingangResource + title: string; + component: ComponentType<any>; + vorgang?: VorgangWithEingangResource; } diff --git a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.html b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.html index ccb7cd7e63a41ea0ea8b7c39f1389b5c914194a8..ee3cf044ba42da80dc30afedf7329cb0dfd45ecf 100644 --- a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.html +++ b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.html @@ -24,23 +24,29 @@ --> <div mat-dialog-title data-test-id="dialog-header"> - <span>{{ data.title }}</span> - <div class="button-bar"> - <button mat-icon-button data-test-id="min-max-button" - (click)="minimize()" - [ngClass]="{minimized: isMinimized}" - aria-label="Nachricht minimieren"> - <mat-icon>minimize</mat-icon> - </button> + <span>{{ data.title }}</span> + <div class="button-bar"> + <button + mat-icon-button + data-test-id="min-max-button" + (click)="minimize()" + [ngClass]="{ minimized: isMinimized }" + aria-label="Nachricht minimieren" + > + <mat-icon>minimize</mat-icon> + </button> - <button mat-icon-button data-test-id="close-button" - [mat-dialog-close]="true" - aria-label="Nachricht schließen"> - <mat-icon>close</mat-icon> - </button> - </div> + <button + mat-icon-button + data-test-id="close-button" + [mat-dialog-close]="true" + aria-label="Nachricht schließen" + > + <mat-icon>close</mat-icon> + </button> + </div> </div> <mat-dialog-content [ngClass]="{ minimized: isMinimized }" data-test-id="dialog-content"> - <ng-container *ngComponentOutlet="data.component; injector: componentInjector"></ng-container> + <ng-container *ngComponentOutlet="data.component; injector: componentInjector"></ng-container> </mat-dialog-content> diff --git a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.spec.ts index 478e73a89bd8562751ecf3bee180faff9d6ed4b5..7ed131624203c896fb6a1adc5be5fd93525b28d3 100644 --- a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.spec.ts @@ -27,38 +27,33 @@ import { MatDialogModule, MatDialogRef, MAT_DIALOG_DATA } from '@angular/materia import { FixedDialogComponent } from './fixed-dialog.component'; describe('FixedDialogComponent', () => { - let component: FixedDialogComponent; - let fixture: ComponentFixture<FixedDialogComponent>; + let component: FixedDialogComponent; + let fixture: ComponentFixture<FixedDialogComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - MatDialogModule - ], - declarations: [ - FixedDialogComponent, - MatIcon - ], - providers: [ - { - provide: MatDialogRef, - useValue: {} - }, { - provide: MAT_DIALOG_DATA, - useValue: { } - } - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MatDialogModule], + declarations: [FixedDialogComponent, MatIcon], + providers: [ + { + provide: MatDialogRef, + useValue: {}, + }, + { + provide: MAT_DIALOG_DATA, + useValue: {}, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(FixedDialogComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(FixedDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.ts b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.ts index c28044caff7e8080559a3537e24c07b7efaa494e..6d9eec3a38b16fa8e90bd04175723a58d22e1523 100644 --- a/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/fixed-dialog/fixed-dialog.component.ts @@ -27,33 +27,35 @@ import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { FixedDialogData } from './fixed-dialog-data.model'; @Component({ - selector: 'ozgcloud-fixed-dialog', - templateUrl: './fixed-dialog.component.html' + selector: 'ozgcloud-fixed-dialog', + templateUrl: './fixed-dialog.component.html', }) export class FixedDialogComponent { + componentInjector: Injector; - componentInjector: Injector; + isMinimized: boolean; - isMinimized: boolean; + constructor( + @Inject(MAT_DIALOG_DATA) public data: FixedDialogData, + injector: Injector, + ) { + this.componentInjector = Injector.create({ + providers: [ + { + provide: InjectedVorgangInDialog, + useValue: new InjectedVorgangInDialog(this.data.vorgang), + }, + ], + parent: injector, + }); + } - constructor( - @Inject(MAT_DIALOG_DATA) public data: FixedDialogData, - injector: Injector - ) { - this.componentInjector = Injector.create({ - providers: [{ - provide: InjectedVorgangInDialog, - useValue: new InjectedVorgangInDialog(this.data.vorgang) - }], parent: injector - }); - } - - minimize() { - this.isMinimized = !this.isMinimized; - } + minimize() { + this.isMinimized = !this.isMinimized; + } } @Injectable() export class InjectedVorgangInDialog { - constructor(public vorgang: VorgangWithEingangResource) { } + constructor(public vorgang: VorgangWithEingangResource) {} } diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.html b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.html index 7eb27762bdfc3a65d7e74eb827fa4389149f2de0..f24647e97bba9b54d0835c95a8334e011a41574b 100644 --- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.html +++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.html @@ -24,13 +24,11 @@ --> <div class="notification-dialog" data-test-id="connection-timeout-retry-dialog"> - <h1 mat-dialog-title> - <mat-icon data-test-id="icon">error_outline</mat-icon> - <span data-test-id="header">Es ist ein Verbindungsfehler aufgetreten ...</span> - </h1> - <mat-dialog-content> - <p data-test-id="message"> - Ihre Anfrage wird wiederholt - </p> - </mat-dialog-content> + <h1 mat-dialog-title> + <mat-icon data-test-id="icon">error_outline</mat-icon> + <span data-test-id="header">Es ist ein Verbindungsfehler aufgetreten ...</span> + </h1> + <mat-dialog-content> + <p data-test-id="message">Ihre Anfrage wird wiederholt</p> + </mat-dialog-content> </div> diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.scss b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.scss index 921a943426ae3182104f148bebfbf3aaf0361c9b..6d01e5239cf92f45f39c7c0f6344a683f858e0bf 100644 --- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.scss @@ -22,15 +22,15 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ h1 { - font-weight: normal; - font-size: 24px; - display: flex; - align-items: center; + font-weight: normal; + font-size: 24px; + display: flex; + align-items: center; - .mat-icon { - margin-right: 8px; - font-size: 30px; - width: 30px; - height: 30px; - } -} \ No newline at end of file + .mat-icon { + margin-right: 8px; + font-size: 30px; + width: 30px; + height: 30px; + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.spec.ts index 2e0c0ad2a3c83379e6be4fa3d9a9e07995451678..f508e78db93f7b7b7577f530d8c43150021446f7 100644 --- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.spec.ts @@ -29,29 +29,27 @@ import { MockComponent } from 'ng-mocks'; import { ConnectionTimeoutRetryDialogComponent } from './connection-timeout-retry-dialog.component'; describe('ConnectionTimeoutRetryDialogComponent', () => { - let component: ConnectionTimeoutRetryDialogComponent; - let fixture: ComponentFixture<ConnectionTimeoutRetryDialogComponent>; + let component: ConnectionTimeoutRetryDialogComponent; + let fixture: ComponentFixture<ConnectionTimeoutRetryDialogComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - MatDialogModule - ], - declarations: [ConnectionTimeoutRetryDialogComponent, - MatIcon, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MatDialogModule], + declarations: [ + ConnectionTimeoutRetryDialogComponent, + MatIcon, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + ], + }).compileComponents(); + }); - ] - }).compileComponents(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ConnectionTimeoutRetryDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(ConnectionTimeoutRetryDialogComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.ts b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.ts index d405cc627305f4b3d3ec9280017c4e2065cdf948..ff0d1d2a8f8ebf54d3aa491bb4a005ac26785e39 100644 --- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component.ts @@ -24,8 +24,8 @@ import { Component } from '@angular/core'; @Component({ - selector: 'ozgcloud-connection-timeout-retry-dialog', - templateUrl: './connection-timeout-retry-dialog.component.html', - styleUrls: ['./connection-timeout-retry-dialog.component.scss'] + selector: 'ozgcloud-connection-timeout-retry-dialog', + templateUrl: './connection-timeout-retry-dialog.component.html', + styleUrls: ['./connection-timeout-retry-dialog.component.scss'], }) -export class ConnectionTimeoutRetryDialogComponent { } \ No newline at end of file +export class ConnectionTimeoutRetryDialogComponent {} diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.html b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.html index 7085599b3a10a892ad5b88b41c258ed8916afdfe..fdef477758b0b130c87fa6de64d5ace547979356 100644 --- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.html +++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.html @@ -24,17 +24,23 @@ --> <div class="notification-dialog" data-test-id="connection-timeout-retry-fail-dialog"> - <h2 mat-dialog-title> - <mat-icon data-test-id="icon">error_outline</mat-icon> - <span data-test-id="header">Zeitüberschreitung der Verbindung</span> - </h2> - <mat-dialog-content> - <p data-test-id="message"> - Auch nach weiteren Versuchen konnte keine Verbindung aufgebaut werden. <br /> - Bitte wenden Sie sich an Ihren Administrator. - </p> - <ozgcloud-stroked-button-with-spinner tabindex="-1" class="button" icon="refresh" text="Reload" data-test-id="reload-button" - (click)="reload()"> - </ozgcloud-stroked-button-with-spinner> - </mat-dialog-content> + <h2 mat-dialog-title> + <mat-icon data-test-id="icon">error_outline</mat-icon> + <span data-test-id="header">Zeitüberschreitung der Verbindung</span> + </h2> + <mat-dialog-content> + <p data-test-id="message"> + Auch nach weiteren Versuchen konnte keine Verbindung aufgebaut werden. <br /> + Bitte wenden Sie sich an Ihren Administrator. + </p> + <ozgcloud-stroked-button-with-spinner + tabindex="-1" + class="button" + icon="refresh" + text="Reload" + data-test-id="reload-button" + (click)="reload()" + > + </ozgcloud-stroked-button-with-spinner> + </mat-dialog-content> </div> diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.scss b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.scss index 216ac6aa787fb4fc8fb0d1f7638ac76fe522235e..48d8d08527c969b705c347d217d527c30aa6cd39 100644 --- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.scss @@ -22,15 +22,15 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ h2 { - font-weight: normal; - font-size: 24px; - display: flex; - align-items: center; + font-weight: normal; + font-size: 24px; + display: flex; + align-items: center; - .mat-icon { - margin-right: 8px; - font-size: 30px; - width: 30px; - height: 30px; - } -} \ No newline at end of file + .mat-icon { + margin-right: 8px; + font-size: 30px; + width: 30px; + height: 30px; + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.spec.ts index 4b083a5dbb385a912f1fad1ed59300a17e617f39..ff2529780d1015667e3adeb0d532e826dac5931a 100644 --- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.spec.ts @@ -29,28 +29,27 @@ import { MockComponent } from 'ng-mocks'; import { ConnectionTimeoutRetryFailDialogComponent } from './connection-timeout-retry-fail-dialog.component'; describe('ConnectionTimeoutRetryFailDialogComponent', () => { - let component: ConnectionTimeoutRetryFailDialogComponent; - let fixture: ComponentFixture<ConnectionTimeoutRetryFailDialogComponent>; + let component: ConnectionTimeoutRetryFailDialogComponent; + let fixture: ComponentFixture<ConnectionTimeoutRetryFailDialogComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - MatDialogModule - ], - declarations: [ConnectionTimeoutRetryFailDialogComponent, - MatIcon, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent) - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MatDialogModule], + declarations: [ + ConnectionTimeoutRetryFailDialogComponent, + MatIcon, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(ConnectionTimeoutRetryFailDialogComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ConnectionTimeoutRetryFailDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.ts b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.ts index 5ddb7e66fa59e47b21497b664103f667ebce70e2..fac29791d3ae5f5f5c30e5c3776271122f2f55ca 100644 --- a/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component.ts @@ -24,13 +24,12 @@ import { Component } from '@angular/core'; @Component({ - selector: 'ozgcloud-connection-timeout-retry-fail-dialog', - templateUrl: './connection-timeout-retry-fail-dialog.component.html', - styleUrls: ['./connection-timeout-retry-fail-dialog.component.scss'] + selector: 'ozgcloud-connection-timeout-retry-fail-dialog', + templateUrl: './connection-timeout-retry-fail-dialog.component.html', + styleUrls: ['./connection-timeout-retry-fail-dialog.component.scss'], }) export class ConnectionTimeoutRetryFailDialogComponent { - - reload(): void { - window.location.reload(); - } -} \ No newline at end of file + reload(): void { + window.location.reload(); + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.html b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.html index 7700059b1e5e19ca90885225e89865dabdb70176..d07cea93308d33ecfb5af0d917ad1fdfd84629d6 100644 --- a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.html +++ b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.html @@ -23,27 +23,38 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<button mat-icon-button data-test-class="icon-button" - [attr.aria-label]="toolTip ? toolTip : 'Icon Button mit einem ' + (icon ? icon : svgIcon) + ' Icon'" - [disabled]="isDisabled" - [matTooltip]="toolTip" - (click)="clickEmitter.emit($event)" - type="button"> - - <mat-icon *ngIf="icon" data-test-class="icon" - [style.visibility]="isDisabled ? 'hidden' : 'visible'"> - {{ icon }} - </mat-icon> - - <mat-icon *ngIf="svgIcon" data-test-class="icon" - [svgIcon]="svgIcon" - [style.visibility]="isDisabled ? 'hidden' : 'visible'"> - </mat-icon> - - <ozgcloud-spinner - [stateResource]="getStateResource()" [diameter]="22" - [show]="showSpinner" - padding="0"> - </ozgcloud-spinner> - +<button + mat-icon-button + data-test-class="icon-button" + [attr.aria-label]=" + toolTip ? toolTip : 'Icon Button mit einem ' + (icon ? icon : svgIcon) + ' Icon' + " + [disabled]="isDisabled" + [matTooltip]="toolTip" + (click)="clickEmitter.emit($event)" + type="button" +> + <mat-icon + *ngIf="icon" + data-test-class="icon" + [style.visibility]="isDisabled ? 'hidden' : 'visible'" + > + {{ icon }} + </mat-icon> + + <mat-icon + *ngIf="svgIcon" + data-test-class="icon" + [svgIcon]="svgIcon" + [style.visibility]="isDisabled ? 'hidden' : 'visible'" + > + </mat-icon> + + <ozgcloud-spinner + [stateResource]="getStateResource()" + [diameter]="22" + [show]="showSpinner" + padding="0" + > + </ozgcloud-spinner> </button> diff --git a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.scss b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.scss index a69744885ec768c7a76e82dd0be1a96c6eb299f2..1e62fe55a9c5b29fb9f878bc3bd66d158b48686e 100644 --- a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.scss @@ -22,20 +22,20 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - position: relative; + position: relative; } [disabled] { - background-color: rgba(#000, 0.08); + background-color: rgba(#000, 0.08); } ozgcloud-spinner { - position: absolute; - top: 0; - left: 0; - display: flex; - height: 100%; - width: 100%; - justify-content: center; - align-items: center; + position: absolute; + top: 0; + left: 0; + display: flex; + height: 100%; + width: 100%; + justify-content: center; + align-items: center; } diff --git a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.spec.ts index 3478d230354a4ab05fad1cdcf84eb63e59f20f03..e136723944a8a3abc875efe9bf7204cc4407f748 100644 --- a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.spec.ts @@ -30,68 +30,68 @@ import { SpinnerComponent } from '../spinner/spinner.component'; import { IconButtonWithSpinnerComponent } from './icon-button-with-spinner.component'; describe('IconButtonWithSpinnerComponent', () => { - let component: IconButtonWithSpinnerComponent; - let fixture: ComponentFixture<IconButtonWithSpinnerComponent>; + let component: IconButtonWithSpinnerComponent; + let fixture: ComponentFixture<IconButtonWithSpinnerComponent>; - const buttonSelector = '[data-test-class="icon-button"]' - const iconSelector = '[data-test-class="icon"]' + const buttonSelector = '[data-test-class="icon-button"]'; + const iconSelector = '[data-test-class="icon"]'; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - IconButtonWithSpinnerComponent, - MatIcon, - MockDirective(MatTooltipDirective), - MockComponent(SpinnerComponent) - ], - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + IconButtonWithSpinnerComponent, + MatIcon, + MockDirective(MatTooltipDirective), + MockComponent(SpinnerComponent), + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(IconButtonWithSpinnerComponent); - component = fixture.componentInstance; - component.icon = 'edit'; + beforeEach(() => { + fixture = TestBed.createComponent(IconButtonWithSpinnerComponent); + component = fixture.componentInstance; + component.icon = 'edit'; - fixture.detectChanges(); - }); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('Button', () => { - it('should NOT disabled initial', () => { - const button = fixture.nativeElement.querySelector(buttonSelector); - component.stateResource = createEmptyStateResource(); - fixture.detectChanges(); + describe('Button', () => { + it('should NOT disabled initial', () => { + const button = fixture.nativeElement.querySelector(buttonSelector); + component.stateResource = createEmptyStateResource(); + fixture.detectChanges(); - expect(button).not.toBeDisabled() - }); + expect(button).not.toBeDisabled(); + }); - it('should disabled if loading', () => { - const button = fixture.nativeElement.querySelector(buttonSelector); - component.stateResource = createEmptyStateResource(true); - fixture.detectChanges(); + it('should disabled if loading', () => { + const button = fixture.nativeElement.querySelector(buttonSelector); + component.stateResource = createEmptyStateResource(true); + fixture.detectChanges(); - expect(button).toBeDisabled(); - }); - }) + expect(button).toBeDisabled(); + }); + }); - describe('Icon', () => { - it('should visible initial', () => { - const icon = fixture.nativeElement.querySelector(iconSelector); - component.stateResource = createEmptyStateResource(); - fixture.detectChanges(); + describe('Icon', () => { + it('should visible initial', () => { + const icon = fixture.nativeElement.querySelector(iconSelector); + component.stateResource = createEmptyStateResource(); + fixture.detectChanges(); - expect(icon).toBeVisible(); - }); + expect(icon).toBeVisible(); + }); - it('should not visible if loading', () => { - const icon = fixture.nativeElement.querySelector(iconSelector); - component.stateResource = createEmptyStateResource(true); - fixture.detectChanges(); + it('should not visible if loading', () => { + const icon = fixture.nativeElement.querySelector(iconSelector); + component.stateResource = createEmptyStateResource(true); + fixture.detectChanges(); - expect(icon).not.toBeVisible(); - }); - }) + expect(icon).not.toBeVisible(); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.ts b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.ts index 24c155b0f5be6be9ab85c9875a8be49bfda82405..aac12cd1ba42b1995fc8c188498c08f5ab0c7211 100644 --- a/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/icon-button-with-spinner/icon-button-with-spinner.component.ts @@ -27,25 +27,24 @@ import { Resource } from '@ngxp/rest'; import { isNil } from 'lodash-es'; @Component({ - selector: 'ozgcloud-icon-button-with-spinner', - templateUrl: './icon-button-with-spinner.component.html', - styleUrls: ['./icon-button-with-spinner.component.scss'] + selector: 'ozgcloud-icon-button-with-spinner', + templateUrl: './icon-button-with-spinner.component.html', + styleUrls: ['./icon-button-with-spinner.component.scss'], }) export class IconButtonWithSpinnerComponent { + @Input() icon: string; + @Input() svgIcon: string; + @Input() stateResource: StateResource<Resource>; + @Input() toolTip: string = ''; + @Input() showSpinner: boolean = false; - @Input() icon: string; - @Input() svgIcon: string; - @Input() stateResource: StateResource<Resource>; - @Input() toolTip: string = ''; - @Input() showSpinner: boolean = false; + @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); - @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); + get isDisabled(): boolean { + return this.showSpinner || this.getStateResource().loading; + } - get isDisabled(): boolean { - return this.showSpinner || this.getStateResource().loading; - } - - getStateResource(): StateResource<Resource> { - return isNil(this.stateResource) ? createEmptyStateResource<Resource>() : this.stateResource; - } + getStateResource(): StateResource<Resource> { + return isNil(this.stateResource) ? createEmptyStateResource<Resource>() : this.stateResource; + } } diff --git a/alfa-client/libs/ui/src/lib/ui/mattooltip/mattooltip.directive.spec.ts b/alfa-client/libs/ui/src/lib/ui/mattooltip/mattooltip.directive.spec.ts index 6ccbe0db7cb07a98b04d907aa9d80911aac1db19..2ebf4a59ad1ce37a0135097f9181b2b35fbc703a 100644 --- a/alfa-client/libs/ui/src/lib/ui/mattooltip/mattooltip.directive.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/mattooltip/mattooltip.directive.spec.ts @@ -23,34 +23,36 @@ */ import { ElementRef } from '@angular/core'; import faker from '@faker-js/faker'; -import { MatTooltipClassDirective, MatTooltipDirective, MatTooltipDisabledDirective } from './mattooltip.directive'; +import { + MatTooltipClassDirective, + MatTooltipDirective, + MatTooltipDisabledDirective, +} from './mattooltip.directive'; describe('MatToolTip Directives', () => { + describe('MatTooltipDirective', () => { + const el: ElementRef = <ElementRef>{}; + const tooltipText: string = faker.lorem.text(); - describe('MatTooltipDirective', () => { - const el: ElementRef = <ElementRef>{}; - const tooltipText: string = faker.lorem.text(); + it('should create an instance', () => { + const directive = new MatTooltipDirective(el); + expect(directive).toBeTruthy(); + }); + }); - it('should create an instance', () => { - const directive = new MatTooltipDirective(el); - expect(directive).toBeTruthy(); - }); - }); + describe('MatTooltipDisabledDirective', () => { + const el: ElementRef = <ElementRef>{}; - describe('MatTooltipDisabledDirective', () => { - const el: ElementRef = <ElementRef>{}; + it('should create an instance', () => { + const directive = new MatTooltipDisabledDirective(el); + expect(directive).toBeTruthy(); + }); + }); - it('should create an instance', () => { - const directive = new MatTooltipDisabledDirective(el); - expect(directive).toBeTruthy(); - }); - }); - - describe('MatTooltipClassDirective', () => { - - it('should create an instance', () => { - const directive = new MatTooltipClassDirective(); - expect(directive).toBeTruthy(); - }); - }); -}) \ No newline at end of file + describe('MatTooltipClassDirective', () => { + it('should create an instance', () => { + const directive = new MatTooltipClassDirective(); + expect(directive).toBeTruthy(); + }); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/ui/mattooltip/mattooltip.directive.ts b/alfa-client/libs/ui/src/lib/ui/mattooltip/mattooltip.directive.ts index 2081a5f548dbf79afaf396c4ca18421e9438ec82..593d0c45b3a996c3eb87d347bfd92553bed9c3fe 100644 --- a/alfa-client/libs/ui/src/lib/ui/mattooltip/mattooltip.directive.ts +++ b/alfa-client/libs/ui/src/lib/ui/mattooltip/mattooltip.directive.ts @@ -32,44 +32,44 @@ import { EMPTY_STRING } from '@alfa-client/tech-shared'; * verwendet werden. * * Implementiert sind nur die Directiven, die bei uns zum Einsatz kommen. -*/ + */ const titleAttribute: string = 'title'; -const ariaDescribedBy: string = 'aria-describedby' +const ariaDescribedBy: string = 'aria-describedby'; @Directive({ - selector: '[matTooltip]' + selector: '[matTooltip]', }) export class MatTooltipDirective implements OnChanges { - @Input() matTooltip: string = EMPTY_STRING; + @Input() matTooltip: string = EMPTY_STRING; - constructor(private el: ElementRef) { } + constructor(private el: ElementRef) {} - ngOnChanges(): void { - this.el.nativeElement.setAttribute(titleAttribute, this.matTooltip); - this.el.nativeElement.setAttribute(ariaDescribedBy, this.matTooltip); - } + ngOnChanges(): void { + this.el.nativeElement.setAttribute(titleAttribute, this.matTooltip); + this.el.nativeElement.setAttribute(ariaDescribedBy, this.matTooltip); + } } @Directive({ - selector: '[matTooltipDisabled]' + selector: '[matTooltipDisabled]', }) export class MatTooltipDisabledDirective implements OnInit { - @Input() matTooltipDisabled: boolean = false; + @Input() matTooltipDisabled: boolean = false; - constructor(private el: ElementRef) { } + constructor(private el: ElementRef) {} - ngOnInit(): void { - if (this.matTooltipDisabled) { - this.el.nativeElement.setAttribute(titleAttribute, EMPTY_STRING); - this.el.nativeElement.setAttribute(ariaDescribedBy, EMPTY_STRING); - } - } + ngOnInit(): void { + if (this.matTooltipDisabled) { + this.el.nativeElement.setAttribute(titleAttribute, EMPTY_STRING); + this.el.nativeElement.setAttribute(ariaDescribedBy, EMPTY_STRING); + } + } } @Directive({ - selector: '[matTooltipClass]' + selector: '[matTooltipClass]', }) export class MatTooltipClassDirective { - @Input() matTooltipClass: string = EMPTY_STRING; + @Input() matTooltipClass: string = EMPTY_STRING; } diff --git a/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.html b/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.html index c4f56f748c42f39ff147652ceadab53dd39ba14a..2a127b78127ac601a4ba02e88f6b428795d26970 100644 --- a/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.html +++ b/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.html @@ -1,12 +1,12 @@ -<ng-container *ngIf="iconSizeBig, else standardSize"> - <ozgcloud-svgicon-big [svgIcon]="icon"></ozgcloud-svgicon-big> +<ng-container *ngIf="iconSizeBig; else standardSize"> + <ozgcloud-svgicon-big [svgIcon]="icon"></ozgcloud-svgicon-big> </ng-container> <ng-template #standardSize> - <ozgcloud-svgicon [svgIcon]="icon"></ozgcloud-svgicon> + <ozgcloud-svgicon [svgIcon]="icon"></ozgcloud-svgicon> </ng-template> <div> - <div class="headline">{{headline}}</div> - <div class="text">{{text}}</div> - <ng-content></ng-content> -</div> \ No newline at end of file + <div class="headline">{{ headline }}</div> + <div class="text">{{ text }}</div> + <ng-content></ng-content> +</div> diff --git a/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.scss b/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.scss index 0f391c61c9c487c0ac09b43faf8e7048b3d5fc67..41f783ee481e672a91b6b728e277ef0ccbf7f868 100644 --- a/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.scss @@ -3,32 +3,32 @@ $menuItemBorder: 1px solid #eeeeee; :host { - display: flex; - padding: 0.5rem 1rem; - background-color: #fff; - border-top: $menuItemBorder; - border-bottom: $menuItemBorder; + display: flex; + padding: 0.5rem 1rem; + background-color: #fff; + border-top: $menuItemBorder; + border-bottom: $menuItemBorder; } ozgcloud-svgicon, ozgcloud-svgicon-big { - margin-right: 1rem; + margin-right: 1rem; } .headline { - font-weight: 500; - font-size: 16px; + font-weight: 500; + font-size: 16px; } .text { - font-weight: 400; - font-size: 14px; - margin-bottom: 10px; + font-weight: 400; + font-size: 14px; + margin-bottom: 10px; } :host-context(.dark) { - color: #fff; - background-color: #393939; - border-top-color: rgba(255, 255, 255, 0.12); - border-bottom-color: rgba(255, 255, 255, 0.12); -} \ No newline at end of file + color: #fff; + background-color: #393939; + border-top-color: rgba(255, 255, 255, 0.12); + border-bottom-color: rgba(255, 255, 255, 0.12); +} diff --git a/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.spec.ts index 1095e98c2d1ffbdcd6699e601ea8c55226d21c16..4cba0e1af53fd592e3d12974745f9e2104a4d4f4 100644 --- a/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.spec.ts @@ -4,24 +4,24 @@ import { MockComponent } from 'ng-mocks'; import { MenuItemComponent } from './menu-item.component'; describe('MenuItemComponent', () => { - let component: MenuItemComponent; - let fixture: ComponentFixture<MenuItemComponent>; + let component: MenuItemComponent; + let fixture: ComponentFixture<MenuItemComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MenuItemComponent, - MockComponent(OzgcloudIconComponent), - MockComponent(OzgcloudSvgIconComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + MenuItemComponent, + MockComponent(OzgcloudIconComponent), + MockComponent(OzgcloudSvgIconComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(MenuItemComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(MenuItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.ts b/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.ts index f14bc644aecabe1ba0ad957582c28a9513b449b3..c76591a0fb27929ebd0bf9da749f74e7ac9cb9c3 100644 --- a/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/menu-item/menu-item.component.ts @@ -1,15 +1,13 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-menu-item', - templateUrl: './menu-item.component.html', - styleUrls: ['./menu-item.component.scss'] + selector: 'ozgcloud-menu-item', + templateUrl: './menu-item.component.html', + styleUrls: ['./menu-item.component.scss'], }) export class MenuItemComponent { - - @Input() headline: string; - @Input() text: string; - @Input() icon: string; - @Input() iconSizeBig: boolean = false; - + @Input() headline: string; + @Input() text: string; + @Input() icon: string; + @Input() iconSizeBig: boolean = false; } diff --git a/alfa-client/libs/ui/src/lib/ui/messages.ts b/alfa-client/libs/ui/src/lib/ui/messages.ts index 6a0b6ba87cd898dbb99113265081ffde8451a837..35f77d1e3c0b4cb1134b96853eaead712319de2b 100644 --- a/alfa-client/libs/ui/src/lib/ui/messages.ts +++ b/alfa-client/libs/ui/src/lib/ui/messages.ts @@ -22,6 +22,6 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum Messages { - HTTP_STATUS_FORBIDDEN = 'Die Aktion konnte wegen fehlender Berechtigungen nicht durchgeführt werden', - HTTP_USER_MANAGER_SERVICE_UNAVAILABLE = 'Der UserManager ist zurzeit leider nicht verfügbar.' -} \ No newline at end of file + HTTP_STATUS_FORBIDDEN = 'Die Aktion konnte wegen fehlender Berechtigungen nicht durchgeführt werden', + HTTP_USER_MANAGER_SERVICE_UNAVAILABLE = 'Der UserManager ist zurzeit leider nicht verfügbar.', +} diff --git a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.html b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.html index c539d1e9c542e0c4eb3156a68ed660ca2afe0119..bc9c9e6857fe8bd80fdc1f1bdb85c0ece4f12b5a 100644 --- a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.html +++ b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.html @@ -24,17 +24,26 @@ --> <h1 mat-dialog-title> - <mat-icon data-test-id="error-icon">error_outline</mat-icon> - <span data-test-id="error-header">Es ist ein Fehler aufgetreten ...</span> + <mat-icon data-test-id="error-icon">error_outline</mat-icon> + <span data-test-id="error-header">Es ist ein Fehler aufgetreten ...</span> </h1> <mat-dialog-content> - <p data-test-id="error-message" class="error-message"> - Wir sind nicht ganz sicher, was schiefgelaufen ist. Der Fehler <span *ngIf="showId()">(ID: {{ data.issues[0].exceptionId }})</span> wurde unserem Support gemeldet. Bitte starten sie die Anwendung neu. - </p> - <a href="/" tabindex="-1" class="button"> - <ozgcloud-stroked-button-with-spinner icon="refresh" text="Neu starten"></ozgcloud-stroked-button-with-spinner> - </a> - <ozgcloud-stroked-button-with-spinner icon="logout" text="Abmelden" data-test-id="logout-button" - (clickEmitter)="authService.logOut()"> - </ozgcloud-stroked-button-with-spinner> + <p data-test-id="error-message" class="error-message"> + Wir sind nicht ganz sicher, was schiefgelaufen ist. Der Fehler + <span *ngIf="showId()">(ID: {{ data.issues[0].exceptionId }})</span> wurde unserem Support + gemeldet. Bitte starten sie die Anwendung neu. + </p> + <a href="/" tabindex="-1" class="button"> + <ozgcloud-stroked-button-with-spinner + icon="refresh" + text="Neu starten" + ></ozgcloud-stroked-button-with-spinner> + </a> + <ozgcloud-stroked-button-with-spinner + icon="logout" + text="Abmelden" + data-test-id="logout-button" + (clickEmitter)="authService.logOut()" + > + </ozgcloud-stroked-button-with-spinner> </mat-dialog-content> diff --git a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.scss b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.scss index b7646cc7feccde2cf346600e7d2fdd609afd84b0..cc051218ffa5dbef0d2c3ad72469e6e01b8baeb9 100644 --- a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.scss @@ -22,21 +22,21 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ h1 { - display: flex; - align-items: center; + display: flex; + align-items: center; - .mat-icon { - margin-right: 8px; - font-size: 30px; - width: 30px; - height: 30px; - } + .mat-icon { + margin-right: 8px; + font-size: 30px; + width: 30px; + height: 30px; + } } .button { - margin-right: 16px; + margin-right: 16px; } .error-message { - margin-bottom: 20px; + margin-bottom: 20px; } diff --git a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.spec.ts index bdcc606d51acbf5ce57b7917f058076d2e68d98a..e36771e50e4be57cb20e5aa2322cf3b4711bd539 100644 --- a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.spec.ts @@ -33,60 +33,59 @@ import { MockComponent } from 'ng-mocks'; import { InternalServerErrorDialogComponent } from './internal-server-error-dialog.component'; describe('InternalServerErrorDialogComponent', () => { - let component: InternalServerErrorDialogComponent; - let fixture: ComponentFixture<InternalServerErrorDialogComponent>; + let component: InternalServerErrorDialogComponent; + let fixture: ComponentFixture<InternalServerErrorDialogComponent>; - let dialogData: any; + let dialogData: any; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - InternalServerErrorDialogComponent, - MatIcon, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent) - ], - imports: [ - MatDialogModule - ], - providers: [ - { - provide: MatDialogRef, - useValue: {} - }, - { - provide: OAuthService, - useValue: mock(OAuthService) - }, - { - provide: MAT_DIALOG_DATA, - useValue: dialogData - } - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + InternalServerErrorDialogComponent, + MatIcon, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + ], + imports: [MatDialogModule], + providers: [ + { + provide: MatDialogRef, + useValue: {}, + }, + { + provide: OAuthService, + useValue: mock(OAuthService), + }, + { + provide: MAT_DIALOG_DATA, + useValue: dialogData, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(InternalServerErrorDialogComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(InternalServerErrorDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('exception id', () => { - it('should be hidden', () => { - expect(fixture.nativeElement).not.toHaveTextContent('ID:'); - }) + describe('exception id', () => { + it('should be hidden', () => { + expect(fixture.nativeElement).not.toHaveTextContent('ID:'); + }); - it('should be visible', () => { - const exceptionId = faker.datatype.uuid(); - dialogData = { error: { ...{ issues: [createIssue()] }, id: exceptionId } }; - fixture.detectChanges(); + it('should be visible', () => { + const exceptionId = faker.datatype.uuid(); + dialogData = { error: { ...{ issues: [createIssue()] }, id: exceptionId } }; + fixture.detectChanges(); - expect(fixture.nativeElement).not.toHaveTextContent(`ID: ${dialogData.error.issues[0].exceptionId}`); - }) - }) + expect(fixture.nativeElement).not.toHaveTextContent( + `ID: ${dialogData.error.issues[0].exceptionId}`, + ); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.ts b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.ts index 39b24e2a09413f035e00b843132472584249d8f6..767fb5cc076e16a736f7e89e2a751ed5d77d07d0 100644 --- a/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/notification/internal-server-error-dialog/internal-server-error-dialog.component.ts @@ -27,15 +27,17 @@ import { ApiError, hasExceptionId } from '@alfa-client/tech-shared'; import { OAuthService } from 'angular-oauth2-oidc'; @Component({ - selector: 'ozgcloud-internal-server-error-dialog', - templateUrl: './internal-server-error-dialog.component.html', - styleUrls: ['./internal-server-error-dialog.component.scss'] + selector: 'ozgcloud-internal-server-error-dialog', + templateUrl: './internal-server-error-dialog.component.html', + styleUrls: ['./internal-server-error-dialog.component.scss'], }) export class InternalServerErrorDialogComponent { + constructor( + @Inject(MAT_DIALOG_DATA) public data: ApiError, + public authService: OAuthService, + ) {} - constructor(@Inject(MAT_DIALOG_DATA) public data: ApiError, public authService: OAuthService) { } - - showId(): boolean { - return hasExceptionId(this.data); - } + showId(): boolean { + return hasExceptionId(this.data); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.html b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.html index 41f09d9d52572cdf2efbf3c0fbdd833ccd0a0731..d5da9183f237f187be716d871c9181e5691438d5 100644 --- a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.html +++ b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.html @@ -1,11 +1,14 @@ -<a mat-button data-test-id="open-url-in-new-window" - [href]="url" - [target]="targetName" - [attr.aria-label]="text" - [matTooltip]="tooltip" - [color]="'primary'" - [title]="tooltip" - class="button"> - <mat-icon>open_in_new</mat-icon> - <span>{{ text }}</span> +<a + mat-button + data-test-id="open-url-in-new-window" + [href]="url" + [target]="targetName" + [attr.aria-label]="text" + [matTooltip]="tooltip" + [color]="'primary'" + [title]="tooltip" + class="button" +> + <mat-icon>open_in_new</mat-icon> + <span>{{ text }}</span> </a> diff --git a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.scss b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.scss index 0a99fb3418e543df0aec2bb285645dded123f24a..b93b9abafd0e579ef34ffd50f46c30fd6725fda7 100644 --- a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.scss @@ -1,3 +1,3 @@ a { - padding: 0 15px; -} \ No newline at end of file + padding: 0 15px; +} diff --git a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.spec.ts index 5259139f5253662dc2df9666b306b5eef8105478..6cc98dc00f04d65694178148b0f4b8a27a9fed7c 100644 --- a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.spec.ts @@ -1,26 +1,23 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { OpenUrlButtonComponent } from './open-url-button.component'; -import { MockComponent } from "ng-mocks"; +import { MockComponent } from 'ng-mocks'; describe('OpenUrlButtonComponent', () => { - let component: OpenUrlButtonComponent; - let fixture: ComponentFixture<OpenUrlButtonComponent>; + let component: OpenUrlButtonComponent; + let fixture: ComponentFixture<OpenUrlButtonComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - OpenUrlButtonComponent, - MockComponent(OpenUrlButtonComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [OpenUrlButtonComponent, MockComponent(OpenUrlButtonComponent)], + }).compileComponents(); - fixture = TestBed.createComponent(OpenUrlButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(OpenUrlButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.ts b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.ts index 73fd7c5c227a82ce9bc492b280da55a9ca123954..3f369d1764dcf0a41b082b422b97fa64d6d0281f 100644 --- a/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/open-url-button/open-url-button.component.ts @@ -1,15 +1,14 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-open-url-button', - templateUrl: './open-url-button.component.html', - styleUrls: ['./open-url-button.component.scss'], + selector: 'ozgcloud-open-url-button', + templateUrl: './open-url-button.component.html', + styleUrls: ['./open-url-button.component.scss'], }) export class OpenUrlButtonComponent { - - @Input() icon: string; - @Input() url: string; - @Input() text: string; - @Input() targetName: string; - @Input() tooltip: string; + @Input() icon: string; + @Input() url: string; + @Input() text: string; + @Input() targetName: string; + @Input() tooltip: string; } diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.html index 789a3767deec331d79ac450bb554cdf6369cac3f..2e8bb15fd072ee4da74b4a072597fd079991efa8 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.html +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.html @@ -23,21 +23,24 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<button mat-button data-test-class="icon-button" [attr.data-test-id]="dataTestId" - [color]="color" - [type]="type" - [disabled]="isDisabled" - [matTooltip]="toolTip" - [class.with-text]="text" - (click)="clickEmitter.emit($event)"> - - <ozgcloud-button-content - [icon]="icon" - [svgIcon]="svgIcon" - [text]="text" - [stateResource]="stateResource" - [showSpinner]="showSpinner" - [isDisabled]="isDisabled"> - </ozgcloud-button-content> - +<button + mat-button + data-test-class="icon-button" + [attr.data-test-id]="dataTestId" + [color]="color" + [type]="type" + [disabled]="isDisabled" + [matTooltip]="toolTip" + [class.with-text]="text" + (click)="clickEmitter.emit($event)" +> + <ozgcloud-button-content + [icon]="icon" + [svgIcon]="svgIcon" + [text]="text" + [stateResource]="stateResource" + [showSpinner]="showSpinner" + [isDisabled]="isDisabled" + > + </ozgcloud-button-content> </button> diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.scss b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.scss index 8069fed25cd27089f993e6233b46148263192a6e..d8b80df0506a2ab68a7bb527da8d44a0de3d178e 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.scss @@ -22,10 +22,10 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ button { - min-width: 36px; - min-height: 36px; - padding: 0; - &.with-text { - padding: 0 15px; - } -} \ No newline at end of file + min-width: 36px; + min-height: 36px; + padding: 0; + &.with-text { + padding: 0 15px; + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.spec.ts index 1ded0801c248b23436378f817c58cecb18679d50..cee700af33230e1aa016f18ec929cae9f2b12799 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.spec.ts @@ -34,128 +34,127 @@ import { OzgcloudButtonWithSpinnerComponent } from './ozgcloud-button-with-spinn import * as ResourceUtils from 'libs/tech-shared/src/lib/resource/resource.util'; describe('OzgcloudButtonWithSpinnerComponent', () => { - let component: OzgcloudButtonWithSpinnerComponent; - let fixture: ComponentFixture<OzgcloudButtonWithSpinnerComponent>; + let component: OzgcloudButtonWithSpinnerComponent; + let fixture: ComponentFixture<OzgcloudButtonWithSpinnerComponent>; - const buttonSelector: string = getDataTestClassOf('icon-button'); + const buttonSelector: string = getDataTestClassOf('icon-button'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MatButton, - MatRipple, - OzgcloudButtonWithSpinnerComponent, - MatTooltipDirective, - MockComponent(OzgcloudButtonContentComponent) - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + MatButton, + MatRipple, + OzgcloudButtonWithSpinnerComponent, + MatTooltipDirective, + MockComponent(OzgcloudButtonContentComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(OzgcloudButtonWithSpinnerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(OzgcloudButtonWithSpinnerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('isDisabled', () => { - it('should return true if showSpinner is true and stateResource is loading', () => { - component.showSpinner = true; - component.stateResource.loading = true; + describe('isDisabled', () => { + it('should return true if showSpinner is true and stateResource is loading', () => { + component.showSpinner = true; + component.stateResource.loading = true; - const result: boolean = component.isDisabled; + const result: boolean = component.isDisabled; - expect(result).toBeTruthy(); - }) + expect(result).toBeTruthy(); + }); - it('should return true if showSpinner is false and stateResource is loading', () => { - component.showSpinner = false; - component.stateResource.loading = true; + it('should return true if showSpinner is false and stateResource is loading', () => { + component.showSpinner = false; + component.stateResource.loading = true; - const result: boolean = component.isDisabled; + const result: boolean = component.isDisabled; - expect(result).toBeTruthy(); - }) + expect(result).toBeTruthy(); + }); - it('should return true if showSpinner is true and stateResource is not loading', () => { - component.showSpinner = true; - component.stateResource.loading = false; + it('should return true if showSpinner is true and stateResource is not loading', () => { + component.showSpinner = true; + component.stateResource.loading = false; - const result: boolean = component.isDisabled; + const result: boolean = component.isDisabled; - expect(result).toBeTruthy(); - }) + expect(result).toBeTruthy(); + }); - it('should return false if showSpinner is false and stateResource is not loading', () => { - component.showSpinner = false; - component.stateResource.loading = false; + it('should return false if showSpinner is false and stateResource is not loading', () => { + component.showSpinner = false; + component.stateResource.loading = false; - const result: boolean = component.isDisabled; + const result: boolean = component.isDisabled; - expect(result).toBeFalsy(); - }) - }) + expect(result).toBeFalsy(); + }); + }); - describe('ngOnInit', () => { - it('should call getStateResource()', () => { - component.getStateResource = jest.fn(); + describe('ngOnInit', () => { + it('should call getStateResource()', () => { + component.getStateResource = jest.fn(); - component.ngOnInit(); + component.ngOnInit(); - expect(component.getStateResource).toHaveBeenCalled(); - }) - }) + expect(component.getStateResource).toHaveBeenCalled(); + }); + }); - describe('getStateResource', () => { - it('should call createEmptyStateResource if stateResource is undefined', () => { - const spy = jest.spyOn(ResourceUtils, 'createEmptyStateResource'); - component.stateResource = undefined; + describe('getStateResource', () => { + it('should call createEmptyStateResource if stateResource is undefined', () => { + const spy = jest.spyOn(ResourceUtils, 'createEmptyStateResource'); + component.stateResource = undefined; - component.getStateResource(); + component.getStateResource(); - expect(spy).toHaveBeenCalled(); - }) + expect(spy).toHaveBeenCalled(); + }); - it('should call createEmptyStateResource if stateResource is null', () => { - const spy = jest.spyOn(ResourceUtils, 'createEmptyStateResource'); - component.stateResource = null; + it('should call createEmptyStateResource if stateResource is null', () => { + const spy = jest.spyOn(ResourceUtils, 'createEmptyStateResource'); + component.stateResource = null; - component.getStateResource(); + component.getStateResource(); - expect(spy).toHaveBeenCalled(); - }) + expect(spy).toHaveBeenCalled(); + }); - it('should return non empty stateResource', () => { - component.stateResource = ResourceUtils.createStateResource(createCommandResource()); + it('should return non empty stateResource', () => { + component.stateResource = ResourceUtils.createStateResource(createCommandResource()); - component.getStateResource(); + component.getStateResource(); - const valid: boolean = ResourceUtils.isValidStateResouce(component.stateResource); - expect(valid).toBeTruthy(); - }) - }) + const valid: boolean = ResourceUtils.isValidStateResouce(component.stateResource); + expect(valid).toBeTruthy(); + }); + }); - describe('Button', () => { + describe('Button', () => { + it('should NOT be disabled initialy', () => { + component.stateResource = ResourceUtils.createEmptyStateResource(); + fixture.detectChanges(); - it('should NOT be disabled initialy', () => { - component.stateResource = ResourceUtils.createEmptyStateResource(); - fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(buttonSelector); - const button = fixture.nativeElement.querySelector(buttonSelector); + expect(button).not.toBeDisabled(); + }); - expect(button).not.toBeDisabled() - }); + it('should be disabled if loading', () => { + component.stateResource = ResourceUtils.createEmptyStateResource(true); + fixture.detectChanges(); - it('should be disabled if loading', () => { - component.stateResource = ResourceUtils.createEmptyStateResource(true); - fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(buttonSelector); - const button = fixture.nativeElement.querySelector(buttonSelector); - - expect(button).toBeDisabled(); - }); - }) -}); \ No newline at end of file + expect(button).toBeDisabled(); + }); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.ts index 802ed077a31e3b4332c832f931b121af31ca8471..4eb45c30387f922359949585ac3629ed8a8709c3 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-button-with-spinner/ozgcloud-button-with-spinner.component.ts @@ -27,33 +27,32 @@ import { Resource } from '@ngxp/rest'; import { isNil } from 'lodash-es'; @Component({ - selector: 'ozgcloud-button-with-spinner', - templateUrl: './ozgcloud-button-with-spinner.component.html', - styleUrls: ['./ozgcloud-button-with-spinner.component.scss'] + selector: 'ozgcloud-button-with-spinner', + templateUrl: './ozgcloud-button-with-spinner.component.html', + styleUrls: ['./ozgcloud-button-with-spinner.component.scss'], }) export class OzgcloudButtonWithSpinnerComponent implements OnInit { + @Input() icon: string; + @Input() svgIcon: string; + @Input() text: string; + @Input() stateResource: StateResource<Resource>; + @Input() color: string = 'primary'; + @Input() type: 'button' | 'submit' = 'button'; + @Input() toolTip: string = ''; + @Input() dataTestId: string; + @Input() showSpinner: boolean = false; - @Input() icon: string; - @Input() svgIcon: string; - @Input() text: string; - @Input() stateResource: StateResource<Resource>; - @Input() color: string = 'primary'; - @Input() type: 'button' | 'submit' = 'button'; - @Input() toolTip: string = ''; - @Input() dataTestId: string; - @Input() showSpinner: boolean = false; + @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); - @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); + get isDisabled(): boolean { + return this.showSpinner || this.stateResource.loading; + } - get isDisabled(): boolean { - return this.showSpinner || this.stateResource.loading; - } + ngOnInit(): void { + this.stateResource = this.getStateResource(); + } - ngOnInit(): void { - this.stateResource = this.getStateResource(); - } - - getStateResource(): StateResource<Resource> { - return isNil(this.stateResource) ? createEmptyStateResource<Resource>() : this.stateResource; - } -} \ No newline at end of file + getStateResource(): StateResource<Resource> { + return isNil(this.stateResource) ? createEmptyStateResource<Resource>() : this.stateResource; + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.html index 80962be53c865da19bdce56209f849dad1994b35..b0ecf6c5de127cddea84861601dde60fb1e2efb1 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.html +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.html @@ -23,11 +23,14 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<button mat-icon-button data-test-class="icon-button-primary" - [attr.aria-label]="ariaLabel" - [matTooltip]="tooltip" - (click)="clickEmitter.emit($event)" - color="primary" - type="button"> - <mat-icon data-test-class="icon" [svgIcon]="svgIcon"></mat-icon> +<button + mat-icon-button + data-test-class="icon-button-primary" + [attr.aria-label]="ariaLabel" + [matTooltip]="tooltip" + (click)="clickEmitter.emit($event)" + color="primary" + type="button" +> + <mat-icon data-test-class="icon" [svgIcon]="svgIcon"></mat-icon> </button> diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.scss b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.scss index b23ad1177000d7387abd85d56be30e3ba969ff7d..af82db8c6ff99b292d748f41a135b0e811f8a879 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.scss @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - position: relative; -} \ No newline at end of file + position: relative; +} diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.spec.ts index 649235c6d32f340f342fdcb2776e82469b7c0769..91c58127ea53ad7eb01d20ff19ea86c472a3de47 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.spec.ts @@ -12,62 +12,60 @@ jest.mock('@alfa-client/tech-shared'); const createAriaLabelForIconButtonMock = createAriaLabelForIconButton as jest.Mock; describe('IconButtonPrimaryWithSpinnerComponent', () => { - let component: OzgcloudIconButtonPrimaryComponent; - let fixture: ComponentFixture<OzgcloudIconButtonPrimaryComponent>; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [MatIconTestingModule], - declarations: [ - OzgcloudIconButtonPrimaryComponent, - MockComponent(MatIcon), - MockDirective(MatTooltipDirective) - ], - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(OzgcloudIconButtonPrimaryComponent); - component = fixture.componentInstance; - component.svgIcon = 'edit'; - - fixture.detectChanges(); - }) - - it('should create', () => { - expect(component).toBeTruthy(); - }) - - describe('ngOnInit', () => { - - it('should create aria label', () => { - component.ngOnInit(); - - expect(createAriaLabelForIconButtonMock).toHaveBeenCalledWith(component.tooltip, component.svgIcon); - }) - - it('should set aria label', () => { - const ariaLabel = 'Eine Taste'; - createAriaLabelForIconButtonMock.mockReturnValue(ariaLabel); - - component.ngOnInit(); - - expect(component.ariaLabel).toBe(ariaLabel); - }) - - }) - - describe('onClick', () => { - - it('should emit event', () => { - const element = getElementFromFixture(fixture, getDataTestClassOf('icon-button-primary')); - const emitSpy = jest.spyOn(component.clickEmitter, 'emit'); - - element.click(); - - expect(emitSpy).toHaveBeenCalled(); - }) - - }) - + let component: OzgcloudIconButtonPrimaryComponent; + let fixture: ComponentFixture<OzgcloudIconButtonPrimaryComponent>; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [MatIconTestingModule], + declarations: [ + OzgcloudIconButtonPrimaryComponent, + MockComponent(MatIcon), + MockDirective(MatTooltipDirective), + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(OzgcloudIconButtonPrimaryComponent); + component = fixture.componentInstance; + component.svgIcon = 'edit'; + + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should create aria label', () => { + component.ngOnInit(); + + expect(createAriaLabelForIconButtonMock).toHaveBeenCalledWith( + component.tooltip, + component.svgIcon, + ); + }); + + it('should set aria label', () => { + const ariaLabel = 'Eine Taste'; + createAriaLabelForIconButtonMock.mockReturnValue(ariaLabel); + + component.ngOnInit(); + + expect(component.ariaLabel).toBe(ariaLabel); + }); + }); + + describe('onClick', () => { + it('should emit event', () => { + const element = getElementFromFixture(fixture, getDataTestClassOf('icon-button-primary')); + const emitSpy = jest.spyOn(component.clickEmitter, 'emit'); + + element.click(); + + expect(emitSpy).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.ts index 7886e6448051de4cfcc65877c2ffec1e2eaa97da..73cfb10c7b75f34560e396596daca1edf7a36956 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-icon-button-primary/ozgcloud-icon-button-primary.component.ts @@ -3,20 +3,19 @@ import { createAriaLabelForIconButton, StateResource } from '@alfa-client/tech-s import { Resource } from '@ngxp/rest'; @Component({ - selector: 'ozgcloud-icon-button-primary', - templateUrl: './ozgcloud-icon-button-primary.component.html', - styleUrls: ['./ozgcloud-icon-button-primary.component.scss'] + selector: 'ozgcloud-icon-button-primary', + templateUrl: './ozgcloud-icon-button-primary.component.html', + styleUrls: ['./ozgcloud-icon-button-primary.component.scss'], }) export class OzgcloudIconButtonPrimaryComponent implements OnInit { + @Input() svgIcon: string; + @Input() stateResource: StateResource<Resource>; + @Input() tooltip = ''; + @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); - @Input() svgIcon: string; - @Input() stateResource: StateResource<Resource>; - @Input() tooltip = ''; - @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); + ariaLabel = ''; - ariaLabel = ''; - - ngOnInit(): void { - this.ariaLabel = createAriaLabelForIconButton(this.tooltip, this.svgIcon); - } + ngOnInit(): void { + this.ariaLabel = createAriaLabelForIconButton(this.tooltip, this.svgIcon); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.html index 15328b6c0e37c960cd29faf3b9ba3d5b49ccff52..fd31e239161797bd14faee219135ded4d229b6c0 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.html +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.html @@ -23,21 +23,23 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<button mat-stroked-button data-test-class="icon-button" [attr.data-test-id]="dataTestId" - [color]="color" - [type]="type" - [disabled]="isDisabled" - [matTooltip]="toolTip" - [class.with-text]="text" - (click)="clickEmitter.emit($event)"> - - <ozgcloud-button-content - [icon]="icon" - [svgIcon]="svgIcon" - [text]="text" - [stateResource]="stateResource" - [showSpinner]="showSpinner" - [isDisabled]="isDisabled" - ></ozgcloud-button-content> - +<button + mat-stroked-button + data-test-class="icon-button" + [attr.data-test-id]="dataTestId" + [color]="color" + [type]="type" + [disabled]="isDisabled" + [matTooltip]="toolTip" + [class.with-text]="text" + (click)="clickEmitter.emit($event)" +> + <ozgcloud-button-content + [icon]="icon" + [svgIcon]="svgIcon" + [text]="text" + [stateResource]="stateResource" + [showSpinner]="showSpinner" + [isDisabled]="isDisabled" + ></ozgcloud-button-content> </button> diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.scss b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.scss index 8069fed25cd27089f993e6233b46148263192a6e..d8b80df0506a2ab68a7bb527da8d44a0de3d178e 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.scss @@ -22,10 +22,10 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ button { - min-width: 36px; - min-height: 36px; - padding: 0; - &.with-text { - padding: 0 15px; - } -} \ No newline at end of file + min-width: 36px; + min-height: 36px; + padding: 0; + &.with-text { + padding: 0 15px; + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.spec.ts index d0ef6e5df6a0779a2b7d29ff87ac26863229c978..5abd6101c3f6af641abaffd7a0293a77f17dd908 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.spec.ts @@ -34,128 +34,127 @@ import { OzgcloudStrokedButtonWithSpinnerComponent } from './ozgcloud-stroked-bu import * as ResourceUtils from 'libs/tech-shared/src/lib/resource/resource.util'; describe('OzgcloudStrokedButtonWithSpinnerComponent', () => { - let component: OzgcloudStrokedButtonWithSpinnerComponent; - let fixture: ComponentFixture<OzgcloudStrokedButtonWithSpinnerComponent>; + let component: OzgcloudStrokedButtonWithSpinnerComponent; + let fixture: ComponentFixture<OzgcloudStrokedButtonWithSpinnerComponent>; - const buttonSelector: string = getDataTestClassOf('icon-button'); + const buttonSelector: string = getDataTestClassOf('icon-button'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MatButton, - MatRipple, - OzgcloudStrokedButtonWithSpinnerComponent, - MatTooltipDirective, - MockComponent(OzgcloudButtonContentComponent) - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + MatButton, + MatRipple, + OzgcloudStrokedButtonWithSpinnerComponent, + MatTooltipDirective, + MockComponent(OzgcloudButtonContentComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(OzgcloudStrokedButtonWithSpinnerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(OzgcloudStrokedButtonWithSpinnerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('isDisabled', () => { - it('should return true if showSpinner is true and stateResource is loading', () => { - component.showSpinner = true; - component.stateResource.loading = true; + describe('isDisabled', () => { + it('should return true if showSpinner is true and stateResource is loading', () => { + component.showSpinner = true; + component.stateResource.loading = true; - const result: boolean = component.isDisabled; + const result: boolean = component.isDisabled; - expect(result).toBeTruthy(); - }) + expect(result).toBeTruthy(); + }); - it('should return true if showSpinner is false and stateResource is loading', () => { - component.showSpinner = false; - component.stateResource.loading = true; + it('should return true if showSpinner is false and stateResource is loading', () => { + component.showSpinner = false; + component.stateResource.loading = true; - const result: boolean = component.isDisabled; + const result: boolean = component.isDisabled; - expect(result).toBeTruthy(); - }) + expect(result).toBeTruthy(); + }); - it('should return true if showSpinner is true and stateResource is not loading', () => { - component.showSpinner = true; - component.stateResource.loading = false; + it('should return true if showSpinner is true and stateResource is not loading', () => { + component.showSpinner = true; + component.stateResource.loading = false; - const result: boolean = component.isDisabled; + const result: boolean = component.isDisabled; - expect(result).toBeTruthy(); - }) + expect(result).toBeTruthy(); + }); - it('should return false if showSpinner is false and stateResource is not loading', () => { - component.showSpinner = false; - component.stateResource.loading = false; + it('should return false if showSpinner is false and stateResource is not loading', () => { + component.showSpinner = false; + component.stateResource.loading = false; - const result: boolean = component.isDisabled; + const result: boolean = component.isDisabled; - expect(result).toBeFalsy(); - }) - }) + expect(result).toBeFalsy(); + }); + }); - describe('ngOnInit', () => { - it('should call getStateResource()', () => { - component.getStateResource = jest.fn(); + describe('ngOnInit', () => { + it('should call getStateResource()', () => { + component.getStateResource = jest.fn(); - component.ngOnInit(); + component.ngOnInit(); - expect(component.getStateResource).toHaveBeenCalled(); - }) - }) + expect(component.getStateResource).toHaveBeenCalled(); + }); + }); - describe('getStateResource', () => { - it('should call createEmptyStateResource if stateResource is undefined', () => { - const spy = jest.spyOn(ResourceUtils, 'createEmptyStateResource'); - component.stateResource = undefined; + describe('getStateResource', () => { + it('should call createEmptyStateResource if stateResource is undefined', () => { + const spy = jest.spyOn(ResourceUtils, 'createEmptyStateResource'); + component.stateResource = undefined; - component.getStateResource(); + component.getStateResource(); - expect(spy).toHaveBeenCalled(); - }) + expect(spy).toHaveBeenCalled(); + }); - it('should call createEmptyStateResource if stateResource is null', () => { - const spy = jest.spyOn(ResourceUtils, 'createEmptyStateResource'); - component.stateResource = null; + it('should call createEmptyStateResource if stateResource is null', () => { + const spy = jest.spyOn(ResourceUtils, 'createEmptyStateResource'); + component.stateResource = null; - component.getStateResource(); + component.getStateResource(); - expect(spy).toHaveBeenCalled(); - }) + expect(spy).toHaveBeenCalled(); + }); - it('should return non empty stateResource', () => { - component.stateResource = ResourceUtils.createStateResource(createCommandResource()); + it('should return non empty stateResource', () => { + component.stateResource = ResourceUtils.createStateResource(createCommandResource()); - component.getStateResource(); + component.getStateResource(); - const valid: boolean = ResourceUtils.isValidStateResouce(component.stateResource); - expect(valid).toBeTruthy(); - }) - }) + const valid: boolean = ResourceUtils.isValidStateResouce(component.stateResource); + expect(valid).toBeTruthy(); + }); + }); - describe('Button', () => { + describe('Button', () => { + it('should NOT be disabled initialy', () => { + component.stateResource = ResourceUtils.createEmptyStateResource(); + fixture.detectChanges(); - it('should NOT be disabled initialy', () => { - component.stateResource = ResourceUtils.createEmptyStateResource(); - fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(buttonSelector); - const button = fixture.nativeElement.querySelector(buttonSelector); + expect(button).not.toBeDisabled(); + }); - expect(button).not.toBeDisabled() - }); + it('should be disabled if loading', () => { + component.stateResource = ResourceUtils.createEmptyStateResource(true); + fixture.detectChanges(); - it('should be disabled if loading', () => { - component.stateResource = ResourceUtils.createEmptyStateResource(true); - fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(buttonSelector); - const button = fixture.nativeElement.querySelector(buttonSelector); - - expect(button).toBeDisabled(); - }); - }) -}); \ No newline at end of file + expect(button).toBeDisabled(); + }); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.ts index 1d6b8671f01db449127ad8e7cdc288272308af96..338481b983e63ca10c701e6d693b928fbe70e739 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/ozgcloud-stroked-button-with-spinner/ozgcloud-stroked-button-with-spinner.component.ts @@ -27,34 +27,33 @@ import { Resource } from '@ngxp/rest'; import { isNil } from 'lodash-es'; @Component({ - selector: 'ozgcloud-stroked-button-with-spinner', - templateUrl: './ozgcloud-stroked-button-with-spinner.component.html', - styleUrls: ['./ozgcloud-stroked-button-with-spinner.component.scss'] + selector: 'ozgcloud-stroked-button-with-spinner', + templateUrl: './ozgcloud-stroked-button-with-spinner.component.html', + styleUrls: ['./ozgcloud-stroked-button-with-spinner.component.scss'], }) export class OzgcloudStrokedButtonWithSpinnerComponent implements OnInit { + @Input() icon: string; + @Input() svgIcon: string; + @Input() text: string; + @Input() stateResource: StateResource<Resource>; + @Input() color: string = 'primary'; + @Input() type: 'button' | 'submit' = 'button'; + @Input() toolTip: string = ''; + @Input() dataTestId: string; + @Input() showSpinner: boolean = false; + @Input() strokedButton: boolean = true; - @Input() icon: string; - @Input() svgIcon: string; - @Input() text: string; - @Input() stateResource: StateResource<Resource>; - @Input() color: string = 'primary'; - @Input() type: 'button' | 'submit' = 'button'; - @Input() toolTip: string = ''; - @Input() dataTestId: string; - @Input() showSpinner: boolean = false; - @Input() strokedButton: boolean = true; + @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); - @Output() public clickEmitter: EventEmitter<MouseEvent> = new EventEmitter<MouseEvent>(); + get isDisabled(): boolean { + return this.showSpinner || this.stateResource.loading; + } - get isDisabled(): boolean { - return this.showSpinner || this.stateResource.loading; - } + ngOnInit(): void { + this.stateResource = this.getStateResource(); + } - ngOnInit(): void { - this.stateResource = this.getStateResource(); - } - - getStateResource(): StateResource<Resource> { - return isNil(this.stateResource) ? createEmptyStateResource<Resource>() : this.stateResource; - } -} \ No newline at end of file + getStateResource(): StateResource<Resource> { + return isNil(this.stateResource) ? createEmptyStateResource<Resource>() : this.stateResource; + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.html index fd800b47fd620f96e27880e6f165680d1939e277..43d399abb04e8fc3417be4b88a13c6d5d2d5b810 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.html +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.html @@ -1,19 +1,22 @@ -<mat-icon *ngIf="icon" data-test-class="icon" - [class.with-text]="text" - [style.visibility]="isDisabled ? 'hidden' : 'visible'"> - {{ icon }} +<mat-icon + *ngIf="icon" + data-test-class="icon" + [class.with-text]="text" + [style.visibility]="isDisabled ? 'hidden' : 'visible'" +> + {{ icon }} </mat-icon> -<mat-icon *ngIf="svgIcon" data-test-class="icon" - [class.with-text]="text" - [svgIcon]="svgIcon" - [style.visibility]="isDisabled ? 'hidden' : 'visible'"> +<mat-icon + *ngIf="svgIcon" + data-test-class="icon" + [class.with-text]="text" + [svgIcon]="svgIcon" + [style.visibility]="isDisabled ? 'hidden' : 'visible'" +> </mat-icon> <span *ngIf="text" data-test-class="button-with-spinner-text">{{ text }}</span> -<ozgcloud-spinner - [diameter]="22" padding="0" - [stateResource]="stateResource" - [show]="showSpinner"> -</ozgcloud-spinner> \ No newline at end of file +<ozgcloud-spinner [diameter]="22" padding="0" [stateResource]="stateResource" [show]="showSpinner"> +</ozgcloud-spinner> diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.scss b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.scss index 99053feec562dcbc112ae4b253a6dd3b318c3021..73891f28375df67527bfde3e40edeff7bf71af61 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.scss @@ -1,22 +1,21 @@ $rightMargin: 8px; :host { - display: flex; - align-items: center; - justify-content: center; + display: flex; + align-items: center; + justify-content: center; } mat-icon.with-text { - margin-right: $rightMargin; + margin-right: $rightMargin; } ozgcloud-spinner { - position: absolute; - top: 0; - display: flex; - height: 100%; - width: 100%; - justify-content: flex-start; - align-items: center; + position: absolute; + top: 0; + display: flex; + height: 100%; + width: 100%; + justify-content: flex-start; + align-items: center; } - diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.spec.ts index dcec09dddd50d60748ba045794ac94b4c3a72060..0d7191f4a2a005f0795c02b975b1ef6fad37cee3 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.spec.ts @@ -6,74 +6,67 @@ import { SpinnerComponent } from '../../../spinner/spinner.component'; import { OzgcloudButtonContentComponent } from './ozgcloud-button-content.component'; describe('OzgcloudButtonContentComponent', () => { - let component: OzgcloudButtonContentComponent; - let fixture: ComponentFixture<OzgcloudButtonContentComponent>; + let component: OzgcloudButtonContentComponent; + let fixture: ComponentFixture<OzgcloudButtonContentComponent>; - const iconSelector: string = getDataTestClassOf('icon'); - const text: string = getDataTestClassOf('button-with-spinner-text'); + const iconSelector: string = getDataTestClassOf('icon'); + const text: string = getDataTestClassOf('button-with-spinner-text'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MatIcon, - MockComponent(SpinnerComponent), - OzgcloudButtonContentComponent - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [MatIcon, MockComponent(SpinnerComponent), OzgcloudButtonContentComponent], + }).compileComponents(); - fixture = TestBed.createComponent(OzgcloudButtonContentComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(OzgcloudButtonContentComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('Icon', () => { + describe('Icon', () => { + beforeEach(() => { + component.icon = 'add'; + }); - beforeEach(() => { - component.icon = 'add'; - }) + it('should be visible', () => { + component.isDisabled = false; + fixture.detectChanges(); - it('should be visible', () => { - component.isDisabled = false; - fixture.detectChanges(); + const icon = fixture.nativeElement.querySelector(iconSelector); - const icon = fixture.nativeElement.querySelector(iconSelector); + expect(icon).toBeVisible(); + }); - expect(icon).toBeVisible(); - }); + it('should not be visible', () => { + component.isDisabled = true; + fixture.detectChanges(); - it('should not be visible', () => { - component.isDisabled = true; - fixture.detectChanges(); + const icon = fixture.nativeElement.querySelector(iconSelector); - const icon = fixture.nativeElement.querySelector(iconSelector); + expect(icon).not.toBeVisible(); + }); + }); - expect(icon).not.toBeVisible(); - }); - }) + describe('Text', () => { + it('should be visible if exist', () => { + component.text = 'Test text'; + fixture.detectChanges(); - describe('Text', () => { + const textElement = fixture.nativeElement.querySelector(text); - it('should be visible if exist', () => { - component.text = 'Test text'; - fixture.detectChanges(); + expect(textElement).toBeInTheDocument(); + }); - const textElement = fixture.nativeElement.querySelector(text); + it('should not be visible if is null', () => { + component.text = null; + fixture.detectChanges(); - expect(textElement).toBeInTheDocument(); - }); - - it('should not be visible if is null', () => { - component.text = null; - fixture.detectChanges(); - - const textElement = fixture.nativeElement.querySelector(text); - - expect(textElement).not.toBeInTheDocument(); - }); - }) + const textElement = fixture.nativeElement.querySelector(text); + expect(textElement).not.toBeInTheDocument(); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.ts index 9ef4f088e5248f2170cd011e4eedb1a885852619..8aaee54a4cc36db3b8bfab21cf6ee28c2b4dc57b 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-button/shared/ozgcloud-button-content/ozgcloud-button-content.component.ts @@ -3,17 +3,15 @@ import { StateResource } from '@alfa-client/tech-shared'; import { Resource } from '@ngxp/rest'; @Component({ - selector: 'ozgcloud-button-content', - templateUrl: './ozgcloud-button-content.component.html', - styleUrls: ['./ozgcloud-button-content.component.scss'], + selector: 'ozgcloud-button-content', + templateUrl: './ozgcloud-button-content.component.html', + styleUrls: ['./ozgcloud-button-content.component.scss'], }) export class OzgcloudButtonContentComponent { - - @Input() icon: string; - @Input() svgIcon: string; - @Input() text: string; - @Input() stateResource: StateResource<Resource>; - @Input() showSpinner: boolean = false; - @Input() isDisabled: boolean = false; - + @Input() icon: string; + @Input() svgIcon: string; + @Input() text: string; + @Input() stateResource: StateResource<Resource>; + @Input() showSpinner: boolean = false; + @Input() isDisabled: boolean = false; } diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.html index 3050a73c5789be2e4f144d80f0acceb522454a23..bf4c33cef671e494ad6d16f6a71d3f0b09801ad7 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.html +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.html @@ -1 +1 @@ -<mat-icon>{{icon}}</mat-icon> \ No newline at end of file +<mat-icon>{{ icon }}</mat-icon> diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.scss b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.scss index 95f1adbcfaa0000d68178e5b675f9c768cc3146c..cd6deb28863e552a21fb661587de07d4544bdb3c 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.scss @@ -1,6 +1,6 @@ @import 'variables'; :host { - display: inline-block; - height: $iconHeight; -} \ No newline at end of file + display: inline-block; + height: $iconHeight; +} diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.spec.ts index ae61720bb322510d118e5df2a47579827ec44fb9..5bee2df59ccb409bed55f0c53df19638a466897b 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.spec.ts @@ -3,23 +3,20 @@ import { MatIcon } from '@angular/material/icon'; import { OzgcloudIconComponent } from './ozgcloud-icon.component'; describe('OzgcloudIconComponent', () => { - let component: OzgcloudIconComponent; - let fixture: ComponentFixture<OzgcloudIconComponent>; + let component: OzgcloudIconComponent; + let fixture: ComponentFixture<OzgcloudIconComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - OzgcloudIconComponent, - MatIcon - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [OzgcloudIconComponent, MatIcon], + }).compileComponents(); - fixture = TestBed.createComponent(OzgcloudIconComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(OzgcloudIconComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.ts index ae5cd032fd99b06625c69f576b7ce38f8fee6cd2..00ce4c1262cff7174c09bf9126524fdffd31689a 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-icon/ozgcloud-icon.component.ts @@ -1,11 +1,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-icon', - templateUrl: './ozgcloud-icon.component.html', - styleUrls: ['./ozgcloud-icon.component.scss'], + selector: 'ozgcloud-icon', + templateUrl: './ozgcloud-icon.component.html', + styleUrls: ['./ozgcloud-icon.component.scss'], }) export class OzgcloudIconComponent { - - @Input() icon: string; + @Input() icon: string; } diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.html index b928c4f047bc3c9ed41f41f969cbaf1225f0757d..3b26d58152cca031d5a38685681d5256d082f14d 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.html +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.html @@ -1,4 +1,3 @@ <mat-menu #menu="matMenu" class="menu"> - <ng-content></ng-content> + <ng-content></ng-content> </mat-menu> - diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.spec.ts index d2a8dbed4d5ccc6c6531fc8b7369b511d08645a8..659ca944d23e9b9538b61fe4614f876b47756a0a 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.spec.ts @@ -3,21 +3,21 @@ import { MatMenuModule } from '@angular/material/menu'; import { OzgcloudMenuComponent } from './ozgcloud-menu.component'; describe('OzgcloudMenuComponent', () => { - let component: OzgcloudMenuComponent; - let fixture: ComponentFixture<OzgcloudMenuComponent>; + let component: OzgcloudMenuComponent; + let fixture: ComponentFixture<OzgcloudMenuComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [OzgcloudMenuComponent], - imports: [MatMenuModule] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [OzgcloudMenuComponent], + imports: [MatMenuModule], + }).compileComponents(); - fixture = TestBed.createComponent(OzgcloudMenuComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(OzgcloudMenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.ts index c2c27f55cd47ae1148b2b265b7cb3d14955f8f17..5922ba8b9ace317e094b62916737d42d166c43c6 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-menu/ozgcloud-menu.component.ts @@ -2,11 +2,10 @@ import { Component, ViewChild } from '@angular/core'; import { MatMenu } from '@angular/material/menu'; @Component({ - selector: 'ozgcloud-menu', - templateUrl: './ozgcloud-menu.component.html', - styleUrls: ['./ozgcloud-menu.component.scss'], + selector: 'ozgcloud-menu', + templateUrl: './ozgcloud-menu.component.html', + styleUrls: ['./ozgcloud-menu.component.scss'], }) export class OzgcloudMenuComponent { - - @ViewChild('menu', { static: true }) matMenu: MatMenu; + @ViewChild('menu', { static: true }) matMenu: MatMenu; } diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.html index d5066021493c17c4bdf2717de51e828a0f4542bd..57d857be3edfa27ed96999e340d8bcc34838172f 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.html +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.html @@ -1,8 +1,9 @@ <ozgcloud-icon-button-primary - *ngIf="isPasteSupported" - [tooltip]="tooltip" - svgIcon="paste_from_clipboard" - class="paste_icon" - (clickEmitter)="onPaste()" - data-test-id="paste_from_clipboard"> -</ozgcloud-icon-button-primary> \ No newline at end of file + *ngIf="isPasteSupported" + [tooltip]="tooltip" + svgIcon="paste_from_clipboard" + class="paste_icon" + (clickEmitter)="onPaste()" + data-test-id="paste_from_clipboard" +> +</ozgcloud-icon-button-primary> diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.spec.ts index 52c30cc53d5ca29106776ee7e4638a2f2bae812f..2173708cb5c899e1a77535619409507f2917957d 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.spec.ts @@ -18,78 +18,75 @@ const readTextMock = jest.fn().mockResolvedValue(clipboardContent); Object.assign(navigator, { clipboard: { readText: readTextMock } }); describe('OzgcloudPasteTextButtonComponent', () => { - let component: OzgcloudPasteTextButtonComponent; - let fixture: ComponentFixture<OzgcloudPasteTextButtonComponent>; - - function getMatIconElement(): HTMLElement { - return getElementFromFixture(fixture, getDataTestIdOf('paste_from_clipboard')); - } - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [MatIconTestingModule], - declarations: [ - OzgcloudPasteTextButtonComponent, - MockComponent(MatIcon), - MockComponent(OzgcloudIconButtonPrimaryComponent), - MockDirective(MatTooltipDirective), - ] - }).compileComponents(); - - fixture = TestBed.createComponent(OzgcloudPasteTextButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - component.pasteEmitter = <any>mock(EventEmitter); - }) - - it('should create', () => { - expect(component).toBeTruthy(); - }) - - it('should have no paste supported by default', () => { - expect(component.isPasteSupported).toBeFalsy(); - }) - - it('should not render if paste not supported', () => { - const matIcon = getMatIconElement(); - - expect(matIcon).not.toBeInstanceOf(HTMLElement); - }) - - describe('ngOnInit', () => { - - it('should check if clipboard read is supported', () => { - component.ngOnInit(); - - expect(isClipboardReadSupported).toHaveBeenCalled(); - }) - - it('should set paste support', () => { - isClipboardReadSupportedMock.mockReturnValue(true); - - component.ngOnInit(); - - expect(component.isPasteSupported).toBeTruthy(); - }) - - it('should render if paste supported', () => { - isClipboardReadSupportedMock.mockReturnValue(true); - fixture.detectChanges(); - const matIcon = getMatIconElement(); - - component.ngOnInit(); - - expect(matIcon).toBeInstanceOf(HTMLElement); - }) - }) - - describe('onPaste', () => { - - it('should emit clipboard content', async () => { - await component.onPaste(); - - expect(component.pasteEmitter.emit).toHaveBeenCalledWith(clipboardContent); - }) - - }) -}) + let component: OzgcloudPasteTextButtonComponent; + let fixture: ComponentFixture<OzgcloudPasteTextButtonComponent>; + + function getMatIconElement(): HTMLElement { + return getElementFromFixture(fixture, getDataTestIdOf('paste_from_clipboard')); + } + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MatIconTestingModule], + declarations: [ + OzgcloudPasteTextButtonComponent, + MockComponent(MatIcon), + MockComponent(OzgcloudIconButtonPrimaryComponent), + MockDirective(MatTooltipDirective), + ], + }).compileComponents(); + + fixture = TestBed.createComponent(OzgcloudPasteTextButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + component.pasteEmitter = <any>mock(EventEmitter); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + it('should have no paste supported by default', () => { + expect(component.isPasteSupported).toBeFalsy(); + }); + + it('should not render if paste not supported', () => { + const matIcon = getMatIconElement(); + + expect(matIcon).not.toBeInstanceOf(HTMLElement); + }); + + describe('ngOnInit', () => { + it('should check if clipboard read is supported', () => { + component.ngOnInit(); + + expect(isClipboardReadSupported).toHaveBeenCalled(); + }); + + it('should set paste support', () => { + isClipboardReadSupportedMock.mockReturnValue(true); + + component.ngOnInit(); + + expect(component.isPasteSupported).toBeTruthy(); + }); + + it('should render if paste supported', () => { + isClipboardReadSupportedMock.mockReturnValue(true); + fixture.detectChanges(); + const matIcon = getMatIconElement(); + + component.ngOnInit(); + + expect(matIcon).toBeInstanceOf(HTMLElement); + }); + }); + + describe('onPaste', () => { + it('should emit clipboard content', async () => { + await component.onPaste(); + + expect(component.pasteEmitter.emit).toHaveBeenCalledWith(clipboardContent); + }); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.ts index 50c4b0d183703da63f88898bf5ff508c6c749304..722118e1a606dafcc55ddabab9c0813d944f5785 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-paste-text-button/ozgcloud-paste-text-button.component.ts @@ -2,23 +2,21 @@ import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; import { isClipboardReadSupported } from '@alfa-client/tech-shared'; @Component({ - selector: 'ozgcloud-paste-text-button', - templateUrl: './ozgcloud-paste-text-button.component.html', - styleUrls: ['./ozgcloud-paste-text-button.component.scss'], + selector: 'ozgcloud-paste-text-button', + templateUrl: './ozgcloud-paste-text-button.component.html', + styleUrls: ['./ozgcloud-paste-text-button.component.scss'], }) export class OzgcloudPasteTextButtonComponent implements OnInit { + @Input() tooltip: string; + @Output() pasteEmitter: EventEmitter<string> = new EventEmitter<string>(); - @Input() tooltip: string; - @Output() pasteEmitter: EventEmitter<string> = new EventEmitter<string>(); + isPasteSupported = false; - isPasteSupported = false; - - ngOnInit(): void { - this.isPasteSupported = isClipboardReadSupported(); - } - - async onPaste(): Promise<void> { - this.pasteEmitter.emit(await navigator.clipboard.readText()); - } + ngOnInit(): void { + this.isPasteSupported = isClipboardReadSupported(); + } + async onPaste(): Promise<void> { + this.pasteEmitter.emit(await navigator.clipboard.readText()); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.html index aaeb16a50d1f3b26ebc2e60047c746fce767602d..4698f6d4b9b1154459bf3802866c2ec11b95da24 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.html +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.html @@ -1,3 +1,3 @@ <a mat-button extended [routerLink]="routerLinkPath" data-test-class="routing-button"> - <ng-content></ng-content> -</a> \ No newline at end of file + <ng-content></ng-content> +</a> diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.spec.ts index 7f25578e040a26992b8d79259fd12be893e15c8b..c13000f704e40ef732f01ec5b8ff372c874f69c3 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.spec.ts @@ -3,23 +3,21 @@ import { RouterTestingModule } from '@angular/router/testing'; import { OzgcloudRoutingButtonComponent } from './ozgcloud-routing-button.component'; describe('OzgcloudRoutingButtonComponent', () => { - let component: OzgcloudRoutingButtonComponent; - let fixture: ComponentFixture<OzgcloudRoutingButtonComponent>; + let component: OzgcloudRoutingButtonComponent; + let fixture: ComponentFixture<OzgcloudRoutingButtonComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [OzgcloudRoutingButtonComponent], - imports:[ - RouterTestingModule - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [OzgcloudRoutingButtonComponent], + imports: [RouterTestingModule], + }).compileComponents(); - fixture = TestBed.createComponent(OzgcloudRoutingButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(OzgcloudRoutingButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.ts index b3ca23af21510dd946bd047337a48eea7edd9d60..97ab8a682e44f02ba7cbcc6e3498596deb2a8688 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-routing-button/ozgcloud-routing-button.component.ts @@ -1,11 +1,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-routing-button', - templateUrl: './ozgcloud-routing-button.component.html', - styleUrls: ['./ozgcloud-routing-button.component.scss'], + selector: 'ozgcloud-routing-button', + templateUrl: './ozgcloud-routing-button.component.html', + styleUrls: ['./ozgcloud-routing-button.component.scss'], }) export class OzgcloudRoutingButtonComponent { - - @Input() routerLinkPath: string; + @Input() routerLinkPath: string; } diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.html index 6782a720b2a88459811f06cc712a3153fc85de5e..a44febfc5b6442851bb2a2ac81526b38a773e38e 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.html +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.html @@ -1 +1 @@ -<mat-icon [svgIcon]="svgIcon"></mat-icon> \ No newline at end of file +<mat-icon [svgIcon]="svgIcon"></mat-icon> diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.scss b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.scss index bb74370c138b6951676665b828823668b4c4e94f..37837884462ac90784fd00d0c598568d88a58c15 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.scss @@ -1,5 +1,5 @@ mat-icon { - display: block; - width: 32px; - height: 40px; + display: block; + width: 32px; + height: 40px; } diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.spec.ts index 652c6588305ee961486f62bd26897685184801af..4c8e75a14124586938db0ec5fe73436b9152d685 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.spec.ts @@ -3,23 +3,20 @@ import { MatIcon } from '@angular/material/icon'; import { OzgcloudSvgIconBigComponent } from './ozgcloud-svgicon-big.component'; describe('OzgcloudSvgIconBigComponent', () => { - let component: OzgcloudSvgIconBigComponent; - let fixture: ComponentFixture<OzgcloudSvgIconBigComponent>; + let component: OzgcloudSvgIconBigComponent; + let fixture: ComponentFixture<OzgcloudSvgIconBigComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - OzgcloudSvgIconBigComponent, - MatIcon - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [OzgcloudSvgIconBigComponent, MatIcon], + }).compileComponents(); - fixture = TestBed.createComponent(OzgcloudSvgIconBigComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(OzgcloudSvgIconBigComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.ts index aa1cbe0825ce867a54d807d7b35c207835200e04..285f9e48c6937ca904a7df9a7d7de5f26eaeaa4f 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon-big/ozgcloud-svgicon-big.component.ts @@ -1,12 +1,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-svgicon-big', - templateUrl: './ozgcloud-svgicon-big.component.html', - styleUrls: ['./ozgcloud-svgicon-big.component.scss'], + selector: 'ozgcloud-svgicon-big', + templateUrl: './ozgcloud-svgicon-big.component.html', + styleUrls: ['./ozgcloud-svgicon-big.component.scss'], }) export class OzgcloudSvgIconBigComponent { - - @Input() svgIcon: string; - + @Input() svgIcon: string; } diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.html b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.html index 6782a720b2a88459811f06cc712a3153fc85de5e..a44febfc5b6442851bb2a2ac81526b38a773e38e 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.html +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.html @@ -1 +1 @@ -<mat-icon [svgIcon]="svgIcon"></mat-icon> \ No newline at end of file +<mat-icon [svgIcon]="svgIcon"></mat-icon> diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.scss b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.scss index f5dcc5118a881284bce6596638869ffb66884dd2..9efaf377206b31ea456c5fb103e0d0f167715759 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.scss @@ -1,3 +1,3 @@ mat-icon { - display: block; + display: block; } diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.spec.ts index ad9a9292720c4c3f74d0845b6487cf66d04d4605..bff8651ffd4d1d7b2e842404e9efa84704b6fcf2 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.spec.ts @@ -3,23 +3,20 @@ import { MatIcon } from '@angular/material/icon'; import { OzgcloudSvgIconComponent } from './ozgcloud-svgicon.component'; describe('OzgcloudSvgIconComponent', () => { - let component: OzgcloudSvgIconComponent; - let fixture: ComponentFixture<OzgcloudSvgIconComponent>; + let component: OzgcloudSvgIconComponent; + let fixture: ComponentFixture<OzgcloudSvgIconComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - OzgcloudSvgIconComponent, - MatIcon - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [OzgcloudSvgIconComponent, MatIcon], + }).compileComponents(); - fixture = TestBed.createComponent(OzgcloudSvgIconComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(OzgcloudSvgIconComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.ts b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.ts index f59052f04474bd2e753f8481ac5e6a11c6527885..165e74a5d23a74aa300a060ca503a18c96aed537 100644 --- a/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/ozgcloud-svgicon/ozgcloud-svgicon.component.ts @@ -1,12 +1,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'ozgcloud-svgicon', - templateUrl: './ozgcloud-svgicon.component.html', - styleUrls: ['./ozgcloud-svgicon.component.scss'], + selector: 'ozgcloud-svgicon', + templateUrl: './ozgcloud-svgicon.component.html', + styleUrls: ['./ozgcloud-svgicon.component.scss'], }) export class OzgcloudSvgIconComponent { - - @Input() svgIcon: string; - + @Input() svgIcon: string; } diff --git a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html index a65d308f36677c8f84b14ba207e369d188892828..35b6f0a7b1391e12cb557a80b6addf15897a4df5 100644 --- a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html +++ b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.html @@ -24,5 +24,5 @@ --> <div *ngIf="isVisible" class="progressbar-overlay" data-test-class="progressbar-overlay"> - <mat-progress-bar data-test-id="progress-bar" mode="indeterminate"></mat-progress-bar> + <mat-progress-bar data-test-id="progress-bar" mode="indeterminate"></mat-progress-bar> </div> diff --git a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.scss b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.scss index 13cb7b90ee4e488e27528e92c82361d105994a27..cf91b8ba65dcc63695c7df660b642937891292b8 100644 --- a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.scss @@ -22,13 +22,13 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .progressbar-overlay { - display: flex; - width: 100%; - height: 100%; - position: fixed; - top: 0; - left: 0; - background-color: rgba(#000, 0.08); - z-index: 100; - align-items: flex-end; + display: flex; + width: 100%; + height: 100%; + position: fixed; + top: 0; + left: 0; + background-color: rgba(#000, 0.08); + z-index: 100; + align-items: flex-end; } diff --git a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.spec.ts index 947534116008c912025808a0cb8b65ca82326d15..c71f231595ee4439b4a84002368d43bd567acae5 100644 --- a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.spec.ts @@ -27,56 +27,53 @@ import { createEmptyStateResource } from '@alfa-client/tech-shared'; import { ProgressBarComponent } from './progress-bar.component'; describe('ProgressBarComponent', () => { - let component: ProgressBarComponent; - let fixture: ComponentFixture<ProgressBarComponent>; + let component: ProgressBarComponent; + let fixture: ComponentFixture<ProgressBarComponent>; - const overlaySelector = '[data-test-class="progressbar-overlay"]' + const overlaySelector = '[data-test-class="progressbar-overlay"]'; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - ProgressBarComponent, - MatProgressBar - ] - }) - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ProgressBarComponent, MatProgressBar], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(ProgressBarComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ProgressBarComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('progressbar overlay', () => { - it('should NOT be visible if NOT loading and NOT loaded', () => { - component.stateResource = { ...createEmptyStateResource(false), loaded: false }; - fixture.detectChanges(); + describe('progressbar overlay', () => { + it('should NOT be visible if NOT loading and NOT loaded', () => { + component.stateResource = { ...createEmptyStateResource(false), loaded: false }; + fixture.detectChanges(); - const overlay = fixture.nativeElement.querySelector(overlaySelector); + const overlay = fixture.nativeElement.querySelector(overlaySelector); - expect(overlay).not.toBeInstanceOf(HTMLElement); - }); + expect(overlay).not.toBeInstanceOf(HTMLElement); + }); - it('should NOT be visible if NOT loading and already loaded', () => { - component.stateResource = { ...createEmptyStateResource(false), loaded: true }; - fixture.detectChanges(); + it('should NOT be visible if NOT loading and already loaded', () => { + component.stateResource = { ...createEmptyStateResource(false), loaded: true }; + fixture.detectChanges(); - const overlay = fixture.nativeElement.querySelector(overlaySelector); + const overlay = fixture.nativeElement.querySelector(overlaySelector); - expect(overlay).not.toBeInstanceOf(HTMLElement); - }); + expect(overlay).not.toBeInstanceOf(HTMLElement); + }); - it('should be visible if loading', () => { - component.stateResource = createEmptyStateResource(true); - fixture.detectChanges(); + it('should be visible if loading', () => { + component.stateResource = createEmptyStateResource(true); + fixture.detectChanges(); - const overlay = fixture.nativeElement.querySelector(overlaySelector); + const overlay = fixture.nativeElement.querySelector(overlaySelector); - expect(overlay).toBeInstanceOf(HTMLElement); - }); - }); + expect(overlay).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.ts b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.ts index 13e5a563bc447a7c4aa46a026f6f7bcf71fd0591..39f14e3af07d2bc5fea6fea7c06e3e42eb4e211c 100644 --- a/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/progress-bar/progress-bar.component.ts @@ -26,15 +26,14 @@ import { createEmptyStateResource, StateResource } from '@alfa-client/tech-share import { Resource } from '@ngxp/rest'; @Component({ - selector: 'ozgcloud-progress-bar', - templateUrl: './progress-bar.component.html', - styleUrls: ['./progress-bar.component.scss'] + selector: 'ozgcloud-progress-bar', + templateUrl: './progress-bar.component.html', + styleUrls: ['./progress-bar.component.scss'], }) export class ProgressBarComponent { + @Input() stateResource: StateResource<Resource> = createEmptyStateResource<Resource>(); - @Input() stateResource: StateResource<Resource> = createEmptyStateResource<Resource>(); - - get isVisible(): boolean { - return this.stateResource.loading; - } + get isVisible(): boolean { + return this.stateResource.loading; + } } diff --git a/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.html b/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.html index 995ea58e63b982d6271139b5b72abf3fb855d0c4..a76b8bea8332621394acda1e83b7aebfbd987394 100644 --- a/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.html +++ b/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.html @@ -23,9 +23,11 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<mat-slide-toggle color="primary" - [disabled]="disabled" - [matTooltip]="toolTip" - [checked]="checked" - (change)="valueChanged.emit($event.checked)">{{label}} -</mat-slide-toggle> \ No newline at end of file +<mat-slide-toggle + color="primary" + [disabled]="disabled" + [matTooltip]="toolTip" + [checked]="checked" + (change)="valueChanged.emit($event.checked)" + >{{ label }} +</mat-slide-toggle> diff --git a/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.spec.ts index 108c2d62672dc5532d278e7df93efe194a898771..15c28f9a98d9fc31212b13df5e007921440f4e4d 100644 --- a/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.spec.ts @@ -28,27 +28,21 @@ import { MatTooltipDirective } from 'libs/ui/src/lib/ui/mattooltip/mattooltip.di import { SlideToggleComponent } from './slide-toggle.component'; describe('SlideToggleComponent', () => { - let component: SlideToggleComponent; - let fixture: ComponentFixture<SlideToggleComponent>; + let component: SlideToggleComponent; + let fixture: ComponentFixture<SlideToggleComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - MatRippleModule - ], - declarations: [ - SlideToggleComponent, - MatTooltipDirective, - MatSlideToggle - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [MatRippleModule], + declarations: [SlideToggleComponent, MatTooltipDirective, MatSlideToggle], + }).compileComponents(); - fixture = TestBed.createComponent(SlideToggleComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(SlideToggleComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.ts b/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.ts index 59054ccfeee2aeba743b661a8148ed40ea17b2f0..4e7cdb5020cf206fb4d4c606774b4f52cfac87f8 100644 --- a/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/slide-toggle/slide-toggle.component.ts @@ -25,16 +25,15 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { EMPTY_STRING } from '@alfa-client/tech-shared'; @Component({ - selector: 'ozgcloud-slide-toggle', - templateUrl: './slide-toggle.component.html', - styleUrls: ['./slide-toggle.component.scss'], + selector: 'ozgcloud-slide-toggle', + templateUrl: './slide-toggle.component.html', + styleUrls: ['./slide-toggle.component.scss'], }) export class SlideToggleComponent { + @Input() checked: boolean = false; + @Input() label: string = EMPTY_STRING; + @Input() toolTip: string = EMPTY_STRING; + @Input() disabled: boolean = false; - @Input() checked: boolean = false; - @Input() label: string = EMPTY_STRING; - @Input() toolTip: string = EMPTY_STRING; - @Input() disabled: boolean = false; - - @Output() valueChanged: EventEmitter<boolean> = new EventEmitter(); -} \ No newline at end of file + @Output() valueChanged: EventEmitter<boolean> = new EventEmitter(); +} diff --git a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.html b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.html index 6933f9ce8591e51e9f621349931d57f4d3497620..c613be35fc54f222f841e299620539576142cc01 100644 --- a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.html +++ b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.html @@ -1,5 +1,10 @@ -<div *ngIf="showSpinner" data-test-class="spinner-transparency" class="spinner" [style.padding]="'16px'"> - <mat-spinner [diameter]="70"></mat-spinner> +<div + *ngIf="showSpinner" + data-test-class="spinner-transparency" + class="spinner" + [style.padding]="'16px'" +> + <mat-spinner [diameter]="70"></mat-spinner> </div> <ng-content *ngIf="!showSpinner" data-test-class="spinner-transparency-content"></ng-content> diff --git a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.scss b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.scss index d549da40ac63bd860c4ed7e838e59bf9fd8d33aa..75c027c63f628c0ba4169c714820fda2b2ee4015 100644 --- a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.scss @@ -1,12 +1,12 @@ .spinner { - display: flex; - width: 100%; - height: 100%; - position: fixed; - top: 0; - left: 0; - background-color: rgba(#000, 0.3); - z-index: 100; - align-items: center; - justify-content: center; -} \ No newline at end of file + display: flex; + width: 100%; + height: 100%; + position: fixed; + top: 0; + left: 0; + background-color: rgba(#000, 0.3); + z-index: 100; + align-items: center; + justify-content: center; +} diff --git a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.spec.ts index b15aacda3092e770d4735ae910321877d2c7b0e9..62f9dfed608a6b4e31366f2d301f955d6ff621b0 100644 --- a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.spec.ts @@ -8,51 +8,45 @@ import { getDataTestClassOf } from 'libs/tech-shared/test/data-test'; import { SpinnerTransparencyComponent } from './spinner-transparency.component'; describe('SpinnerTransparencyComponent', () => { - let component: SpinnerTransparencyComponent; - let fixture: ComponentFixture<SpinnerTransparencyComponent>; + let component: SpinnerTransparencyComponent; + let fixture: ComponentFixture<SpinnerTransparencyComponent>; - const spinnerSelector: string = getDataTestClassOf('spinner-transparency'); + const spinnerSelector: string = getDataTestClassOf('spinner-transparency'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - SpinnerTransparencyComponent, - SpinnerComponent, - MatIcon, - MatSpinner - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [SpinnerTransparencyComponent, SpinnerComponent, MatIcon, MatSpinner], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(SpinnerTransparencyComponent); - component = fixture.componentInstance; + beforeEach(() => { + fixture = TestBed.createComponent(SpinnerTransparencyComponent); + component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('spinner', () => { + describe('spinner', () => { + it('should NOT be visible if NOT loading and already loaded', () => { + component.stateResource = { ...createEmptyStateResource(false), loaded: true }; + fixture.detectChanges(); - it('should NOT be visible if NOT loading and already loaded', () => { - component.stateResource = { ...createEmptyStateResource(false), loaded: true }; - fixture.detectChanges(); + const spinner = getElementFromFixture(fixture, spinnerSelector); - const spinner = getElementFromFixture(fixture, spinnerSelector); + expect(spinner).not.toBeInstanceOf(HTMLElement); + }); - expect(spinner).not.toBeInstanceOf(HTMLElement); - }) + it('should be visible if loading', () => { + component.stateResource = createEmptyStateResource(true); + fixture.detectChanges(); - it('should be visible if loading', () => { - component.stateResource = createEmptyStateResource(true); - fixture.detectChanges(); + const spinner = getElementFromFixture(fixture, spinnerSelector); - const spinner = getElementFromFixture(fixture, spinnerSelector); - - expect(spinner).toBeInstanceOf(HTMLElement); - }); - }); + expect(spinner).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.ts b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.ts index 12c7d2fb1c4af03a84a07a221eda2fd569d3b283..b4e7d845196476f4fc839dd8711efebb9d41400e 100644 --- a/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/spinner-transparency/spinner-transparency.component.ts @@ -3,15 +3,14 @@ import { StateResource, createEmptyStateResource } from '@alfa-client/tech-share import { Resource } from '@ngxp/rest'; @Component({ - selector: 'ozgcloud-spinner-transparency', - templateUrl: './spinner-transparency.component.html', - styleUrls: ['./spinner-transparency.component.scss'], + selector: 'ozgcloud-spinner-transparency', + templateUrl: './spinner-transparency.component.html', + styleUrls: ['./spinner-transparency.component.scss'], }) export class SpinnerTransparencyComponent { + @Input() stateResource: StateResource<Resource> = createEmptyStateResource<Resource>(); - @Input() stateResource: StateResource<Resource> = createEmptyStateResource<Resource>(); - - get showSpinner(): boolean { - return this.stateResource.loading || this.stateResource.reload; - } + get showSpinner(): boolean { + return this.stateResource.loading || this.stateResource.reload; + } } diff --git a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.html b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.html index d968cdfdb056244bd3d09b45e1694ef00918a6c2..7d747d7685124129b52a1069467600538a464aa0 100644 --- a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.html +++ b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.html @@ -24,8 +24,8 @@ --> <div *ngIf="showSpinner" data-test-class="spinner" class="spinner" [style.padding]="padding + 'px'"> - <mat-spinner [diameter]="diameter"></mat-spinner> - <span *ngIf="text">{{ text }}</span> + <mat-spinner [diameter]="diameter"></mat-spinner> + <span *ngIf="text">{{ text }}</span> </div> <ng-content *ngIf="!showSpinner" data-test-class="spinner-content"></ng-content> diff --git a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.scss b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.scss index 71640251a62ac56222ed803dc5de8c2c33f60697..13cda62da60f0843643ccb975179de19529db649 100644 --- a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.scss @@ -22,12 +22,12 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ span { - color: #999; - margin-left: 8px; + color: #999; + margin-left: 8px; } .spinner { - display: flex; - justify-content: center; - align-items: center; + display: flex; + justify-content: center; + align-items: center; } diff --git a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.spec.ts index 53cff94938cfecff6f6a0c2795efeb56abc6f336..0ee0f00ba00d9f9a5d56f3a93cdff1bc8ed9c4f5 100644 --- a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.spec.ts @@ -30,73 +30,67 @@ import { getDataTestClassOf } from 'libs/tech-shared/test/data-test'; import { SpinnerComponent } from './spinner.component'; describe('SpinnerComponent', () => { - let component: SpinnerComponent; - let fixture: ComponentFixture<SpinnerComponent>; + let component: SpinnerComponent; + let fixture: ComponentFixture<SpinnerComponent>; - const spinnerSelector: string = getDataTestClassOf('spinner'); + const spinnerSelector: string = getDataTestClassOf('spinner'); - beforeEach(async () => { - TestBed.configureTestingModule({ - declarations: [ - SpinnerComponent, - MatIcon, - MatSpinner - ] - }) - }); + beforeEach(async () => { + TestBed.configureTestingModule({ + declarations: [SpinnerComponent, MatIcon, MatSpinner], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(SpinnerComponent); - component = fixture.componentInstance; + beforeEach(() => { + fixture = TestBed.createComponent(SpinnerComponent); + component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('spinner', () => { + describe('spinner', () => { + it('should NOT be visible if NOT loading and already loaded', () => { + component.stateResource = { ...createEmptyStateResource(false), loaded: true }; + fixture.detectChanges(); - it('should NOT be visible if NOT loading and already loaded', () => { - component.stateResource = { ...createEmptyStateResource(false), loaded: true }; - fixture.detectChanges(); + const spinner = getElementFromFixture(fixture, spinnerSelector); - const spinner = getElementFromFixture(fixture, spinnerSelector); + expect(spinner).not.toBeInstanceOf(HTMLElement); + }); - expect(spinner).not.toBeInstanceOf(HTMLElement); - }) + it('should be visible if loading', () => { + component.stateResource = createEmptyStateResource(true); + fixture.detectChanges(); - it('should be visible if loading', () => { - component.stateResource = createEmptyStateResource(true); - fixture.detectChanges(); + const spinner = getElementFromFixture(fixture, spinnerSelector); - const spinner = getElementFromFixture(fixture, spinnerSelector); + expect(spinner).toBeInstanceOf(HTMLElement); + }); + }); - expect(spinner).toBeInstanceOf(HTMLElement); - }); - }); + describe('loaded spinner', () => { + beforeEach(() => { + component.show = false; + fixture.detectChanges(); + }); - describe('loaded spinner', () => { + it('should NOT be visible if showIf return false', () => { + const spinner = getElementFromFixture(fixture, spinnerSelector); - beforeEach(() => { - component.show = false; - fixture.detectChanges(); - }) + expect(spinner).not.toBeInstanceOf(HTMLElement); + }); - it('should NOT be visible if showIf return false', () => { - const spinner = getElementFromFixture(fixture, spinnerSelector); + it('should be visible if loaded', () => { + component.show = true; + fixture.detectChanges(); - expect(spinner).not.toBeInstanceOf(HTMLElement); - }) + const spinner = getElementFromFixture(fixture, spinnerSelector); - it('should be visible if loaded', () => { - component.show = true; - fixture.detectChanges(); - - const spinner = getElementFromFixture(fixture, spinnerSelector); - - expect(spinner).toBeInstanceOf(HTMLElement); - }); - }); + expect(spinner).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.ts b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.ts index a7ec921293047d6b3e00ee633383d1c23d8b5b2b..aaea10bcd8ce1200bd6ee7c26a3ddbfbd686f335 100644 --- a/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/spinner/spinner.component.ts @@ -26,20 +26,19 @@ import { createEmptyStateResource, StateResource } from '@alfa-client/tech-share import { Resource } from '@ngxp/rest'; @Component({ - selector: 'ozgcloud-spinner', - templateUrl: './spinner.component.html', - styleUrls: ['./spinner.component.scss'] + selector: 'ozgcloud-spinner', + templateUrl: './spinner.component.html', + styleUrls: ['./spinner.component.scss'], }) export class SpinnerComponent { + @Input() stateResource: StateResource<Resource> = createEmptyStateResource<Resource>(); + @Input() diameter: number = 70; + @Input() padding: number = 16; + @Input() text: string; + @Input() show: boolean = false; - @Input() stateResource: StateResource<Resource> = createEmptyStateResource<Resource>(); - @Input() diameter: number = 70; - @Input() padding: number = 16; - @Input() text: string; - @Input() show: boolean = false; - - get showSpinner(): boolean { - if (this.show) return this.show; - return this.stateResource.loading || this.stateResource.reload; - } -} \ No newline at end of file + get showSpinner(): boolean { + if (this.show) return this.show; + return this.stateResource.loading || this.stateResource.reload; + } +} diff --git a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.scss b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.scss index 605800c7e24ada121dc27a7877f777082ada61f5..be17b27b1231a145f383f40e1447c385c1492255 100644 --- a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.scss +++ b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.scss @@ -24,19 +24,21 @@ @import 'variables'; :host { - position: sticky; - top: $header-height; - height: 48px; - width: 100%; - z-index: 2; - box-shadow: $shadow-bottom; - display: flex; - justify-content: flex-start; - align-items: center; - padding: 0.25rem 0.75rem 0.25rem 1rem; + position: sticky; + top: $header-height; + height: 48px; + width: 100%; + z-index: 2; + box-shadow: $shadow-bottom; + display: flex; + justify-content: flex-start; + align-items: center; + padding: 0.25rem 0.75rem 0.25rem 1rem; - &.shadow { - //overflow-x: hidden; - box-shadow: $shadow-bottom, 0 2px 2px -2px rgba(#000, 0.16); - } + &.shadow { + //overflow-x: hidden; + box-shadow: + $shadow-bottom, + 0 2px 2px -2px rgba(#000, 0.16); + } } diff --git a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.spec.ts index b7e67e79b240b9a6df8d130ef25ffd6f93ab55ae..62377e29fcdded4e3d2af6c0110cd0510194d5b7 100644 --- a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.spec.ts @@ -30,9 +30,8 @@ describe('SubnavigationComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ SubnavigationComponent ] - }) - .compileComponents(); + declarations: [SubnavigationComponent], + }).compileComponents(); }); beforeEach(() => { diff --git a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.ts b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.ts index 0e99b0c95b1d0f0ca715f42666cf1a8f77241783..829c0ac7cbe4120b62f9c1ab2bfb142907d8ad1b 100644 --- a/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/subnavigation/subnavigation.component.ts @@ -26,6 +26,6 @@ import { Component } from '@angular/core'; @Component({ selector: 'ozgcloud-subnavigation', templateUrl: './subnavigation.component.html', - styleUrls: ['./subnavigation.component.scss'] + styleUrls: ['./subnavigation.component.scss'], }) -export class SubnavigationComponent { } +export class SubnavigationComponent {} diff --git a/alfa-client/libs/ui/src/lib/ui/ui.module.spec.ts b/alfa-client/libs/ui/src/lib/ui/ui.module.spec.ts index e2ba6612ecec1f4e9573b4fc0924c7e9f611c537..2839934b19316db382f7b32853888e9d276eaee1 100644 --- a/alfa-client/libs/ui/src/lib/ui/ui.module.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/ui.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { UiModule } from './ui.module'; describe('UiModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [UiModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [UiModule], + }).compileComponents(); + }); - it('should create', () => { - expect(UiModule).toBeDefined(); - }); + it('should create', () => { + expect(UiModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/ui.module.ts b/alfa-client/libs/ui/src/lib/ui/ui.module.ts index da367a4d36b494f8885d59b796c72fbc4a9ae6de..61c0bd7440b5187519bb0b8397c35f88bc7f7678 100644 --- a/alfa-client/libs/ui/src/lib/ui/ui.module.ts +++ b/alfa-client/libs/ui/src/lib/ui/ui.module.ts @@ -73,7 +73,11 @@ import { FixedDialogComponent } from './fixed-dialog/fixed-dialog.component'; import { ConnectionTimeoutRetryDialogComponent } from './http-error-dialog/connection-timeout-retry-dialog/connection-timeout-retry-dialog.component'; import { ConnectionTimeoutRetryFailDialogComponent } from './http-error-dialog/connection-timeout-retry-fail-dialog/connection-timeout-retry-fail-dialog.component'; import { IconButtonWithSpinnerComponent } from './icon-button-with-spinner/icon-button-with-spinner.component'; -import { MatTooltipClassDirective, MatTooltipDirective, MatTooltipDisabledDirective } from './mattooltip/mattooltip.directive'; +import { + MatTooltipClassDirective, + MatTooltipDirective, + MatTooltipDisabledDirective, +} from './mattooltip/mattooltip.directive'; import { MenuItemComponent } from './menu-item/menu-item.component'; import { InternalServerErrorDialogComponent } from './notification/internal-server-error-dialog/internal-server-error-dialog.component'; import { OpenUrlButtonComponent } from './open-url-button/open-url-button.component'; @@ -95,173 +99,173 @@ import { OzgcloudIconButtonPrimaryComponent } from './ozgcloud-button/ozgcloud-i import { OzgcloudPasteTextButtonComponent } from './ozgcloud-paste-text-button/ozgcloud-paste-text-button.component'; @NgModule({ - declarations: [ - SubnavigationComponent, - SpinnerComponent, - OzgcloudButtonWithSpinnerComponent, - OzgcloudStrokedButtonWithSpinnerComponent, - IconButtonWithSpinnerComponent, - ProgressBarComponent, - ExpansionPanelComponent, - SnackbarInfoComponent, - SnackbarErrorComponent, - EnumEditorComponent, - FileUploadComponent, - DateEditorComponent, - TextEditorComponent, - TextAreaEditorComponent, - ValidationErrorComponent, - AutocompleteEditorComponent, - FixedDialogComponent, - EnumEditorComponent, - InternalServerErrorDialogComponent, - FileUploadEditorComponent, - MatTooltipDirective, - MatTooltipDisabledDirective, - MatTooltipClassDirective, - MenuItemComponent, - PostfachIconComponent, - AccordionComponent, - AppIconComponent, - SlideToggleComponent, - BackButtonComponent, - ButtonToggleGroupComponent, - ButtonToggleComponent, - OzgcloudIconButtonPrimaryComponent, - OzgcloudIconComponent, - OzgcloudRoutingButtonComponent, - OzgcloudSvgIconComponent, - OzgcloudSvgIconBigComponent, - SpinnerTransparencyComponent, - OpenUrlButtonComponent, - DownloadButtonComponent, - OzgcloudMenuComponent, - ConnectionTimeoutRetryDialogComponent, - ConnectionTimeoutRetryFailDialogComponent, - SnackbarCloseButtonComponent, - BasicDialogComponent, - OzgcloudButtonContentComponent, - OzgcloudPasteTextButtonComponent, - ], - imports: [ - MatButtonModule, - MatIconModule, - MatProgressBarModule, - MatProgressSpinnerModule, - MatMenuModule, - MatSlideToggleModule, - MatExpansionModule, - MatRippleModule, - MatSnackBarModule, - MatCheckboxModule, - MatFormFieldModule, - MatInputModule, - MatListModule, - MatDatepickerModule, - MatDateFnsModule, - FormsModule, - ReactiveFormsModule, - MatAutocompleteModule, - MatDialogModule, - MatTabsModule, - MatBadgeModule, - CommonModule, - TechSharedModule, - RouterModule, - MatButtonToggleModule - ], - exports: [ - MatButtonModule, - MatIconModule, - MatProgressBarModule, - MatProgressSpinnerModule, - MatMenuModule, - MatSlideToggleModule, - MatExpansionModule, - MatRippleModule, - MatSnackBarModule, - MatCheckboxModule, - MatFormFieldModule, - MatInputModule, - MatListModule, - MatDatepickerModule, - MatDateFnsModule, - FormsModule, - ReactiveFormsModule, - MatAutocompleteModule, - MatDialogModule, - MatTabsModule, - MatBadgeModule, - CommonModule, - TechSharedModule, - RouterModule, - MatButtonToggleModule, - SubnavigationComponent, - SpinnerComponent, - OzgcloudIconButtonPrimaryComponent, - OzgcloudButtonWithSpinnerComponent, - OzgcloudStrokedButtonWithSpinnerComponent, - IconButtonWithSpinnerComponent, - ProgressBarComponent, - ExpansionPanelComponent, - SnackbarInfoComponent, - SnackbarErrorComponent, - EnumEditorComponent, - FileUploadComponent, - DateEditorComponent, - TextEditorComponent, - TextAreaEditorComponent, - ValidationErrorComponent, - AutocompleteEditorComponent, - FixedDialogComponent, - EnumEditorComponent, - InternalServerErrorDialogComponent, - FileUploadEditorComponent, - MatTooltipDirective, - MatTooltipDisabledDirective, - MatTooltipClassDirective, - MenuItemComponent, - PostfachIconComponent, - AccordionComponent, - AppIconComponent, - SlideToggleComponent, - BackButtonComponent, - ButtonToggleGroupComponent, - ButtonToggleComponent, - OzgcloudIconComponent, - OzgcloudRoutingButtonComponent, - OzgcloudSvgIconComponent, - OzgcloudSvgIconBigComponent, - SpinnerTransparencyComponent, - OpenUrlButtonComponent, - DownloadButtonComponent, - OzgcloudMenuComponent, - ConnectionTimeoutRetryDialogComponent, - ConnectionTimeoutRetryFailDialogComponent, - SnackbarCloseButtonComponent, - BasicDialogComponent, - OzgcloudPasteTextButtonComponent, - ], - providers: [ - { - provide: HTTP_INTERCEPTORS, - useClass: HttpErrorInterceptor, - multi: true, - }, - { - provide: HTTP_INTERCEPTORS, - useClass: HttpConnectionTimeoutInterceptor, - multi: true, - }, - { - provide: MAT_DATE_LOCALE, - useValue: de, - }, - { - provide: DateAdapter, - useClass: DateFnsAdapter, - deps: [MAT_DATE_LOCALE], - }, - ], + declarations: [ + SubnavigationComponent, + SpinnerComponent, + OzgcloudButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, + IconButtonWithSpinnerComponent, + ProgressBarComponent, + ExpansionPanelComponent, + SnackbarInfoComponent, + SnackbarErrorComponent, + EnumEditorComponent, + FileUploadComponent, + DateEditorComponent, + TextEditorComponent, + TextAreaEditorComponent, + ValidationErrorComponent, + AutocompleteEditorComponent, + FixedDialogComponent, + EnumEditorComponent, + InternalServerErrorDialogComponent, + FileUploadEditorComponent, + MatTooltipDirective, + MatTooltipDisabledDirective, + MatTooltipClassDirective, + MenuItemComponent, + PostfachIconComponent, + AccordionComponent, + AppIconComponent, + SlideToggleComponent, + BackButtonComponent, + ButtonToggleGroupComponent, + ButtonToggleComponent, + OzgcloudIconButtonPrimaryComponent, + OzgcloudIconComponent, + OzgcloudRoutingButtonComponent, + OzgcloudSvgIconComponent, + OzgcloudSvgIconBigComponent, + SpinnerTransparencyComponent, + OpenUrlButtonComponent, + DownloadButtonComponent, + OzgcloudMenuComponent, + ConnectionTimeoutRetryDialogComponent, + ConnectionTimeoutRetryFailDialogComponent, + SnackbarCloseButtonComponent, + BasicDialogComponent, + OzgcloudButtonContentComponent, + OzgcloudPasteTextButtonComponent, + ], + imports: [ + MatButtonModule, + MatIconModule, + MatProgressBarModule, + MatProgressSpinnerModule, + MatMenuModule, + MatSlideToggleModule, + MatExpansionModule, + MatRippleModule, + MatSnackBarModule, + MatCheckboxModule, + MatFormFieldModule, + MatInputModule, + MatListModule, + MatDatepickerModule, + MatDateFnsModule, + FormsModule, + ReactiveFormsModule, + MatAutocompleteModule, + MatDialogModule, + MatTabsModule, + MatBadgeModule, + CommonModule, + TechSharedModule, + RouterModule, + MatButtonToggleModule, + ], + exports: [ + MatButtonModule, + MatIconModule, + MatProgressBarModule, + MatProgressSpinnerModule, + MatMenuModule, + MatSlideToggleModule, + MatExpansionModule, + MatRippleModule, + MatSnackBarModule, + MatCheckboxModule, + MatFormFieldModule, + MatInputModule, + MatListModule, + MatDatepickerModule, + MatDateFnsModule, + FormsModule, + ReactiveFormsModule, + MatAutocompleteModule, + MatDialogModule, + MatTabsModule, + MatBadgeModule, + CommonModule, + TechSharedModule, + RouterModule, + MatButtonToggleModule, + SubnavigationComponent, + SpinnerComponent, + OzgcloudIconButtonPrimaryComponent, + OzgcloudButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, + IconButtonWithSpinnerComponent, + ProgressBarComponent, + ExpansionPanelComponent, + SnackbarInfoComponent, + SnackbarErrorComponent, + EnumEditorComponent, + FileUploadComponent, + DateEditorComponent, + TextEditorComponent, + TextAreaEditorComponent, + ValidationErrorComponent, + AutocompleteEditorComponent, + FixedDialogComponent, + EnumEditorComponent, + InternalServerErrorDialogComponent, + FileUploadEditorComponent, + MatTooltipDirective, + MatTooltipDisabledDirective, + MatTooltipClassDirective, + MenuItemComponent, + PostfachIconComponent, + AccordionComponent, + AppIconComponent, + SlideToggleComponent, + BackButtonComponent, + ButtonToggleGroupComponent, + ButtonToggleComponent, + OzgcloudIconComponent, + OzgcloudRoutingButtonComponent, + OzgcloudSvgIconComponent, + OzgcloudSvgIconBigComponent, + SpinnerTransparencyComponent, + OpenUrlButtonComponent, + DownloadButtonComponent, + OzgcloudMenuComponent, + ConnectionTimeoutRetryDialogComponent, + ConnectionTimeoutRetryFailDialogComponent, + SnackbarCloseButtonComponent, + BasicDialogComponent, + OzgcloudPasteTextButtonComponent, + ], + providers: [ + { + provide: HTTP_INTERCEPTORS, + useClass: HttpErrorInterceptor, + multi: true, + }, + { + provide: HTTP_INTERCEPTORS, + useClass: HttpConnectionTimeoutInterceptor, + multi: true, + }, + { + provide: MAT_DATE_LOCALE, + useValue: de, + }, + { + provide: DateAdapter, + useClass: DateFnsAdapter, + deps: [MAT_DATE_LOCALE], + }, + ], }) export class UiModule {} diff --git a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html index e8a62d2d732817bb524d1705945106e8da46a0c8..13f1ef45c46566b76aad56247845108a014310e6 100644 --- a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html +++ b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.html @@ -23,4 +23,4 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<span *ngFor="let issue of issues">{{message(issue)}}</span> \ No newline at end of file +<span *ngFor="let issue of issues">{{ message(issue) }}</span> diff --git a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts index 145ce0438ec43cbd6bcbfedecbf3da3233468deb..299af463232908e4f3edec96f97f7fd912379b0e 100644 --- a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts +++ b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.spec.ts @@ -25,31 +25,29 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { createIssue } from 'libs/tech-shared/test/error'; import { ValidationErrorComponent } from './validation-error.component'; - describe('ValidationErrorComponent', () => { - let component: ValidationErrorComponent; - let fixture: ComponentFixture<ValidationErrorComponent>; + let component: ValidationErrorComponent; + let fixture: ComponentFixture<ValidationErrorComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ValidationErrorComponent] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ValidationErrorComponent], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(ValidationErrorComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ValidationErrorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should get message', () => { - var msg = component.message({ ...createIssue(), messageCode: 'validation_field_size' }); + it('should get message', () => { + var msg = component.message({ ...createIssue(), messageCode: 'validation_field_size' }); - expect(msg).not.toHaveLength(0); - }) + expect(msg).not.toHaveLength(0); + }); }); diff --git a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts index 985bf3d3c9ca7fe8eda45fd71c44bfca523b7bbb..066afd9e872c3354d475f0421d8cb2f363d1acd8 100644 --- a/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts +++ b/alfa-client/libs/ui/src/lib/ui/validation-error/validation-error.component.ts @@ -25,16 +25,15 @@ import { Component, Input } from '@angular/core'; import { getMessageForIssue, Issue } from '@alfa-client/tech-shared'; @Component({ - selector: 'ozgcloud-validation-error', - templateUrl: './validation-error.component.html', - styleUrls: ['./validation-error.component.scss'] + selector: 'ozgcloud-validation-error', + templateUrl: './validation-error.component.html', + styleUrls: ['./validation-error.component.scss'], }) export class ValidationErrorComponent { + @Input() label: string; + @Input() issues: Issue[]; - @Input() label: string; - @Input() issues: Issue[]; - - message(issue: Issue): string { - return getMessageForIssue(this.label, issue); - } -} \ No newline at end of file + message(issue: Issue): string { + return getMessageForIssue(this.label, issue); + } +} diff --git a/alfa-client/libs/ui/src/test-setup.ts b/alfa-client/libs/ui/src/test-setup.ts index 5870fdabb6470fd0f6f3f63be3d4f6b8041b4dd2..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/ui/src/test-setup.ts +++ b/alfa-client/libs/ui/src/test-setup.ts @@ -26,17 +26,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/ui/tsconfig.json b/alfa-client/libs/ui/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/ui/tsconfig.json +++ b/alfa-client/libs/ui/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/ui/tsconfig.lib.json b/alfa-client/libs/ui/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/ui/tsconfig.lib.json +++ b/alfa-client/libs/ui/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/ui/tsconfig.spec.json b/alfa-client/libs/ui/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/ui/tsconfig.spec.json +++ b/alfa-client/libs/ui/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/user-assistance/.eslintrc.json b/alfa-client/libs/user-assistance/.eslintrc.json index 7b7b6231394b8c5674ce1b007077d4327aea7fda..9416ef7fe3c2643718ea92627388bf35847fc788 100644 --- a/alfa-client/libs/user-assistance/.eslintrc.json +++ b/alfa-client/libs/user-assistance/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - }, - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ] - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + }, + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"] + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/user-assistance/jest.config.ts b/alfa-client/libs/user-assistance/jest.config.ts index 1832780aaf2634457ae963c4dd7dd3903126c78a..68ef54e1b78afcebc100bafc1014722bff656607 100644 --- a/alfa-client/libs/user-assistance/jest.config.ts +++ b/alfa-client/libs/user-assistance/jest.config.ts @@ -1,23 +1,23 @@ /* eslint-disable */ export default { - displayName: 'user-assistance', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/user-profile', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'user-assistance', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/user-profile', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/user-assistance/project.json b/alfa-client/libs/user-assistance/project.json index 9041cd7c3e594d6e0d42b361461564614beec5be..caf7b025be789cf4a87d839a7032ecf29464eac7 100644 --- a/alfa-client/libs/user-assistance/project.json +++ b/alfa-client/libs/user-assistance/project.json @@ -1,28 +1,25 @@ { - "name": "user-assistance", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/user-assistance/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/user-assistance"], - "options": { - "jestConfig": "libs/user-assistance/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "outputs": ["{options.outputFile}"], - "options": { - "lintFilePatterns": [ - "libs/user-assistance/**/*.ts", - "libs/user-assistance/**/*.html" - ] - } - } - }, - "tags": [] + "name": "user-assistance", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/user-assistance/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/user-assistance"], + "options": { + "jestConfig": "libs/user-assistance/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "outputs": ["{options.outputFile}"], + "options": { + "lintFilePatterns": ["libs/user-assistance/**/*.ts", "libs/user-assistance/**/*.html"] + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/user-assistance/src/index.ts b/alfa-client/libs/user-assistance/src/index.ts index d8be0745a90094989e53537c9d62c498c3191483..8245e6ddf20e990b02cf575a76597daee6a96836 100644 --- a/alfa-client/libs/user-assistance/src/index.ts +++ b/alfa-client/libs/user-assistance/src/index.ts @@ -1,3 +1,2 @@ export * from './lib/help-menu/help-menu.component'; export * from './lib/user-assistance.module'; - diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html index dcc6a6ca8c7a4e03b6cd563abeb193067da0641d..e9289c2c408ded61b2210d3c5c3aa636be4cc0f4 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.html @@ -1 +1 @@ -<alfa-open-documentation-button [url]="url"></alfa-open-documentation-button> \ No newline at end of file +<alfa-open-documentation-button [url]="url"></alfa-open-documentation-button> diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.scss b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.scss index a440dd243c68309efbcf544aa7f680ad7b94efc7..bcbd245ce7ef1ee60e79e99fce4f19f468a8c145 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.scss +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.scss @@ -1,3 +1,3 @@ :host { - white-space: nowrap; -} \ No newline at end of file + white-space: nowrap; +} diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts index c478991e84af0b41afe725fcb3e7fcca6c82a841..a698afa79496b8fb18b66aad3f4586596c374d49 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.spec.ts @@ -1,26 +1,23 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { MockComponent } from "ng-mocks"; +import { MockComponent } from 'ng-mocks'; import { DocumentationComponent } from './documentation.component'; -import { OpenDocumentationButtonComponent } from "./open-documentation-button/open-documentation-button.component"; +import { OpenDocumentationButtonComponent } from './open-documentation-button/open-documentation-button.component'; describe('DocumentationComponent', () => { - let component: DocumentationComponent; - let fixture: ComponentFixture<DocumentationComponent>; + let component: DocumentationComponent; + let fixture: ComponentFixture<DocumentationComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - DocumentationComponent, - MockComponent(OpenDocumentationButtonComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [DocumentationComponent, MockComponent(OpenDocumentationButtonComponent)], + }).compileComponents(); - fixture = TestBed.createComponent(DocumentationComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(DocumentationComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.ts index 3792659757f84fc76ab1fbec07d9b24570db78a0..d8298776c23a5dd1590d234b6b51a54afcf56e20 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.ts +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/documentation.component.ts @@ -1,13 +1,11 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'alfa-documentation', - templateUrl: './documentation.component.html', - styleUrls: ['./documentation.component.scss'], + selector: 'alfa-documentation', + templateUrl: './documentation.component.html', + styleUrls: ['./documentation.component.scss'], }) export class DocumentationComponent { - - @Input() url: string; - @Input() menuTitle: string; - + @Input() url: string; + @Input() menuTitle: string; } diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html index 15ac6fa582945b4726349f50976d9473bee02dff..2764f98acb1ee7de4188fcba3353b627a7b5b0a6 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.html @@ -1 +1,7 @@ -<ozgcloud-open-url-button text="Öffnen" [url]="url" [targetName]="'_blank'" [tooltip]="'Öffnet in einem neuen Tab'" data-test-id="open-documentation-button"></ozgcloud-open-url-button> +<ozgcloud-open-url-button + text="Öffnen" + [url]="url" + [targetName]="'_blank'" + [tooltip]="'Öffnet in einem neuen Tab'" + data-test-id="open-documentation-button" +></ozgcloud-open-url-button> diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.spec.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.spec.ts index 4a011810106e0d3f4915cc916a5a8cb76ef05f3d..616982e9e6962bf3334bd661119aeba0bd9ad7cb 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.spec.ts +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.spec.ts @@ -5,23 +5,20 @@ import { MockComponent } from 'ng-mocks'; import { OpenUrlButtonComponent } from '@alfa-client/ui'; describe('OpenDocumentationButtonComponent', () => { - let component: OpenDocumentationButtonComponent; - let fixture: ComponentFixture<OpenDocumentationButtonComponent>; + let component: OpenDocumentationButtonComponent; + let fixture: ComponentFixture<OpenDocumentationButtonComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - OpenDocumentationButtonComponent, - MockComponent(OpenUrlButtonComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [OpenDocumentationButtonComponent, MockComponent(OpenUrlButtonComponent)], + }).compileComponents(); - fixture = TestBed.createComponent(OpenDocumentationButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(OpenDocumentationButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.ts index 1b1ff96a28a19f44575c3b9bbc6d0fd2203ebf54..fe23a2aa5f13318ff5973d5eed075de77098dec8 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.ts +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/documentation/open-documentation-button/open-documentation-button.component.ts @@ -1,12 +1,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'alfa-open-documentation-button', - templateUrl: './open-documentation-button.component.html', - styleUrls: ['./open-documentation-button.component.scss'], + selector: 'alfa-open-documentation-button', + templateUrl: './open-documentation-button.component.html', + styleUrls: ['./open-documentation-button.component.scss'], }) export class OpenDocumentationButtonComponent { - - @Input() url: string; - + @Input() url: string; } diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html index 5fa94a4e36efbe94c841b8a15f12412cf699d458..2b0db504b3f464f1624afcbceb95df15cfb6e3e0 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.html @@ -1,20 +1,28 @@ -<button *ngIf="getNumberOfMenuItems() > 0" mat-fab extended [matMenuTriggerFor]="helpMenu.matMenu" data-test-id="help-menu-button"> - <div class="help-menu"> - <ozgcloud-icon icon="help_outline"></ozgcloud-icon> - <div class="text">Hilfe</div> - </div> +<button + *ngIf="getNumberOfMenuItems() > 0" + mat-fab + extended + [matMenuTriggerFor]="helpMenu.matMenu" + data-test-id="help-menu-button" +> + <div class="help-menu"> + <ozgcloud-icon icon="help_outline"></ozgcloud-icon> + <div class="text">Hilfe</div> + </div> </button> <ozgcloud-menu #helpMenu> - <ozgcloud-menu-item - *ngIf="apiRootStateResource?.resource | hasLink: apiRootLinkRel.DOCUMENTATIONS" - headline="Benutzerleitfaden" - text="Alle Funktionen der Allgemeinen Fachanwendung (Alfa) erklärt." - icon="pdf_file" - #benutzerleitfadenMenuItem> - <alfa-documentation - data-test-id="documentations-component" - [menuTitle]="benutzerleitfadenMenuItem.headline" - [url]="apiRootStateResource.resource | getUrl: apiRootLinkRel.DOCUMENTATIONS"> - </alfa-documentation> - </ozgcloud-menu-item> + <ozgcloud-menu-item + *ngIf="apiRootStateResource?.resource | hasLink: apiRootLinkRel.DOCUMENTATIONS" + headline="Benutzerleitfaden" + text="Alle Funktionen der Allgemeinen Fachanwendung (Alfa) erklärt." + icon="pdf_file" + #benutzerleitfadenMenuItem + > + <alfa-documentation + data-test-id="documentations-component" + [menuTitle]="benutzerleitfadenMenuItem.headline" + [url]="apiRootStateResource.resource | getUrl: apiRootLinkRel.DOCUMENTATIONS" + > + </alfa-documentation> + </ozgcloud-menu-item> </ozgcloud-menu> diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.scss b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.scss index b6684420af7831874135b303e60daad3f0abc20d..99cbeef04c23dba9c76fa256dbdb4764f5a1e2b4 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.scss +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.scss @@ -1,11 +1,11 @@ @import 'variables'; .help-menu { - display: flex; - align-items: center; - color: $grey; + display: flex; + align-items: center; + color: $grey; } ozgcloud-icon { - margin-right: 4px; + margin-right: 4px; } diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts index 6da5903bce5dbef82dd66d289b13746b453cc6b7..d5a5e76b4013a950b458149b09a8b7eeea78437d 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.spec.ts @@ -1,7 +1,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { ApiRootLinkRel } from '@alfa-client/api-root-shared'; -import { GetUrlPipe, HasLinkPipe, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + GetUrlPipe, + HasLinkPipe, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { getElementFromDomRoot } from '@alfa-client/test-utils'; import { MenuItemComponent, OzgcloudIconComponent, UiModule } from '@alfa-client/ui'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -11,81 +16,80 @@ import { DocumentationComponent } from './documentation/documentation.component' import { HelpMenuComponent } from './help-menu.component'; describe('HelpMenuComponent', () => { - let component: HelpMenuComponent; - let fixture: ComponentFixture<HelpMenuComponent>; - - const helpMenuButton: string = getDataTestIdOf('help-menu-button'); - const documentationsComponent: string = getDataTestIdOf('documentations-component'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HelpMenuComponent, - HasLinkPipe, - GetUrlPipe, - MockComponent(MenuItemComponent), - MockComponent(DocumentationComponent), - MockComponent(OzgcloudIconComponent), - MockComponent(DocumentationComponent) - ], - imports: [ - UiModule, - NoopAnimationsModule, - ] - }).compileComponents(); - - fixture = TestBed.createComponent(HelpMenuComponent); - component = fixture.componentInstance; - component.apiRootStateResource = createStateResource(createApiRootResource()); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('help menu button', () => { - - it('should be hidden', () => { - const item = getElementFromDomRoot(fixture, helpMenuButton); - - expect(item).not.toBeInstanceOf(HTMLElement); - }); - - it('should be shown', () => { - component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.DOCUMENTATIONS])); - - fixture.detectChanges(); - - const item = getElementFromDomRoot(fixture, helpMenuButton); - expect(item).toBeInstanceOf(HTMLElement); - }); - }); - - describe('getNumberOfMenuItems', () => { - - it('should return 1', () => { - component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.DOCUMENTATIONS])); - - const result = component.getNumberOfMenuItems(); - - expect(result).toEqual(1); - }); - - it('should return 0 if state resource is null', () => { - component.apiRootStateResource = null; - - const result = component.getNumberOfMenuItems(); - - expect(result).toEqual(0); - }); - - it('should return 0 if resource is null', () => { - component.apiRootStateResource = createEmptyStateResource(); - - const result = component.getNumberOfMenuItems(); - - expect(result).toEqual(0); - }); - }); + let component: HelpMenuComponent; + let fixture: ComponentFixture<HelpMenuComponent>; + + const helpMenuButton: string = getDataTestIdOf('help-menu-button'); + const documentationsComponent: string = getDataTestIdOf('documentations-component'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HelpMenuComponent, + HasLinkPipe, + GetUrlPipe, + MockComponent(MenuItemComponent), + MockComponent(DocumentationComponent), + MockComponent(OzgcloudIconComponent), + MockComponent(DocumentationComponent), + ], + imports: [UiModule, NoopAnimationsModule], + }).compileComponents(); + + fixture = TestBed.createComponent(HelpMenuComponent); + component = fixture.componentInstance; + component.apiRootStateResource = createStateResource(createApiRootResource()); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('help menu button', () => { + it('should be hidden', () => { + const item = getElementFromDomRoot(fixture, helpMenuButton); + + expect(item).not.toBeInstanceOf(HTMLElement); + }); + + it('should be shown', () => { + component.apiRootStateResource = createStateResource( + createApiRootResource([ApiRootLinkRel.DOCUMENTATIONS]), + ); + + fixture.detectChanges(); + + const item = getElementFromDomRoot(fixture, helpMenuButton); + expect(item).toBeInstanceOf(HTMLElement); + }); + }); + + describe('getNumberOfMenuItems', () => { + it('should return 1', () => { + component.apiRootStateResource = createStateResource( + createApiRootResource([ApiRootLinkRel.DOCUMENTATIONS]), + ); + + const result = component.getNumberOfMenuItems(); + + expect(result).toEqual(1); + }); + + it('should return 0 if state resource is null', () => { + component.apiRootStateResource = null; + + const result = component.getNumberOfMenuItems(); + + expect(result).toEqual(0); + }); + + it('should return 0 if resource is null', () => { + component.apiRootStateResource = createEmptyStateResource(); + + const result = component.getNumberOfMenuItems(); + + expect(result).toEqual(0); + }); + }); }); diff --git a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.ts b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.ts index 7c6678b4c761e3c82f6e2dda3c117a76fa8a158f..602c0ee4effc7366a69024c531427d7ff5410ae9 100644 --- a/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.ts +++ b/alfa-client/libs/user-assistance/src/lib/help-menu/help-menu.component.ts @@ -1,20 +1,21 @@ import { Component, Input } from '@angular/core'; import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; import { StateResource } from '@alfa-client/tech-shared'; -import { hasLink } from "@ngxp/rest"; +import { hasLink } from '@ngxp/rest'; @Component({ - selector: 'alfa-help-menu', - templateUrl: './help-menu.component.html', - styleUrls: ['./help-menu.component.scss'], + selector: 'alfa-help-menu', + templateUrl: './help-menu.component.html', + styleUrls: ['./help-menu.component.scss'], }) export class HelpMenuComponent { + @Input() apiRootStateResource: StateResource<ApiRootResource>; - @Input() apiRootStateResource: StateResource<ApiRootResource>; + readonly apiRootLinkRel = ApiRootLinkRel; - readonly apiRootLinkRel = ApiRootLinkRel; - - public getNumberOfMenuItems(): number { - return [hasLink(this.apiRootStateResource?.resource, ApiRootLinkRel.DOCUMENTATIONS)].filter(isTrue => isTrue).length; - } + public getNumberOfMenuItems(): number { + return [hasLink(this.apiRootStateResource?.resource, ApiRootLinkRel.DOCUMENTATIONS)].filter( + (isTrue) => isTrue, + ).length; + } } diff --git a/alfa-client/libs/user-assistance/src/lib/user-assistance.module.spec.ts b/alfa-client/libs/user-assistance/src/lib/user-assistance.module.spec.ts index 9e0f01aa63dbc7cfa3c33d80a4e3731165f47437..fc50dcfb1a18bab623ef404ffa5d6193257eeb59 100644 --- a/alfa-client/libs/user-assistance/src/lib/user-assistance.module.spec.ts +++ b/alfa-client/libs/user-assistance/src/lib/user-assistance.module.spec.ts @@ -2,14 +2,13 @@ import { TestBed } from '@angular/core/testing'; import { UserAssistanceModule } from './user-assistance.module'; describe('UserAssistanceModule', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [UserAssistanceModule], + }).compileComponents(); + }); - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [UserAssistanceModule], - }).compileComponents(); - }); - - it('should create', () => { - expect(UserAssistanceModule).toBeDefined(); - }); + it('should create', () => { + expect(UserAssistanceModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts b/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts index ac2de9f5cfa62fabff3bf7168b2f2c36b16ae66d..937b7e7bac7ab4ce8aaf9c2f6173510a5ec26907 100644 --- a/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts +++ b/alfa-client/libs/user-assistance/src/lib/user-assistance.module.ts @@ -3,22 +3,12 @@ import { UiModule } from '@alfa-client/ui'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { DocumentationComponent } from './help-menu/documentation/documentation.component'; -import { OpenDocumentationButtonComponent } from "./help-menu/documentation/open-documentation-button/open-documentation-button.component"; +import { OpenDocumentationButtonComponent } from './help-menu/documentation/open-documentation-button/open-documentation-button.component'; import { HelpMenuComponent } from './help-menu/help-menu.component'; @NgModule({ - imports: [ - CommonModule, - TechSharedModule, - UiModule - ], - declarations: [ - HelpMenuComponent, - DocumentationComponent, - OpenDocumentationButtonComponent - ], - exports:[ - HelpMenuComponent - ] + imports: [CommonModule, TechSharedModule, UiModule], + declarations: [HelpMenuComponent, DocumentationComponent, OpenDocumentationButtonComponent], + exports: [HelpMenuComponent], }) export class UserAssistanceModule {} diff --git a/alfa-client/libs/user-assistance/src/test-setup.ts b/alfa-client/libs/user-assistance/src/test-setup.ts index 5870fdabb6470fd0f6f3f63be3d4f6b8041b4dd2..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/user-assistance/src/test-setup.ts +++ b/alfa-client/libs/user-assistance/src/test-setup.ts @@ -26,17 +26,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/user-assistance/tsconfig.json b/alfa-client/libs/user-assistance/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/user-assistance/tsconfig.json +++ b/alfa-client/libs/user-assistance/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/user-assistance/tsconfig.lib.json b/alfa-client/libs/user-assistance/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/user-assistance/tsconfig.lib.json +++ b/alfa-client/libs/user-assistance/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/user-assistance/tsconfig.spec.json b/alfa-client/libs/user-assistance/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/user-assistance/tsconfig.spec.json +++ b/alfa-client/libs/user-assistance/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/user-profile-shared/.eslintrc.json b/alfa-client/libs/user-profile-shared/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/user-profile-shared/.eslintrc.json +++ b/alfa-client/libs/user-profile-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/user-profile-shared/jest.config.ts b/alfa-client/libs/user-profile-shared/jest.config.ts index cb813f281febaef7eb21747cd54e9171b5476256..9dec175d9cafac448ef059c043f5ffd46ba6d663 100644 --- a/alfa-client/libs/user-profile-shared/jest.config.ts +++ b/alfa-client/libs/user-profile-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'user-profile-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/user-profile-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'user-profile-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/user-profile-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/user-profile-shared/project.json b/alfa-client/libs/user-profile-shared/project.json index 85ab4c0b966324a0975396bf169b5f7fea1d41ff..7170e2c24d36e8b4ce7677e4d55b9b68cc01ea9a 100644 --- a/alfa-client/libs/user-profile-shared/project.json +++ b/alfa-client/libs/user-profile-shared/project.json @@ -1,29 +1,29 @@ { - "name": "user-profile-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/user-profile-shared/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/user-profile-shared"], - "options": { - "tsConfig": "libs/user-profile-shared/tsconfig.spec.json", - "jestConfig": "libs/user-profile-shared/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/user-profile-shared/src/**/*.ts", - "libs/user-profile-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [] + "name": "user-profile-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/user-profile-shared/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/user-profile-shared"], + "options": { + "tsConfig": "libs/user-profile-shared/tsconfig.spec.json", + "jestConfig": "libs/user-profile-shared/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/user-profile-shared/src/**/*.ts", + "libs/user-profile-shared/src/**/*.html" + ] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [] } diff --git a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.actions.ts b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.actions.ts index 3aed8e53ee595b23586d40921eaadfaa2ceae6ab..7e505d7a4e203e1c5fda02bc9993f5704c359ae2 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.actions.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.actions.ts @@ -1,5 +1,9 @@ import { TypedActionCreator } from '@alfa-client/tech-shared'; import { createAction } from '@ngrx/store'; -export const showUserProfileSearch: TypedActionCreator = createAction('[UserProfile] Show user profile search'); -export const hideUserProfileSearch: TypedActionCreator = createAction('[UserProfile] Hide user profile search'); \ No newline at end of file +export const showUserProfileSearch: TypedActionCreator = createAction( + '[UserProfile] Show user profile search', +); +export const hideUserProfileSearch: TypedActionCreator = createAction( + '[UserProfile] Hide user profile search', +); diff --git a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.facade.spec.ts b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.facade.spec.ts index abb5c5888073e944f4f9a33023f4279e792a95a6..54ae8581e507b3bd5a3a362f97bb4a8ea1d627f7 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.facade.spec.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.facade.spec.ts @@ -7,49 +7,46 @@ import * as UserProfileActions from './user-profile.actions'; import * as UserProfileSelectors from './user-profile.selectors'; describe('UserProfileFacade', () => { - let facade: UserProfileFacade; - let store: Mock<Store>; + let facade: UserProfileFacade; + let store: Mock<Store>; - let selectionSubject: Subject<any>; + let selectionSubject: Subject<any>; - beforeEach(() => { - store = mock(Store); + beforeEach(() => { + store = mock(Store); - selectionSubject = new Subject(); + selectionSubject = new Subject(); - store.select.mockReturnValue(selectionSubject); + store.select.mockReturnValue(selectionSubject); - facade = new UserProfileFacade(useFromMock(<any>store)); - }) + facade = new UserProfileFacade(useFromMock(<any>store)); + }); - it('is initialized', () => { - expect(facade).toBeTruthy(); - }) + it('is initialized', () => { + expect(facade).toBeTruthy(); + }); - describe('getUserProfileSearchVisibility', () => { + describe('getUserProfileSearchVisibility', () => { + it('should select from store', () => { + facade.getUserProfileSearchVisibility(); - it('should select from store', () => { - facade.getUserProfileSearchVisibility(); + expect(store.select).toHaveBeenCalledWith(UserProfileSelectors.userProfileSearchVisibilty); + }); + }); - expect(store.select).toHaveBeenCalledWith(UserProfileSelectors.userProfileSearchVisibilty); - }) - }) + describe('showUserProfileSearch', () => { + it('should dispatch action', () => { + facade.showUserProfileSearch(); - describe('showUserProfileSearch', () => { + expect(store.dispatch).toHaveBeenCalledWith(UserProfileActions.showUserProfileSearch()); + }); + }); - it('should dispatch action', () => { - facade.showUserProfileSearch(); + describe('hideUserProfileSearch', () => { + it('should dispatch action', () => { + facade.hideUserProfileSearch(); - expect(store.dispatch).toHaveBeenCalledWith(UserProfileActions.showUserProfileSearch()); - }); - }) - - describe('hideUserProfileSearch', () => { - - it('should dispatch action', () => { - facade.hideUserProfileSearch(); - - expect(store.dispatch).toHaveBeenCalledWith(UserProfileActions.hideUserProfileSearch()); - }); - }) -}) \ No newline at end of file + expect(store.dispatch).toHaveBeenCalledWith(UserProfileActions.hideUserProfileSearch()); + }); + }); +}); diff --git a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.facade.ts b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.facade.ts index 899b97f381716194c61bee5fa58f583bc76585f3..c9aeaf724db3e6fa0f185049e1500663fcd93d46 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.facade.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.facade.ts @@ -7,18 +7,17 @@ import * as UserProfileSelectors from './user-profile.selectors'; @Injectable() export class UserProfileFacade { + constructor(private readonly store: Store) {} - constructor(private readonly store: Store) { } + public getUserProfileSearchVisibility(): Observable<boolean> { + return this.store.select(UserProfileSelectors.userProfileSearchVisibilty); + } - public getUserProfileSearchVisibility(): Observable<boolean> { - return this.store.select(UserProfileSelectors.userProfileSearchVisibilty); - } + public showUserProfileSearch(): void { + this.store.dispatch(UserProfileActions.showUserProfileSearch()); + } - public showUserProfileSearch(): void { - this.store.dispatch(UserProfileActions.showUserProfileSearch()); - } - - public hideUserProfileSearch(): void { - this.store.dispatch(UserProfileActions.hideUserProfileSearch()); - } -} \ No newline at end of file + public hideUserProfileSearch(): void { + this.store.dispatch(UserProfileActions.hideUserProfileSearch()); + } +} diff --git a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.reducer.spec.ts b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.reducer.spec.ts index 69039ab5f83d698fc6d00f96b760bc6ecbf36e10..e30aa165cbe57ceb68025d2d4a57b18f0100612d 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.reducer.spec.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.reducer.spec.ts @@ -4,40 +4,35 @@ import { UserProfileState, initialState, reducer } from './user-profile.reducer' import * as UserProfileActions from './user-profile.actions'; describe('UserProfile Reducer', () => { + describe('unknown action', () => { + it('should return current state', () => { + const action = {} as Action; - describe('unknown action', () => { + const result = reducer(initialState, action); - it('should return current state', () => { - const action = {} as Action; + expect(result).toBe(initialState); + }); + }); - const result = reducer(initialState, action); + describe('userProfileSearchVisibilty', () => { + describe('on "showUserProfileSearch" action', () => { + it('should set userProfileSearchVisibilty to true', () => { + const action = UserProfileActions.showUserProfileSearch(); - expect(result).toBe(initialState); - }) - }) + const state: UserProfileState = reducer(initialState, action); - describe('userProfileSearchVisibilty', () => { + expect(state.userProfileSearchVisibilty).toBeTruthy(); + }); + }); - describe('on "showUserProfileSearch" action', () => { + describe('on "hideUserProfileSearch" action', () => { + it('should set userProfileSearchVisibilty to false', () => { + const action = UserProfileActions.hideUserProfileSearch(); - it('should set userProfileSearchVisibilty to true', () => { - const action = UserProfileActions.showUserProfileSearch(); + const state: UserProfileState = reducer(initialState, action); - const state: UserProfileState = reducer(initialState, action); - - expect(state.userProfileSearchVisibilty).toBeTruthy(); - }) - }) - - describe('on "hideUserProfileSearch" action', () => { - - it('should set userProfileSearchVisibilty to false', () => { - const action = UserProfileActions.hideUserProfileSearch(); - - const state: UserProfileState = reducer(initialState, action); - - expect(state.userProfileSearchVisibilty).toBeFalsy(); - }) - }) - }) -}); \ No newline at end of file + expect(state.userProfileSearchVisibilty).toBeFalsy(); + }); + }); + }); +}); diff --git a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.reducer.ts b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.reducer.ts index 01de3ca2840627d75556bbd93e1403bbe8922c5f..b2050494628f9a8bda3f61a21e42f6d46e033171 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.reducer.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.reducer.ts @@ -5,29 +5,35 @@ import * as UserProfileActions from './user-profile.actions'; export const USER_PROFILE_FEATURE_KEY = 'UserProfileState'; export interface UserProfilePartialState { - readonly [USER_PROFILE_FEATURE_KEY]: UserProfileState; + readonly [USER_PROFILE_FEATURE_KEY]: UserProfileState; } export interface UserProfileState { - userProfileSearchVisibilty: boolean; + userProfileSearchVisibilty: boolean; } export const initialState: UserProfileState = { - userProfileSearchVisibilty: false + userProfileSearchVisibilty: false, }; const userProfileReducer: ActionReducer<UserProfileState, Action> = createReducer( - initialState, - on(UserProfileActions.showUserProfileSearch, (state: UserProfileState): UserProfileState => ({ - ...state, - userProfileSearchVisibilty: true - })), - on(UserProfileActions.hideUserProfileSearch, (state: UserProfileState): UserProfileState => ({ - ...state, - userProfileSearchVisibilty: false - })) + initialState, + on( + UserProfileActions.showUserProfileSearch, + (state: UserProfileState): UserProfileState => ({ + ...state, + userProfileSearchVisibilty: true, + }), + ), + on( + UserProfileActions.hideUserProfileSearch, + (state: UserProfileState): UserProfileState => ({ + ...state, + userProfileSearchVisibilty: false, + }), + ), ); export function reducer(state: UserProfileState, action: Action): UserProfileState { - return userProfileReducer(state, action); + return userProfileReducer(state, action); } diff --git a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.selectors.spec.ts b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.selectors.spec.ts index 67d303e3b44ab31146fb9e148e7ecb8a4f8e9048..5cae2c14f54874f51882f0b6673248088bfeddf2 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.selectors.spec.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.selectors.spec.ts @@ -3,23 +3,24 @@ import { UserProfilePartialState, initialState } from './user-profile.reducer'; import * as UserProfileSelectors from './user-profile.selectors'; describe('UserProfile Selectors', () => { + let state: UserProfilePartialState; - let state: UserProfilePartialState; + const userProfileSearchVisibilty: boolean = false; - const userProfileSearchVisibilty: boolean = false; + beforeEach(() => { + state = { + UserProfileState: { + ...initialState, + userProfileSearchVisibilty, + }, + }; + }); - beforeEach(() => { - state = { - UserProfileState: { - ...initialState, - userProfileSearchVisibilty - } - }; - }); + it('should return vorgangList', () => { + const result: boolean = UserProfileSelectors.userProfileSearchVisibilty.projector( + state.UserProfileState, + ); - it('should return vorgangList', () => { - const result: boolean = UserProfileSelectors.userProfileSearchVisibilty.projector(state.UserProfileState); - - expect(result).toBe(userProfileSearchVisibilty); - }) -}); \ No newline at end of file + expect(result).toBe(userProfileSearchVisibilty); + }); +}); diff --git a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.selectors.ts b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.selectors.ts index d7a0df4cb64f3d808cc0af4f1157a37b5fb7a90c..724fd637921cbedd854cb09f134522fc17b65675 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.selectors.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/+state/user-profile.selectors.ts @@ -1,6 +1,11 @@ import { MemoizedSelector, createFeatureSelector, createSelector } from '@ngrx/store'; import { USER_PROFILE_FEATURE_KEY, UserProfileState } from './user-profile.reducer'; -export const getUserProfileState: MemoizedSelector<object, UserProfileState> = createFeatureSelector<UserProfileState>(USER_PROFILE_FEATURE_KEY); +export const getUserProfileState: MemoizedSelector<object, UserProfileState> = + createFeatureSelector<UserProfileState>(USER_PROFILE_FEATURE_KEY); -export const userProfileSearchVisibilty: MemoizedSelector<UserProfileState, boolean> = createSelector(getUserProfileState, (state: UserProfileState) => state.userProfileSearchVisibilty); \ No newline at end of file +export const userProfileSearchVisibilty: MemoizedSelector<UserProfileState, boolean> = + createSelector( + getUserProfileState, + (state: UserProfileState) => state.userProfileSearchVisibilty, + ); diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile-shared.module.spec.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile-shared.module.spec.ts index 5723f05cdd0df76eb8c59767c0d47571d2f601a5..f9040cd64b4935c453b3311fc3c0a6a297d88f27 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile-shared.module.spec.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile-shared.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { UserProfileSharedModule } from './user-profile-shared.module'; describe('UserProfileSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [UserProfileSharedModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [UserProfileSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(UserProfileSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(UserProfileSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile-shared.module.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile-shared.module.ts index 601ce458e0d78f2499e90b44ddbb4ecc4f86d346..e246c822148f9bfc9c9768a5bf23e10f074d7c48 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile-shared.module.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile-shared.module.ts @@ -29,13 +29,10 @@ import { UserProfileFacade } from './+state/user-profile.facade'; import * as fromUserProfile from './+state/user-profile.reducer'; @NgModule({ - imports: [ - CommonModule, - StoreModule.forFeature( - fromUserProfile.USER_PROFILE_FEATURE_KEY, - fromUserProfile.reducer - ) - ], - providers:[UserProfileFacade] + imports: [ + CommonModule, + StoreModule.forFeature(fromUserProfile.USER_PROFILE_FEATURE_KEY, fromUserProfile.reducer), + ], + providers: [UserProfileFacade], }) -export class UserProfileSharedModule { } \ No newline at end of file +export class UserProfileSharedModule {} diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile.linkrel.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile.linkrel.ts index 53c9f82e5f7a5405c99868cbf0ffec65a0667ebb..fe23f4ac1cedbe432f7a007778813973b831e3fb 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile.linkrel.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile.linkrel.ts @@ -22,9 +22,9 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum UserProfileListLinkRel { - USER_PROFILE_LIST = 'userProfileList' + USER_PROFILE_LIST = 'userProfileList', } export enum UserProfileLinkRel { - SETTINGS = 'settings' -} \ No newline at end of file + SETTINGS = 'settings', +} diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile.message.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile.message.ts index 9cc5318d1ac434a4c2bad563f6c7ec4fb8306be4..bb366b27db78d33065791562e54a334a9af4c28e 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile.message.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile.message.ts @@ -24,8 +24,8 @@ import { MessageCode } from '@alfa-client/tech-shared'; export const userProfileMessage = { - [MessageCode.SERVICE_UNAVAILABLE]: 'Die Benutzerdaten konnten nicht geladen werden', - [MessageCode.RESOURCE_NOT_FOUND]: 'Der zugewiesene Bearbeiter konnte nicht gefunden werden', - UNASSIGNED: 'Kein Bearbeiter zugewiesen', - UNKNOW_ERROR: 'Ein unbekannter Fehler ist aufgetreten' -} + [MessageCode.SERVICE_UNAVAILABLE]: 'Die Benutzerdaten konnten nicht geladen werden', + [MessageCode.RESOURCE_NOT_FOUND]: 'Der zugewiesene Bearbeiter konnte nicht gefunden werden', + UNASSIGNED: 'Kein Bearbeiter zugewiesen', + UNKNOW_ERROR: 'Ein unbekannter Fehler ist aufgetreten', +}; diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile.model.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile.model.ts index 3bfb92611eb5c2d692a87d61c3bbe1c79c2a6418..6585d30413e3eb7ee12d8be18e2a31ab369ae7c7 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile.model.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile.model.ts @@ -21,14 +21,14 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { ListResource } from "@alfa-client/tech-shared"; -import { Resource } from "@ngxp/rest"; +import { ListResource } from '@alfa-client/tech-shared'; +import { Resource } from '@ngxp/rest'; export interface UserProfile { - createdAt: Date; - firstName: string; - lastName: string; + createdAt: Date; + firstName: string; + lastName: string; } -export interface UserProfileResource extends UserProfile, Resource { } -export interface UserProfileListResource extends ListResource { } \ No newline at end of file +export interface UserProfileResource extends UserProfile, Resource {} +export interface UserProfileListResource extends ListResource {} diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.spec.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.spec.ts index bcde63b17d6bbd0528ef93b8461e8e934b34074e..b8e5595ec7d67a02b2905ff881a3c8bc1d7dc4e1 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.spec.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.spec.ts @@ -24,116 +24,123 @@ import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; import { HttpErrorHandler, TechSharedModule } from '@alfa-client/tech-shared'; import { mock, mockClass, useFromMock } from '@alfa-client/test-utils'; -import { VorgangHeaderLinkRel, VorgangResource, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangHeaderLinkRel, + VorgangResource, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { ResourceFactory } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; -import { createVorgangResource, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; +import { + createVorgangResource, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; import { createUserProfileListResource, createUserProfileResource } from '../../test/user-profile'; import { UserProfileListResource, UserProfileResource } from './user-profile.model'; import { UserProfileRepository } from './user-profile.repository'; describe('User profile repository', () => { - let repository: UserProfileRepository; + let repository: UserProfileRepository; - const resourceFactory = mock(ResourceFactory); - const resourceWrapper = { get: jest.fn() }; + const resourceFactory = mock(ResourceFactory); + const resourceWrapper = { get: jest.fn() }; - const vorgang: VorgangResource = createVorgangResource(); - const userProfile: UserProfileResource = createUserProfileResource(); + const vorgang: VorgangResource = createVorgangResource(); + const userProfile: UserProfileResource = createUserProfileResource(); - beforeEach(() => { - const classMock = mockClass(TechSharedModule); - classMock.injector = <any>{ get: () => useFromMock(mock(HttpErrorHandler)) }; + beforeEach(() => { + const classMock = mockClass(TechSharedModule); + classMock.injector = <any>{ get: () => useFromMock(mock(HttpErrorHandler)) }; - repository = new UserProfileRepository(useFromMock(resourceFactory)); + repository = new UserProfileRepository(useFromMock(resourceFactory)); - resourceFactory.from.mockReturnValue(resourceWrapper); - resourceFactory.fromId.mockReturnValue(resourceWrapper); - resourceWrapper.get.mockReturnValue(cold('a', { a: userProfile })); - }) + resourceFactory.from.mockReturnValue(resourceWrapper); + resourceFactory.fromId.mockReturnValue(resourceWrapper); + resourceWrapper.get.mockReturnValue(cold('a', { a: userProfile })); + }); - it('should be created', () => { - expect(repository).toBeTruthy(); - }) + it('should be created', () => { + expect(repository).toBeTruthy(); + }); - describe('get user profile', () => { + describe('get user profile', () => { + const linkRel: string = VorgangHeaderLinkRel.ASSIGNED_TO; - const linkRel: string = VorgangHeaderLinkRel.ASSIGNED_TO; + it('should call resource factory', () => { + repository.getUserProfile(vorgang, linkRel); - it('should call resource factory', () => { - repository.getUserProfile(vorgang, linkRel); + expect(resourceFactory.from).toHaveBeenCalledWith(vorgang); + }); - expect(resourceFactory.from).toHaveBeenCalledWith(vorgang); - }) + it('should get', () => { + repository.getUserProfile(vorgang, linkRel); - it('should get', () => { - repository.getUserProfile(vorgang, linkRel); + expect(resourceWrapper.get).toHaveBeenCalledWith(linkRel); + }); - expect(resourceWrapper.get).toHaveBeenCalledWith(linkRel); - }) + it('should return result', () => { + const result = repository.getUserProfile(vorgang, linkRel); - it('should return result', () => { - const result = repository.getUserProfile(vorgang, linkRel); + expect(result).not.toBeNull(); + expect(result).toBeObservable(hot('a', { a: userProfile })); + }); + }); - expect(result).not.toBeNull(); - expect(result).toBeObservable(hot('a', { a: userProfile })); - }) - }) + describe('search', () => { + const searchBy: string = 'SearchMe'; + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.SEARCH_USER_PROFILES, + ]); + const userProfileListResource: UserProfileListResource = createUserProfileListResource(); - describe('search', () => { + beforeEach(() => { + resourceWrapper.get.mockReturnValue(cold('a', { a: userProfileListResource })); + }); - const searchBy: string = 'SearchMe'; - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.SEARCH_USER_PROFILES]); - const userProfileListResource: UserProfileListResource = createUserProfileListResource(); + it('should call resource factory', () => { + repository.search(vorgangWithEingang, searchBy); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(cold('a', { a: userProfileListResource })); - }) + expect(resourceFactory.fromId).toHaveBeenCalled(); + }); - it('should call resource factory', () => { - repository.search(vorgangWithEingang, searchBy); + it('should build search-url', () => { + repository.buildSearchByUrl = jest.fn(); - expect(resourceFactory.fromId).toHaveBeenCalled(); - }) + repository.search(vorgangWithEingang, searchBy); - it('should build search-url', () => { - repository.buildSearchByUrl = jest.fn(); + expect(repository.buildSearchByUrl).toHaveBeenCalledWith(vorgangWithEingang, searchBy); + }); - repository.search(vorgangWithEingang, searchBy); + it('should return result', () => { + const result = repository.search(vorgangWithEingang, searchBy); - expect(repository.buildSearchByUrl).toHaveBeenCalledWith(vorgangWithEingang, searchBy); - }) + expect(result).not.toBeNull(); + expect(result).toBeObservable(hot('a', { a: userProfileListResource })); + }); + }); - it('should return result', () => { - const result = repository.search(vorgangWithEingang, searchBy); + describe('getCurrentUser', () => { + const apiRoot: ApiRootResource = createApiRootResource(); - expect(result).not.toBeNull(); - expect(result).toBeObservable(hot('a', { a: userProfileListResource })); - }) - }) + it('should call resource Factory', () => { + repository.getCurrentUser(apiRoot); - describe('getCurrentUser', () => { + expect(resourceFactory.from).toHaveBeenCalledWith(apiRoot); + }); - const apiRoot: ApiRootResource = createApiRootResource(); + it('should call get', () => { + repository.getCurrentUser(apiRoot); - it('should call resource Factory', () => { - repository.getCurrentUser(apiRoot); + expect(resourceWrapper.get).toHaveBeenCalledWith(ApiRootLinkRel.CURRENT_USER); + }); - expect(resourceFactory.from).toHaveBeenCalledWith(apiRoot); - }) + it('should return result', () => { + const result = repository.getCurrentUser(apiRoot); - it('should call get', () => { - repository.getCurrentUser(apiRoot); - - expect(resourceWrapper.get).toHaveBeenCalledWith(ApiRootLinkRel.CURRENT_USER); - }) - - it('should return result', () => { - const result = repository.getCurrentUser(apiRoot); - - expect(result).not.toBeNull(); - expect(result).toBeObservable(hot('a', { a: userProfile })); - }) - }) -}) \ No newline at end of file + expect(result).not.toBeNull(); + expect(result).toBeObservable(hot('a', { a: userProfile })); + }); + }); +}); diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.ts index 10f9c32d952af1f64ceedba59a6df075fdae07d9..c893a27f1c034eefb881c4d5df03d837d3fa8c88 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile.repository.ts @@ -31,27 +31,32 @@ import { UserProfileListResource, UserProfileResource } from './user-profile.mod @Injectable({ providedIn: 'root' }) export class UserProfileRepository { + static SEARCH_PARAM: string = 'searchBy'; - static SEARCH_PARAM: string = 'searchBy'; + constructor(private resourceFactory: ResourceFactory) {} - constructor(private resourceFactory: ResourceFactory) { } + @SkipInterceptor() + public getUserProfile(resource: Resource, linkRel: string): Observable<UserProfileResource> { + return this.resourceFactory.from(resource).get(linkRel); + } - @SkipInterceptor() - public getUserProfile(resource: Resource, linkRel: string): Observable<UserProfileResource> { - return this.resourceFactory.from(resource).get(linkRel); - } + @SkipInterceptor() + public getCurrentUser(apiRootResource: ApiRootResource): Observable<UserProfileResource> { + return this.resourceFactory.from(apiRootResource).get(ApiRootLinkRel.CURRENT_USER); + } - @SkipInterceptor() - public getCurrentUser(apiRootResource: ApiRootResource): Observable<UserProfileResource> { - return this.resourceFactory.from(apiRootResource).get(ApiRootLinkRel.CURRENT_USER); - } + @SkipInterceptor() + public search( + vorgangWithEingang: VorgangWithEingangResource, + searchBy: string, + ): Observable<UserProfileListResource> { + return this.resourceFactory.fromId(this.buildSearchByUrl(vorgangWithEingang, searchBy)).get(); + } - @SkipInterceptor() - public search(vorgangWithEingang: VorgangWithEingangResource, searchBy: string): Observable<UserProfileListResource> { - return this.resourceFactory.fromId(this.buildSearchByUrl(vorgangWithEingang, searchBy)).get(); - } - - buildSearchByUrl(vorgangWithEingang: VorgangWithEingangResource, searchBy: string): ResourceUri { - return getUrl(vorgangWithEingang, VorgangWithEingangLinkRel.SEARCH_USER_PROFILES).replace('{' + UserProfileRepository.SEARCH_PARAM + '}', searchBy); - } -} \ No newline at end of file + buildSearchByUrl(vorgangWithEingang: VorgangWithEingangResource, searchBy: string): ResourceUri { + return getUrl(vorgangWithEingang, VorgangWithEingangLinkRel.SEARCH_USER_PROFILES).replace( + '{' + UserProfileRepository.SEARCH_PARAM + '}', + searchBy, + ); + } +} diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile.service.spec.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile.service.spec.ts index 40504937fbaa69ae025b8258576eda934778ae19..6e5f5674069ec9f77548b28f2e54b9dd03b6408b 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile.service.spec.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile.service.spec.ts @@ -24,7 +24,14 @@ import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { ApiRootFacade, ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { ApiError, MessageCode, StateResource, createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + ApiError, + MessageCode, + StateResource, + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { VorgangHeaderLinkRel, VorgangResource, VorgangService } from '@alfa-client/vorgang-shared'; import { getLink } from '@ngxp/rest'; @@ -32,7 +39,10 @@ import { cold, hot } from 'jest-marbles'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { createApiError } from 'libs/tech-shared/test/error'; import { createHttpErrorResponse } from 'libs/tech-shared/test/http'; -import { createUserProfileListResource, createUserProfileResource } from 'libs/user-profile-shared/test/user-profile'; +import { + createUserProfileListResource, + createUserProfileResource, +} from 'libs/user-profile-shared/test/user-profile'; import { vorgangWithEingang } from 'libs/vorgang-shared/src/lib/+state/vorgang.selectors'; import { createVorgangResource } from 'libs/vorgang-shared/test/vorgang'; import { of, throwError } from 'rxjs'; @@ -42,314 +52,329 @@ import { UserProfileRepository } from './user-profile.repository'; import { UserProfileService } from './user-profile.service'; describe('UserProfileService', () => { - let service: UserProfileService; - let repository: Mock<UserProfileRepository>; - let apiRootFacade: Mock<ApiRootFacade>; - let navigationService: Mock<NavigationService>; - let vorgangService: Mock<VorgangService>; - let facade: Mock<UserProfileFacade>; + let service: UserProfileService; + let repository: Mock<UserProfileRepository>; + let apiRootFacade: Mock<ApiRootFacade>; + let navigationService: Mock<NavigationService>; + let vorgangService: Mock<VorgangService>; + let facade: Mock<UserProfileFacade>; + + const vorgang: VorgangResource = createVorgangResource([VorgangHeaderLinkRel.ASSIGNED_TO]); + const userProfile: UserProfileResource = createUserProfileResource(); + const userProfileList: UserProfileListResource = createUserProfileListResource(); + + beforeEach(() => { + repository = mock(UserProfileRepository); + apiRootFacade = mock(ApiRootFacade); + vorgangService = mock(VorgangService); + navigationService = mock(NavigationService); + navigationService.urlChanged = jest.fn(); + navigationService.urlChanged.mockReturnValue(of({})); + facade = mock(UserProfileFacade); + + service = new UserProfileService( + useFromMock(repository), + useFromMock(apiRootFacade), + useFromMock(navigationService), + useFromMock(vorgangService), + useFromMock(facade), + ); + }); - const vorgang: VorgangResource = createVorgangResource([VorgangHeaderLinkRel.ASSIGNED_TO]); - const userProfile: UserProfileResource = createUserProfileResource(); - const userProfileList: UserProfileListResource = createUserProfileListResource(); + it('should created', () => { + expect(service).toBeTruthy(); + }); - beforeEach(() => { - repository = mock(UserProfileRepository); - apiRootFacade = mock(ApiRootFacade); - vorgangService = mock(VorgangService); - navigationService = mock(NavigationService); - navigationService.urlChanged = jest.fn(); - navigationService.urlChanged.mockReturnValue(of({})); - facade = mock(UserProfileFacade); + describe('getCurrentUser', () => { + const apiRootResource: StateResource<ApiRootResource> = + createStateResource(createApiRootResource()); + const currentUserProfile: StateResource<UserProfileResource> = createStateResource( + createUserProfileResource(), + ); - service = new UserProfileService(useFromMock(repository), useFromMock(apiRootFacade), useFromMock(navigationService), useFromMock(vorgangService), useFromMock(facade)); - }) + it('should call get current user', () => { + service.getCurrentUserFromState = jest.fn(); - it('should created', () => { - expect(service).toBeTruthy(); - }) + service.getCurrentUser(); - describe('getCurrentUser', () => { + expect(service.getCurrentUserFromState).toHaveBeenCalled(); + }); - const apiRootResource: StateResource<ApiRootResource> = createStateResource(createApiRootResource()); - const currentUserProfile: StateResource<UserProfileResource> = createStateResource(createUserProfileResource()); + it('should call apiRoot facade', () => { + service.getCurrentUser(); - it('should call get current user', () => { - service.getCurrentUserFromState = jest.fn(); + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }); - service.getCurrentUser(); + it('should return initial values', () => { + service.getCurrentUserFromState = jest + .fn() + .mockReturnValue(hot('-a', { a: currentUserProfile })); + apiRootFacade.getApiRoot.mockReturnValue(hot('-a', { a: apiRootResource })); - expect(service.getCurrentUserFromState).toHaveBeenCalled(); - }) + const result = service.getCurrentUser(); - it('should call apiRoot facade', () => { - service.getCurrentUser(); + expect(result).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: currentUserProfile }), + ); + }); - expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); - }) + describe('handle get current user', () => { + beforeEach(() => { + service.handleGetCurrentUser = jest.fn(); + }); - it('should return initial values', () => { - service.getCurrentUserFromState = jest.fn().mockReturnValue(hot('-a', { a: currentUserProfile })); - apiRootFacade.getApiRoot.mockReturnValue(hot('-a', { a: apiRootResource })); + it('should be called if apiRoot exists', () => { + const apiRootResource: StateResource<ApiRootResource> = createStateResource( + createApiRootResource([ApiRootLinkRel.CURRENT_USER]), + ); + apiRootFacade.getApiRoot.mockReturnValue(of(apiRootResource)); - const result = service.getCurrentUser(); + service.getCurrentUser().subscribe(); - expect(result).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: currentUserProfile })); - }) + expect(service.handleGetCurrentUser).toHaveBeenCalled(); + }); - describe('handle get current user', () => { + it('should NOT be called if apiRoot is null', () => { + apiRootFacade.getApiRoot.mockReturnValue(of(createEmptyStateResource())); - beforeEach(() => { - service.handleGetCurrentUser = jest.fn(); - }) + service.getCurrentUser().subscribe(); - it('should be called if apiRoot exists', () => { - const apiRootResource: StateResource<ApiRootResource> = createStateResource(createApiRootResource([ApiRootLinkRel.CURRENT_USER])); - apiRootFacade.getApiRoot.mockReturnValue(of(apiRootResource)); + expect(service.handleGetCurrentUser).not.toHaveBeenCalled(); + }); + }); - service.getCurrentUser().subscribe(); + describe('handleGetCurrentUser', () => { + beforeEach(() => { + service.loadCurrentUser = jest.fn(); + }); - expect(service.handleGetCurrentUser).toHaveBeenCalled(); - }) + describe('with existing link', () => { + const apiRoot: ApiRootResource = createApiRootResource([ApiRootLinkRel.CURRENT_USER]); - it('should NOT be called if apiRoot is null', () => { - apiRootFacade.getApiRoot.mockReturnValue(of(createEmptyStateResource())); + it('should load current userProfile if link exists and no loading required', () => { + service.handleGetCurrentUser(createEmptyStateResource(), apiRoot); - service.getCurrentUser().subscribe(); + expect(service.loadCurrentUser).toHaveBeenCalledWith(apiRoot); + }); - expect(service.handleGetCurrentUser).not.toHaveBeenCalled(); - }) - }) + it('should not load current userProfile on error', () => { + service.handleGetCurrentUser(createErrorStateResource(createApiError()), apiRoot); - describe('handleGetCurrentUser', () => { + expect(service.loadCurrentUser).not.toHaveBeenCalled(); + }); + }); - beforeEach(() => { - service.loadCurrentUser = jest.fn(); - }) + describe('on missing link', () => { + const apiRoot: ApiRootResource = createApiRootResource(); - describe('with existing link', () => { + it('should not load current userProfile if link NOT exists', () => { + service.handleGetCurrentUser(currentUserProfile, apiRoot); - const apiRoot: ApiRootResource = createApiRootResource([ApiRootLinkRel.CURRENT_USER]); + expect(service.loadCurrentUser).not.toHaveBeenCalled(); + }); - it('should load current userProfile if link exists and no loading required', () => { - service.handleGetCurrentUser(createEmptyStateResource(), apiRoot); + it('should not load current userProfile if already loaded', () => { + service.handleGetCurrentUser(currentUserProfile, apiRoot); - expect(service.loadCurrentUser).toHaveBeenCalledWith(apiRoot); - }) + expect(service.loadCurrentUser).not.toHaveBeenCalled(); + }); - it('should not load current userProfile on error', () => { - service.handleGetCurrentUser(createErrorStateResource(createApiError()), apiRoot); + it('should not load current userProfile if is loading', () => { + service.handleGetCurrentUser({ ...createEmptyStateResource(), loading: true }, apiRoot); - expect(service.loadCurrentUser).not.toHaveBeenCalled(); - }) - }) + expect(service.loadCurrentUser).not.toHaveBeenCalled(); + }); + }); + }); - describe('on missing link', () => { + describe('load current user profile', () => { + const apiRoot: ApiRootResource = createApiRootResource(); + const userProfile: UserProfileResource = createUserProfileResource(); - const apiRoot: ApiRootResource = createApiRootResource(); + beforeEach(() => { + repository.getCurrentUser.mockReturnValue(of(userProfile)); + }); - it('should not load current userProfile if link NOT exists', () => { - service.handleGetCurrentUser(currentUserProfile, apiRoot); + it('should set stateResource loading true', () => { + service.setCurrentUserLoading = jest.fn(); - expect(service.loadCurrentUser).not.toHaveBeenCalled(); - }) + service.loadCurrentUser(apiRoot); - it('should not load current userProfile if already loaded', () => { - service.handleGetCurrentUser(currentUserProfile, apiRoot); + expect(service.setCurrentUserLoading).toHaveBeenCalled(); + }); - expect(service.loadCurrentUser).not.toHaveBeenCalled(); - }) + it('should call repository', () => { + service.setCurrentUserLoading = jest.fn(); - it('should not load current userProfile if is loading', () => { - service.handleGetCurrentUser({ ...createEmptyStateResource(), loading: true }, apiRoot); + service.loadCurrentUser(apiRoot); - expect(service.loadCurrentUser).not.toHaveBeenCalled(); - }) - }) - }) + expect(repository.getCurrentUser).toHaveBeenCalledWith(apiRoot); + }); - describe('load current user profile', () => { + it('should createStateResource', () => { + service.createStateResourceForUpdate = jest.fn(); - const apiRoot: ApiRootResource = createApiRootResource(); - const userProfile: UserProfileResource = createUserProfileResource(); + service.loadCurrentUser(apiRoot); - beforeEach(() => { - repository.getCurrentUser.mockReturnValue(of(userProfile)); - }) + expect(service.createStateResourceForUpdate).toHaveBeenCalledWith(userProfile); + }); - it('should set stateResource loading true', () => { - service.setCurrentUserLoading = jest.fn(); + it('should set value', () => { + service.setCurrentUser = jest.fn(); - service.loadCurrentUser(apiRoot); + service.loadCurrentUser(apiRoot); - expect(service.setCurrentUserLoading).toHaveBeenCalled(); - }) + expect(service.setCurrentUser).toHaveBeenCalled(); + }); - it('should call repository', () => { - service.setCurrentUserLoading = jest.fn(); + describe('with error', () => { + const errorResponse: HttpErrorResponse = createHttpErrorResponse(); - service.loadCurrentUser(apiRoot); + it('should call error handler', () => { + repository.getCurrentUser.mockReturnValue(throwError(() => errorResponse)); + service.handleError = jest.fn(); - expect(repository.getCurrentUser).toHaveBeenCalledWith(apiRoot); - }) + service.loadCurrentUser(apiRoot); - it('should createStateResource', () => { - service.createStateResourceForUpdate = jest.fn(); + expect(service.handleError).toHaveBeenCalledWith(errorResponse.error); + }); + }); + }); + }); - service.loadCurrentUser(apiRoot); + describe('load user profile', () => { + const linkRel: string = VorgangHeaderLinkRel.ASSIGNED_TO; - expect(service.createStateResourceForUpdate).toHaveBeenCalledWith(userProfile); - }) + beforeEach(() => { + repository.getUserProfile.mockReturnValue(of(userProfile)); + service.createIfNotExist(getLink(vorgang, linkRel).href); + service.updateUserProfile = jest.fn(); + }); - it('should set value', () => { - service.setCurrentUser = jest.fn(); + it('should call repository', () => { + service.loadUserProfile(vorgang, VorgangHeaderLinkRel.ASSIGNED_TO); - service.loadCurrentUser(apiRoot); + expect(repository.getUserProfile).toHaveBeenCalledWith(vorgang, linkRel); + }); - expect(service.setCurrentUser).toHaveBeenCalled(); - }) + it('should update value', () => { + service.createStateResourceForUpdate = jest.fn(); + (<any>service.createStateResourceForUpdate).mockReturnValue(createStateResource(userProfile)); - describe('with error', () => { + service.loadUserProfile(vorgang, VorgangHeaderLinkRel.ASSIGNED_TO); - const errorResponse: HttpErrorResponse = createHttpErrorResponse(); + expect(service.updateUserProfile).toHaveBeenCalledWith( + vorgang, + linkRel, + createStateResource(userProfile), + ); + }); - it('should call error handler', () => { - repository.getCurrentUser.mockReturnValue(throwError(() => errorResponse)); - service.handleError = jest.fn(); + describe('with error', () => { + const errorResponse: HttpErrorResponse = createHttpErrorResponse(); - service.loadCurrentUser(apiRoot); + it('should call error handler', () => { + repository.getUserProfile.mockReturnValue(throwError(() => errorResponse)); + service.handleError = jest.fn(); - expect(service.handleError).toHaveBeenCalledWith(errorResponse.error); - }); - }); - }) - }) + service.loadUserProfile(vorgang, linkRel); - describe('load user profile', () => { + expect(service.handleError).toHaveBeenCalledWith(errorResponse.error); + }); - const linkRel: string = VorgangHeaderLinkRel.ASSIGNED_TO; + it('should respond with ErrorStateResource for 404 errors', () => { + const result: ApiError = service.handleErrorByStatus({ + ...errorResponse, + status: HttpStatusCode.NotFound, + }); - beforeEach(() => { - repository.getUserProfile.mockReturnValue(of(userProfile)); - service.createIfNotExist(getLink(vorgang, linkRel).href); - service.updateUserProfile = jest.fn(); - }) + expect(result).toEqual(errorResponse.error); + }); - it('should call repository', () => { - service.loadUserProfile(vorgang, VorgangHeaderLinkRel.ASSIGNED_TO); + it('should respond with ErrorStateResource for 503 errors', () => { + const result: ApiError = service.handleErrorByStatus({ + ...errorResponse, + status: HttpStatusCode.ServiceUnavailable, + }); - expect(repository.getUserProfile).toHaveBeenCalledWith(vorgang, linkRel); - }) + expect(result).toEqual(errorResponse.error); + }); - it('should update value', () => { - service.createStateResourceForUpdate = jest.fn(); - (<any>service.createStateResourceForUpdate).mockReturnValue(createStateResource(userProfile)); + it('should respond with ErrorStateResource for 503 errors', () => { + const result: ApiError = service.handleErrorByStatus({ ...errorResponse, status: 0 }); - service.loadUserProfile(vorgang, VorgangHeaderLinkRel.ASSIGNED_TO); + expect(result.issues[0].messageCode).toEqual(MessageCode.SERVICE_UNAVAILABLE); + }); + }); + }); - expect(service.updateUserProfile).toHaveBeenCalledWith(vorgang, linkRel, createStateResource(userProfile)); - }) + describe('createStateResourceForUpdate', () => { + beforeEach(() => { + service.updateUserProfile = jest.fn(); + }); - describe('with error', () => { + it('should return stateResource with userProfile', () => { + const stateResource: StateResource<UserProfileResource> = + service.createStateResourceForUpdate(userProfile); - const errorResponse: HttpErrorResponse = createHttpErrorResponse(); + expect(stateResource).toEqual(createStateResource(userProfile)); + }); - it('should call error handler', () => { - repository.getUserProfile.mockReturnValue(throwError(() => errorResponse)); - service.handleError = jest.fn(); + it('should return stateResource with userProfile', () => { + const userProfile: ApiError = createApiError(); - service.loadUserProfile(vorgang, linkRel); + const errorStateResource: StateResource<UserProfileResource> = + service.createStateResourceForUpdate(userProfile); - expect(service.handleError).toHaveBeenCalledWith(errorResponse.error); - }); + expect(errorStateResource).toEqual(createErrorStateResource(userProfile)); + }); + }); - it('should respond with ErrorStateResource for 404 errors', () => { - const result: ApiError = service.handleErrorByStatus({ ...errorResponse, status: HttpStatusCode.NotFound }); + describe('search', () => { + const searchBy: string = 'SearchMe'; - expect(result).toEqual(errorResponse.error); - }); + beforeEach(() => { + repository.search.mockReturnValue(hot('-a', { a: userProfileList })); + vorgangService.getVorgangWithEingang.mockReturnValue( + of(createStateResource(vorgangWithEingang)), + ); + }); - it('should respond with ErrorStateResource for 503 errors', () => { - const result: ApiError = service.handleErrorByStatus({ ...errorResponse, status: HttpStatusCode.ServiceUnavailable }); + it('should call repository', () => { + service.search(searchBy); - expect(result).toEqual(errorResponse.error); - }); + expect(repository.search).toHaveBeenCalledWith(vorgangWithEingang, searchBy); + }); - it('should respond with ErrorStateResource for 503 errors', () => { - const result: ApiError = service.handleErrorByStatus({ ...errorResponse, status: 0 }); + it('should call vorgang service', () => { + service.search(searchBy); - expect(result.issues[0].messageCode).toEqual(MessageCode.SERVICE_UNAVAILABLE); - }); - }); - }) + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); + }); - describe('createStateResourceForUpdate', () => { + describe('getUserProfileSearchVisibility', () => { + it('should call facade', () => { + service.getUserProfileSearchVisibility(); - beforeEach(() => { - service.updateUserProfile = jest.fn(); - }) + expect(facade.getUserProfileSearchVisibility).toHaveBeenCalled(); + }); + }); - it('should return stateResource with userProfile', () => { - const stateResource: StateResource<UserProfileResource> = service.createStateResourceForUpdate(userProfile); + describe('showUserProfileSearch', () => { + it('should call facade', () => { + service.showUserProfileSearch(); - expect(stateResource).toEqual(createStateResource(userProfile)); - }) + expect(facade.showUserProfileSearch).toHaveBeenCalled(); + }); + }); - it('should return stateResource with userProfile', () => { - const userProfile: ApiError = createApiError(); + describe('hideUserProfileSearch', () => { + it('should call facade', () => { + service.hideUserProfileSearch(); - const errorStateResource: StateResource<UserProfileResource> = service.createStateResourceForUpdate(userProfile); - - expect(errorStateResource).toEqual(createErrorStateResource(userProfile)); - }) - }) - - describe('search', () => { - - const searchBy: string = 'SearchMe'; - - beforeEach(() => { - repository.search.mockReturnValue(hot('-a', { a: userProfileList })) - vorgangService.getVorgangWithEingang.mockReturnValue(of(createStateResource(vorgangWithEingang))); - }) - - it('should call repository', () => { - service.search(searchBy); - - expect(repository.search).toHaveBeenCalledWith(vorgangWithEingang, searchBy); - }) - - it('should call vorgang service', () => { - service.search(searchBy); - - expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); - }) - }) - - describe('getUserProfileSearchVisibility', () => { - - it('should call facade', () => { - service.getUserProfileSearchVisibility(); - - expect(facade.getUserProfileSearchVisibility).toHaveBeenCalled(); - }) - }) - - describe('showUserProfileSearch', () => { - - it('should call facade', () => { - service.showUserProfileSearch(); - - expect(facade.showUserProfileSearch).toHaveBeenCalled(); - }) - }) - - describe('hideUserProfileSearch', () => { - - it('should call facade', () => { - service.hideUserProfileSearch(); - - expect(facade.hideUserProfileSearch).toHaveBeenCalled(); - }) - }) -}) \ No newline at end of file + expect(facade.hideUserProfileSearch).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile.service.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile.service.ts index 0d95e7565cc2f301fc59e3c57bbad6fc7b055f88..e6bb90a524cd2ed537190c35deb14c77f6091ac6 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile.service.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile.service.ts @@ -26,7 +26,20 @@ import { Injectable } from '@angular/core'; import { Params } from '@angular/router'; import { ApiRootFacade, ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { ApiError, MessageCode, StateResource, createEmptyStateResource, createErrorStateResource, createStateResource, doIfLoadingRequired, isApiError, isLoadingRequired, isNotFound, isNotNull, isServiceUnavailable } from '@alfa-client/tech-shared'; +import { + ApiError, + MessageCode, + StateResource, + createEmptyStateResource, + createErrorStateResource, + createStateResource, + doIfLoadingRequired, + isApiError, + isLoadingRequired, + isNotFound, + isNotNull, + isServiceUnavailable, +} from '@alfa-client/tech-shared'; import { VorgangService } from '@alfa-client/vorgang-shared'; import { getUrl, hasLink } from '@ngxp/rest'; import { Resource, ResourceUri } from '@ngxp/rest/lib/resource.model'; @@ -39,172 +52,204 @@ import { UserProfileRepository } from './user-profile.repository'; @Injectable({ providedIn: 'root' }) export class UserProfileService { - - private userProfiles = {}; - private userProfileSearchList: BehaviorSubject<StateResource<UserProfileListResource>> = new BehaviorSubject(createEmptyStateResource<UserProfileListResource>()); - private currentUser: BehaviorSubject<StateResource<UserProfileResource>> = new BehaviorSubject(createEmptyStateResource<UserProfileResource>()); - - private navigationSubscription: Subscription; - - private searchSubscription: Subscription; - - constructor( - private repository: UserProfileRepository, - private apiRootFacade: ApiRootFacade, - private navigationService: NavigationService, - private vorgangService: VorgangService, - private facade: UserProfileFacade - ) { - this.listenOnNavigation(); - } - - private listenOnNavigation(): void { - if (!isNil(this.navigationSubscription)) this.navigationSubscription.unsubscribe(); - this.navigationSubscription = this.navigationService.urlChanged().subscribe(params => this.onNavigation(params)); - } - - onNavigation(params: Params): void { - if (NavigationService.isVorgangListPage(params)) { - this.userProfiles = {}; - this.hideUserProfileSearch(); - } else if (NavigationService.isVorgangDetailPage(params, VorgangService.VORGANG_WITH_EINGANG_URL)) { - this.userProfiles = {}; - } - } - - public getAssignedUserProfile(assignedTo: Resource, linkRel: string): Observable<StateResource<UserProfileResource>> { - const uri: ResourceUri = this.getUserProfileUri(assignedTo, linkRel); - - this.createIfNotExist(uri); - - doIfLoadingRequired(this.userProfiles[uri].value, () => { - this.userProfiles[uri].next({ ...this.userProfiles[uri].value, loading: true }); - this.loadUserProfile(assignedTo, linkRel) - }); - return this.userProfiles[uri].asObservable(); - } - - public getCurrentUser(): Observable<StateResource<UserProfileResource>> { - return combineLatest([this.getCurrentUserFromState(), this.apiRootFacade.getApiRoot()]).pipe( - filter(([, apiRoot]) => isNotNull(apiRoot.resource)), - tap(([currentUser, apiRoot]) => this.handleGetCurrentUser(currentUser, apiRoot.resource)), - map(([currentUser, ]) => currentUser), - startWith(createEmptyStateResource<UserProfileResource>(true)) - ) - } - - getCurrentUserFromState(): Observable<StateResource<UserProfileResource>>{ - return this.currentUser.asObservable(); - } - - handleGetCurrentUser(currentUser: StateResource<UserProfileResource>, apiRoot: ApiRootResource): void { - if(hasLink(apiRoot, ApiRootLinkRel.CURRENT_USER) && isLoadingRequired(currentUser)){ - this.loadCurrentUser(apiRoot); - } - } - - loadCurrentUser(apiRoot: ApiRootResource): void { - this.setCurrentUserLoading(); - this.repository.getCurrentUser(apiRoot) - .pipe( - catchError(errorResponse => this.handleError(errorResponse.error)), - first(), - ).subscribe((currentUser: ApiError | UserProfileResource) => this.setCurrentUser(this.createStateResourceForUpdate(currentUser))) - } - - setCurrentUserLoading(): void { - this.currentUser.next(createEmptyStateResource<UserProfileResource>(true)); - } - - setCurrentUser(userProfile: StateResource<UserProfileResource>): void { - this.currentUser.next(userProfile); - } - - createIfNotExist(uri: ResourceUri): void { - if (isNil(this.userProfiles[uri])) this.userProfiles[uri] = new BehaviorSubject(createEmptyStateResource<UserProfileResource>()); - } - - loadUserProfile(vorgang: Resource, linkRel: string): void { - this.repository.getUserProfile(vorgang, linkRel) - .pipe( - catchError(errorResponse => this.handleError(errorResponse.error)), - first() - ).subscribe((response: ApiError | UserProfileResource) => this.updateUserProfile(vorgang, linkRel, this.createStateResourceForUpdate(response))); - } - - handleError(errorResponse: HttpErrorResponse): Observable<ApiError> { - return of(this.handleErrorByStatus(errorResponse)); - } - - handleErrorByStatus(error: HttpErrorResponse): ApiError { - if (isNotFound(error.status) || isServiceUnavailable(error.status)) { - return error.error; - } - if (this.isNetworkError(error.status)) { - return this.buildServiceUnavailableApiError(); - } - throwError({ error }); - } - - private isNetworkError(status: number): boolean { - return status == 0; - } - - private buildServiceUnavailableApiError(): ApiError { - return <ApiError>{ issues: [{ messageCode: MessageCode.SERVICE_UNAVAILABLE }] }; - } - - createStateResourceForUpdate(response: ApiError | UserProfileResource): StateResource<UserProfileResource> { - if (isApiError(response)) { - return createErrorStateResource(<ApiError>response); - } else { - return createStateResource(<UserProfileResource>response); - } - } - - updateUserProfile(vorgang: Resource, linkRel: string, userProfile: StateResource<UserProfileResource>): void { - //TOCHECK Potentielle Fehlerstelle: "cannot read 'next' of null/undefined" - this.userProfiles[this.getUserProfileUri(vorgang, linkRel)].next(userProfile); - } - - private getUserProfileUri(vorgang: Resource, linkRel: string): ResourceUri { - return getUrl(vorgang, linkRel); - } - - public getSearchedUserProfiles(): Observable<StateResource<UserProfileListResource>> { - return this.userProfileSearchList.asObservable(); - } - - public search(searchBy: string): Observable<StateResource<UserProfileListResource>> { - //TODO Im FormService unterscheiden, ob der Suchbegriff leer ist und direkt die "clearSearchList" Methode vom Service aufrufen. - if (isNil(searchBy)) { - this.clearSearchList(); - } else { - this.searchSubscription = this.vorgangService.getVorgangWithEingang().pipe( - filter(stateResource => stateResource.loaded), - switchMap(vorgangStateResource => this.repository.search(vorgangStateResource.resource, searchBy))) - .subscribe(userProfileList => { - this.userProfileSearchList.next(createStateResource(userProfileList)) - setTimeout(() => this.searchSubscription.unsubscribe(), 0); - }); - } - return this.userProfileSearchList.asObservable(); - } - - public clearSearchList() { - this.userProfileSearchList.next(createEmptyStateResource<UserProfileListResource>()); - } - - public getUserProfileSearchVisibility(): Observable<boolean> { - return this.facade.getUserProfileSearchVisibility(); - } - - public showUserProfileSearch(): void { - this.facade.showUserProfileSearch(); - } - - public hideUserProfileSearch(): void { - this.facade.hideUserProfileSearch(); - this.userProfileSearchList.next(createEmptyStateResource<UserProfileListResource>()); - } -} \ No newline at end of file + private userProfiles = {}; + private userProfileSearchList: BehaviorSubject<StateResource<UserProfileListResource>> = + new BehaviorSubject(createEmptyStateResource<UserProfileListResource>()); + private currentUser: BehaviorSubject<StateResource<UserProfileResource>> = new BehaviorSubject( + createEmptyStateResource<UserProfileResource>(), + ); + + private navigationSubscription: Subscription; + + private searchSubscription: Subscription; + + constructor( + private repository: UserProfileRepository, + private apiRootFacade: ApiRootFacade, + private navigationService: NavigationService, + private vorgangService: VorgangService, + private facade: UserProfileFacade, + ) { + this.listenOnNavigation(); + } + + private listenOnNavigation(): void { + if (!isNil(this.navigationSubscription)) this.navigationSubscription.unsubscribe(); + this.navigationSubscription = this.navigationService + .urlChanged() + .subscribe((params) => this.onNavigation(params)); + } + + onNavigation(params: Params): void { + if (NavigationService.isVorgangListPage(params)) { + this.userProfiles = {}; + this.hideUserProfileSearch(); + } else if ( + NavigationService.isVorgangDetailPage(params, VorgangService.VORGANG_WITH_EINGANG_URL) + ) { + this.userProfiles = {}; + } + } + + public getAssignedUserProfile( + assignedTo: Resource, + linkRel: string, + ): Observable<StateResource<UserProfileResource>> { + const uri: ResourceUri = this.getUserProfileUri(assignedTo, linkRel); + + this.createIfNotExist(uri); + + doIfLoadingRequired(this.userProfiles[uri].value, () => { + this.userProfiles[uri].next({ ...this.userProfiles[uri].value, loading: true }); + this.loadUserProfile(assignedTo, linkRel); + }); + return this.userProfiles[uri].asObservable(); + } + + public getCurrentUser(): Observable<StateResource<UserProfileResource>> { + return combineLatest([this.getCurrentUserFromState(), this.apiRootFacade.getApiRoot()]).pipe( + filter(([, apiRoot]) => isNotNull(apiRoot.resource)), + tap(([currentUser, apiRoot]) => this.handleGetCurrentUser(currentUser, apiRoot.resource)), + map(([currentUser]) => currentUser), + startWith(createEmptyStateResource<UserProfileResource>(true)), + ); + } + + getCurrentUserFromState(): Observable<StateResource<UserProfileResource>> { + return this.currentUser.asObservable(); + } + + handleGetCurrentUser( + currentUser: StateResource<UserProfileResource>, + apiRoot: ApiRootResource, + ): void { + if (hasLink(apiRoot, ApiRootLinkRel.CURRENT_USER) && isLoadingRequired(currentUser)) { + this.loadCurrentUser(apiRoot); + } + } + + loadCurrentUser(apiRoot: ApiRootResource): void { + this.setCurrentUserLoading(); + this.repository + .getCurrentUser(apiRoot) + .pipe( + catchError((errorResponse) => this.handleError(errorResponse.error)), + first(), + ) + .subscribe((currentUser: ApiError | UserProfileResource) => + this.setCurrentUser(this.createStateResourceForUpdate(currentUser)), + ); + } + + setCurrentUserLoading(): void { + this.currentUser.next(createEmptyStateResource<UserProfileResource>(true)); + } + + setCurrentUser(userProfile: StateResource<UserProfileResource>): void { + this.currentUser.next(userProfile); + } + + createIfNotExist(uri: ResourceUri): void { + if (isNil(this.userProfiles[uri])) + this.userProfiles[uri] = new BehaviorSubject(createEmptyStateResource<UserProfileResource>()); + } + + loadUserProfile(vorgang: Resource, linkRel: string): void { + this.repository + .getUserProfile(vorgang, linkRel) + .pipe( + catchError((errorResponse) => this.handleError(errorResponse.error)), + first(), + ) + .subscribe((response: ApiError | UserProfileResource) => + this.updateUserProfile(vorgang, linkRel, this.createStateResourceForUpdate(response)), + ); + } + + handleError(errorResponse: HttpErrorResponse): Observable<ApiError> { + return of(this.handleErrorByStatus(errorResponse)); + } + + handleErrorByStatus(error: HttpErrorResponse): ApiError { + if (isNotFound(error.status) || isServiceUnavailable(error.status)) { + return error.error; + } + if (this.isNetworkError(error.status)) { + return this.buildServiceUnavailableApiError(); + } + throwError({ error }); + } + + private isNetworkError(status: number): boolean { + return status == 0; + } + + private buildServiceUnavailableApiError(): ApiError { + return <ApiError>{ issues: [{ messageCode: MessageCode.SERVICE_UNAVAILABLE }] }; + } + + createStateResourceForUpdate( + response: ApiError | UserProfileResource, + ): StateResource<UserProfileResource> { + if (isApiError(response)) { + return createErrorStateResource(<ApiError>response); + } else { + return createStateResource(<UserProfileResource>response); + } + } + + updateUserProfile( + vorgang: Resource, + linkRel: string, + userProfile: StateResource<UserProfileResource>, + ): void { + //TOCHECK Potentielle Fehlerstelle: "cannot read 'next' of null/undefined" + this.userProfiles[this.getUserProfileUri(vorgang, linkRel)].next(userProfile); + } + + private getUserProfileUri(vorgang: Resource, linkRel: string): ResourceUri { + return getUrl(vorgang, linkRel); + } + + public getSearchedUserProfiles(): Observable<StateResource<UserProfileListResource>> { + return this.userProfileSearchList.asObservable(); + } + + public search(searchBy: string): Observable<StateResource<UserProfileListResource>> { + //TODO Im FormService unterscheiden, ob der Suchbegriff leer ist und direkt die "clearSearchList" Methode vom Service aufrufen. + if (isNil(searchBy)) { + this.clearSearchList(); + } else { + this.searchSubscription = this.vorgangService + .getVorgangWithEingang() + .pipe( + filter((stateResource) => stateResource.loaded), + switchMap((vorgangStateResource) => + this.repository.search(vorgangStateResource.resource, searchBy), + ), + ) + .subscribe((userProfileList) => { + this.userProfileSearchList.next(createStateResource(userProfileList)); + setTimeout(() => this.searchSubscription.unsubscribe(), 0); + }); + } + return this.userProfileSearchList.asObservable(); + } + + public clearSearchList() { + this.userProfileSearchList.next(createEmptyStateResource<UserProfileListResource>()); + } + + public getUserProfileSearchVisibility(): Observable<boolean> { + return this.facade.getUserProfileSearchVisibility(); + } + + public showUserProfileSearch(): void { + this.facade.showUserProfileSearch(); + } + + public hideUserProfileSearch(): void { + this.facade.hideUserProfileSearch(); + this.userProfileSearchList.next(createEmptyStateResource<UserProfileListResource>()); + } +} diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile.util.spec.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile.util.spec.ts index 6b2e849347d37b65b53a94c169eda937ac0c44f4..7584fb43cd88623fa696ec87eb63968fff1c232c 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile.util.spec.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile.util.spec.ts @@ -24,104 +24,135 @@ import { EMPTY_STRING } from '@alfa-client/tech-shared'; import { createUserProfileResource } from '../../../user-profile-shared/test/user-profile'; import { UserProfileResource } from './user-profile.model'; -import { existsName, getUserName, getUserNameInitials, NO_NAME_MESSAGE, UNKNOWN_USER } from './user-profile.util'; +import { + existsName, + getUserName, + getUserNameInitials, + NO_NAME_MESSAGE, + UNKNOWN_USER, +} from './user-profile.util'; describe('UserProfileUtil', () => { + describe('existsName', () => { + it.each([null, EMPTY_STRING])( + 'should return true if only firstName exists and lastName has value %s', + (value: null | string) => { + const exists: boolean = existsName({ ...createUserProfileResource(), lastName: value }); - describe('existsName', () => { + expect(exists).toBeTruthy(); + }, + ); - it.each([null, EMPTY_STRING])('should return true if only firstName exists and lastName has value %s', (value: null | string) => { - const exists: boolean = existsName({ ...createUserProfileResource(), lastName: value }); + it.each([null, EMPTY_STRING])( + 'should return true if only lastName exists and firstName has value %s', + (value: null | string) => { + const exists: boolean = existsName({ ...createUserProfileResource(), firstName: value }); - expect(exists).toBeTruthy(); - }) + expect(exists).toBeTruthy(); + }, + ); - it.each([null, EMPTY_STRING])('should return true if only lastName exists and firstName has value %s', (value: null | string) => { - const exists: boolean = existsName({ ...createUserProfileResource(), firstName: value }); + it.each([null, EMPTY_STRING])( + 'should return false if either firstName nor lastName exists', + (value: null | string) => { + const exists: boolean = existsName({ + ...createUserProfileResource(), + firstName: value, + lastName: value, + }); - expect(exists).toBeTruthy(); - }) + expect(exists).toBeFalsy(); + }, + ); + }); - it.each([null, EMPTY_STRING])('should return false if either firstName nor lastName exists', (value: null | string) => { - const exists: boolean = existsName({ ...createUserProfileResource(), firstName: value, lastName: value }); + describe('get user name', () => { + it('should return unknown user message on null', () => { + const userName: string = getUserName(null); - expect(exists).toBeFalsy(); - }) - }) + expect(userName).toBe(UNKNOWN_USER); + }); - describe('get user name', () => { + it('should return full name', () => { + const userProfile: UserProfileResource = createUserProfileResource(); - it('should return unknown user message on null', () => { - const userName: string = getUserName(null); + const userName: string = getUserName(userProfile); - expect(userName).toBe(UNKNOWN_USER); - }) + expect(userName).toBe(`${userProfile.firstName} ${userProfile.lastName}`); + }); - it('should return full name', () => { - const userProfile: UserProfileResource = createUserProfileResource(); + it('should return if only firstName exists', () => { + const userProfile: UserProfileResource = { ...createUserProfileResource(), lastName: null }; - const userName: string = getUserName(userProfile); + const userName: string = getUserName(userProfile); - expect(userName).toBe(`${userProfile.firstName} ${userProfile.lastName}`); - }) + expect(userName).toBe(userProfile.firstName); + }); - it('should return if only firstName exists', () => { - const userProfile: UserProfileResource = { ...createUserProfileResource(), lastName: null }; + it('should return only lastName exists', () => { + const userProfile: UserProfileResource = { ...createUserProfileResource(), firstName: null }; - const userName: string = getUserName(userProfile); + const userName: string = getUserName(userProfile); - expect(userName).toBe(userProfile.firstName); - }) + expect(userName).toBe(userProfile.lastName); + }); - it('should return only lastName exists', () => { - const userProfile: UserProfileResource = { ...createUserProfileResource(), firstName: null }; + it('should return no name message if either firstName nor lastName exists', () => { + const userProfile: UserProfileResource = { + ...createUserProfileResource(), + firstName: null, + lastName: null, + }; - const userName: string = getUserName(userProfile); + const userName: string = getUserName(userProfile); - expect(userName).toBe(userProfile.lastName); - }) + expect(userName).toBe(NO_NAME_MESSAGE); + }); + }); - it('should return no name message if either firstName nor lastName exists', () => { - const userProfile: UserProfileResource = { ...createUserProfileResource(), firstName: null, lastName: null }; + describe('get user name initials', () => { + it('should return for full name', () => { + const userProfile: UserProfileResource = createUserProfileResource(); - const userName: string = getUserName(userProfile); + const userName: string = getUserNameInitials(userProfile); - expect(userName).toBe(NO_NAME_MESSAGE); - }) - }) + expect(userName).toBe( + `${userProfile.firstName.substring(0, 1).toLocaleUpperCase()}${userProfile.lastName.substring(0, 1).toLocaleUpperCase()}`, + ); + }); - describe('get user name initials', () => { + it('should return if only firstName exists', () => { + const userProfile: UserProfileResource = { + ...createUserProfileResource(), + lastName: EMPTY_STRING, + }; - it('should return for full name', () => { - const userProfile: UserProfileResource = createUserProfileResource(); + const userName: string = getUserNameInitials(userProfile); - const userName: string = getUserNameInitials(userProfile); + expect(userName).toBe(`${userProfile.firstName.substring(0, 1).toLocaleUpperCase()}`); + }); - expect(userName).toBe(`${userProfile.firstName.substring(0, 1).toLocaleUpperCase()}${userProfile.lastName.substring(0, 1).toLocaleUpperCase()}`); - }) + it('should return only lastName exists', () => { + const userProfile: UserProfileResource = { + ...createUserProfileResource(), + firstName: EMPTY_STRING, + }; - it('should return if only firstName exists', () => { - const userProfile: UserProfileResource = { ...createUserProfileResource(), lastName: EMPTY_STRING }; + const userName: string = getUserNameInitials(userProfile); - const userName: string = getUserNameInitials(userProfile); + expect(userName).toBe(`${userProfile.lastName.substring(0, 1).toLocaleUpperCase()}`); + }); - expect(userName).toBe(`${userProfile.firstName.substring(0, 1).toLocaleUpperCase()}`); - }) + it('should return empty string if either firstName nor lastName exists', () => { + const userProfile: UserProfileResource = { + ...createUserProfileResource(), + firstName: EMPTY_STRING, + lastName: EMPTY_STRING, + }; - it('should return only lastName exists', () => { - const userProfile: UserProfileResource = { ...createUserProfileResource(), firstName: EMPTY_STRING }; + const userName: string = getUserNameInitials(userProfile); - const userName: string = getUserNameInitials(userProfile); - - expect(userName).toBe(`${userProfile.lastName.substring(0, 1).toLocaleUpperCase()}`); - }) - - it('should return empty string if either firstName nor lastName exists', () => { - const userProfile: UserProfileResource = { ...createUserProfileResource(), firstName: EMPTY_STRING, lastName: EMPTY_STRING }; - - const userName: string = getUserNameInitials(userProfile); - - expect(userName).toBe(EMPTY_STRING); - }) - }) -}) \ No newline at end of file + expect(userName).toBe(EMPTY_STRING); + }); + }); +}); diff --git a/alfa-client/libs/user-profile-shared/src/lib/user-profile.util.ts b/alfa-client/libs/user-profile-shared/src/lib/user-profile.util.ts index 0024b802df7a75d79c1e04e5dc68d0d718842e83..4c4ff89504423578637421c9172e6aac130c6c84 100644 --- a/alfa-client/libs/user-profile-shared/src/lib/user-profile.util.ts +++ b/alfa-client/libs/user-profile-shared/src/lib/user-profile.util.ts @@ -21,7 +21,13 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { EMPTY_STRING, getFirstLetter, getStringValue, isNotEmpty, isNotNull } from '@alfa-client/tech-shared'; +import { + EMPTY_STRING, + getFirstLetter, + getStringValue, + isNotEmpty, + isNotNull, +} from '@alfa-client/tech-shared'; import { isNil, isNull } from 'lodash-es'; import { UserProfileResource } from './user-profile.model'; @@ -29,24 +35,27 @@ export const NO_NAME_MESSAGE: string = 'Benutzer ohne hinterlegtem Namen'; export const UNKNOWN_USER: string = 'Unbekannter Benutzer'; export function existsName(userProfile: UserProfileResource): boolean { - return (isNotEmpty(userProfile.firstName) && isNotNull(userProfile.firstName)) || (isNotEmpty(userProfile.lastName) && isNotNull(userProfile.lastName)); + return ( + (isNotEmpty(userProfile.firstName) && isNotNull(userProfile.firstName)) || + (isNotEmpty(userProfile.lastName) && isNotNull(userProfile.lastName)) + ); } export function getUserName(userProfile: UserProfileResource): string { - if (isNil(userProfile)) { - return UNKNOWN_USER; - } - if (existsName(userProfile)) { - return `${getStringValue(userProfile.firstName)} ${getStringValue(userProfile.lastName)}`.trim(); - } - return NO_NAME_MESSAGE; + if (isNil(userProfile)) { + return UNKNOWN_USER; + } + if (existsName(userProfile)) { + return `${getStringValue(userProfile.firstName)} ${getStringValue(userProfile.lastName)}`.trim(); + } + return NO_NAME_MESSAGE; } export function getUserNameInitials(userProfile: UserProfileResource): string { - return `${getFirstLetterUpperCase(userProfile.firstName)}${getFirstLetterUpperCase(userProfile.lastName)}`; + return `${getFirstLetterUpperCase(userProfile.firstName)}${getFirstLetterUpperCase(userProfile.lastName)}`; } function getFirstLetterUpperCase(value: string) { - const firstLetter: string = getFirstLetter(value); - return isNull(firstLetter) ? EMPTY_STRING : firstLetter.toUpperCase(); + const firstLetter: string = getFirstLetter(value); + return isNull(firstLetter) ? EMPTY_STRING : firstLetter.toUpperCase(); } diff --git a/alfa-client/libs/user-profile-shared/src/test-setup.ts b/alfa-client/libs/user-profile-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/user-profile-shared/src/test-setup.ts +++ b/alfa-client/libs/user-profile-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/user-profile-shared/test/user-profile.ts b/alfa-client/libs/user-profile-shared/test/user-profile.ts index 0cf7ebf7ee5782791078c4adefdd12ff4a42d601..63293b5774526a0ba38506faae677e3469286043 100644 --- a/alfa-client/libs/user-profile-shared/test/user-profile.ts +++ b/alfa-client/libs/user-profile-shared/test/user-profile.ts @@ -25,26 +25,30 @@ import { faker } from '@faker-js/faker'; import { toResource } from 'libs/tech-shared/test/resource'; import { times } from 'lodash-es'; import { UserProfileListLinkRel } from '../src/lib/user-profile.linkrel'; -import { UserProfile, UserProfileListResource, UserProfileResource } from '../src/lib/user-profile.model'; +import { + UserProfile, + UserProfileListResource, + UserProfileResource, +} from '../src/lib/user-profile.model'; export function createUserProfile(): UserProfile { - return { - createdAt: faker.date.past(), - firstName: faker.name.findName(), - lastName: faker.name.findName() - } + return { + createdAt: faker.date.past(), + firstName: faker.name.findName(), + lastName: faker.name.findName(), + }; } export function createUserProfileResource(linkRel: string[] = []): UserProfileResource { - return toResource(createUserProfile(), linkRel); + return toResource(createUserProfile(), linkRel); } export function createUserProfileResources(linkRel: string[] = []): UserProfileResource[] { - return times(10, () => toResource(createUserProfileResource(), linkRel)); + return times(10, () => toResource(createUserProfileResource(), linkRel)); } export function createUserProfileListResource(linkRel: string[] = []): UserProfileListResource { - return toResource({}, linkRel, { - [UserProfileListLinkRel.USER_PROFILE_LIST]: createUserProfileResources() - }); -} \ No newline at end of file + return toResource({}, linkRel, { + [UserProfileListLinkRel.USER_PROFILE_LIST]: createUserProfileResources(), + }); +} diff --git a/alfa-client/libs/user-profile-shared/tsconfig.json b/alfa-client/libs/user-profile-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/user-profile-shared/tsconfig.json +++ b/alfa-client/libs/user-profile-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/user-profile-shared/tsconfig.lib.json b/alfa-client/libs/user-profile-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/user-profile-shared/tsconfig.lib.json +++ b/alfa-client/libs/user-profile-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/user-profile-shared/tsconfig.spec.json b/alfa-client/libs/user-profile-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/user-profile-shared/tsconfig.spec.json +++ b/alfa-client/libs/user-profile-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/user-profile/.eslintrc.json b/alfa-client/libs/user-profile/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/user-profile/.eslintrc.json +++ b/alfa-client/libs/user-profile/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/user-profile/jest.config.ts b/alfa-client/libs/user-profile/jest.config.ts index c3c1316c63f8d8691b3637f880d1588edc886410..ea9b64c30803fe1bb292f373356f191f46219909 100644 --- a/alfa-client/libs/user-profile/jest.config.ts +++ b/alfa-client/libs/user-profile/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'user-profile', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/user-profile', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'user-profile', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/user-profile', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/user-profile/project.json b/alfa-client/libs/user-profile/project.json index e111876b143330cdaa58f7095130001f61959f27..86ceaaef5d90c389c8861e0ca7e61a1422001765 100644 --- a/alfa-client/libs/user-profile/project.json +++ b/alfa-client/libs/user-profile/project.json @@ -1,29 +1,26 @@ { - "name": "user-profile", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/user-profile/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/user-profile"], - "options": { - "tsConfig": "libs/user-profile/tsconfig.spec.json", - "jestConfig": "libs/user-profile/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/user-profile/src/**/*.ts", - "libs/user-profile/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - } - }, - "tags": [] + "name": "user-profile", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/user-profile/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/user-profile"], + "options": { + "tsConfig": "libs/user-profile/tsconfig.spec.json", + "jestConfig": "libs/user-profile/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/user-profile/src/**/*.ts", "libs/user-profile/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + } + }, + "tags": [] } diff --git a/alfa-client/libs/user-profile/src/index.ts b/alfa-client/libs/user-profile/src/index.ts index 36902d9ba736ecdde7e150bc768c23e86ef454cd..f2549fbc63f76570c417e7f95e752a0a827ddf0e 100644 --- a/alfa-client/libs/user-profile/src/index.ts +++ b/alfa-client/libs/user-profile/src/index.ts @@ -32,4 +32,3 @@ export * from './lib/user-profile-in-postfach-mail-container/user-profile-in-pos export * from './lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component'; export * from './lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component'; export * from './lib/user-profile.module'; - diff --git a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.html b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.html index 7232792d75bf373417f6e9f78e836efc13f8c3a7..861494fe02c34d47e14021ad5060f2066c33d105 100644 --- a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.html @@ -24,9 +24,10 @@ --> <ozgcloud-icon-button-with-spinner - *ngIf="vorgang | hasLink: linkRel.ASSIGN" - svgIcon="account_outline" - toolTip="Bearbeiter zuordnen" - (clickEmitter)="showUserProfileSearch()" - data-test-id="assign-user-profile-icon-button"> + *ngIf="vorgang | hasLink: linkRel.ASSIGN" + svgIcon="account_outline" + toolTip="Bearbeiter zuordnen" + (clickEmitter)="showUserProfileSearch()" + data-test-id="assign-user-profile-icon-button" +> </ozgcloud-icon-button-with-spinner> diff --git a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.spec.ts index 6fa78ee71e1adff92e2d68d6d31027f9bdd4a286..1d73ead9ae4812f2da22e6c42b8e86bd3b0286ee 100644 --- a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.spec.ts @@ -32,66 +32,64 @@ import { MockComponent } from 'ng-mocks'; import { AssignUserProfileButtonContainerComponent } from './assign-user-profile-button-container.component'; describe('AssignUserProfileButtonContainerComponent', () => { - let component: AssignUserProfileButtonContainerComponent; - let fixture: ComponentFixture<AssignUserProfileButtonContainerComponent>; - - const assignUserProfileButton: string = '[data-test-id="assign-user-profile-icon-button"]'; - - const userProfileService = mock(UserProfileService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - AssignUserProfileButtonContainerComponent, - HasLinkPipe, - MockComponent(IconButtonWithSpinnerComponent) - ], - providers: [ - { - provide: UserProfileService, - useValue: userProfileService - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(AssignUserProfileButtonContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('button', () => { - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangHeaderLinkRel.ASSIGN]); - fixture.detectChanges(); - - const button = fixture.nativeElement.querySelector(assignUserProfileButton); - - expect(button).toBeInstanceOf(HTMLElement); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - fixture.detectChanges(); - - const button = fixture.nativeElement.querySelector(assignUserProfileButton); - - expect(button).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('showUserProfileSearch', () => { - - it('should call service', () => { - component.showUserProfileSearch(); - - expect(userProfileService.showUserProfileSearch).toHaveBeenCalled(); - }) - }) + let component: AssignUserProfileButtonContainerComponent; + let fixture: ComponentFixture<AssignUserProfileButtonContainerComponent>; + + const assignUserProfileButton: string = '[data-test-id="assign-user-profile-icon-button"]'; + + const userProfileService = mock(UserProfileService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + AssignUserProfileButtonContainerComponent, + HasLinkPipe, + MockComponent(IconButtonWithSpinnerComponent), + ], + providers: [ + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AssignUserProfileButtonContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('button', () => { + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([VorgangHeaderLinkRel.ASSIGN]); + fixture.detectChanges(); + + const button = fixture.nativeElement.querySelector(assignUserProfileButton); + + expect(button).toBeInstanceOf(HTMLElement); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + fixture.detectChanges(); + + const button = fixture.nativeElement.querySelector(assignUserProfileButton); + + expect(button).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('showUserProfileSearch', () => { + it('should call service', () => { + component.showUserProfileSearch(); + + expect(userProfileService.showUserProfileSearch).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.ts b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.ts index fe7303c09b941797c418a4dbf8af91a68c49bfba..fd3f3f272d026310ba074417701af0e6c64fb6b9 100644 --- a/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/assign-user-profile-button-container/assign-user-profile-button-container.component.ts @@ -26,20 +26,19 @@ import { UserProfileService } from '@alfa-client/user-profile-shared'; import { VorgangHeaderLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-assign-user-profile-button-container', - templateUrl: './assign-user-profile-button-container.component.html', - styleUrls: ['./assign-user-profile-button-container.component.scss'] + selector: 'alfa-assign-user-profile-button-container', + templateUrl: './assign-user-profile-button-container.component.html', + styleUrls: ['./assign-user-profile-button-container.component.scss'], }) export class AssignUserProfileButtonContainerComponent { + @Input() vorgang: VorgangWithEingangResource; - @Input() vorgang: VorgangWithEingangResource; + readonly linkRel = VorgangHeaderLinkRel; - readonly linkRel = VorgangHeaderLinkRel; + constructor(private userProfileService: UserProfileService) {} - constructor(private userProfileService: UserProfileService) { } - - public showUserProfileSearch(): void { - document.documentElement.scrollTop = 0; - this.userProfileService.showUserProfileSearch(); - } + public showUserProfileSearch(): void { + document.documentElement.scrollTop = 0; + this.userProfileService.showUserProfileSearch(); + } } diff --git a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.html b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.html index 47076613ad5c66cec8596b873382cd1c99480ee0..82ea1196252e9ff6298a0065354f36b1b70e2859 100644 --- a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.html @@ -23,6 +23,11 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-link-with-user-name-tooltip [routerLinkString]="routerLinkString" [tooltipTemplate]="tooltipTemplate" [userProfile]="userProfileStateResource$ | async" data-test-id="link-with-user-name-tooltip"> - <ng-content></ng-content> -</alfa-link-with-user-name-tooltip> \ No newline at end of file +<alfa-link-with-user-name-tooltip + [routerLinkString]="routerLinkString" + [tooltipTemplate]="tooltipTemplate" + [userProfile]="userProfileStateResource$ | async" + data-test-id="link-with-user-name-tooltip" +> + <ng-content></ng-content> +</alfa-link-with-user-name-tooltip> diff --git a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.spec.ts index edb5c1e56a9412173aad0679e1e7a0a5e5d7ef77..48b3976697f3b5e9a59d7c5ffcf775758a2b4cd7 100644 --- a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.spec.ts @@ -31,61 +31,61 @@ import { LinkWithUserNameTooltipContainerComponent } from './link-with-user-name import { LinkWithUserNameTooltipComponent } from './link-with-user-name-tooltip/link-with-user-name-tooltip.component'; describe('LinkWithUserNameTooltipContainerComponent', () => { + let component: LinkWithUserNameTooltipContainerComponent; + let fixture: ComponentFixture<LinkWithUserNameTooltipContainerComponent>; - let component: LinkWithUserNameTooltipContainerComponent; - let fixture: ComponentFixture<LinkWithUserNameTooltipContainerComponent>; + const userProfileService = mock(UserProfileService); - const userProfileService = mock(UserProfileService); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + LinkWithUserNameTooltipContainerComponent, + MockComponent(LinkWithUserNameTooltipComponent), + ], + providers: [ + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }).compileComponents(); + }); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - LinkWithUserNameTooltipContainerComponent, - MockComponent(LinkWithUserNameTooltipComponent) - ], - providers: [ - { - provide: UserProfileService, - useValue: userProfileService - } - ] - }).compileComponents(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(LinkWithUserNameTooltipContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(LinkWithUserNameTooltipContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + describe('ngOnInit', () => { + describe('user profile service', () => { + beforeEach(() => { + userProfileService.getAssignedUserProfile.mockClear(); + }); - describe('ngOnInit', () => { + it('should call if link is present', () => { + component.resource = createDummyResource([DummyLinkRel.DUMMY]); + component.linkRel = DummyLinkRel.DUMMY; - describe('user profile service', () => { + component.ngOnInit(); - beforeEach(() => { - userProfileService.getAssignedUserProfile.mockClear(); - }) + expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith( + component.resource, + DummyLinkRel.DUMMY, + ); + }); - it('should call if link is present', () => { - component.resource = createDummyResource([DummyLinkRel.DUMMY]); - component.linkRel = DummyLinkRel.DUMMY; + it('should not call if link is not present', () => { + component.resource = createDummyResource(); - component.ngOnInit(); + component.ngOnInit(); - expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith(component.resource, DummyLinkRel.DUMMY); - }) - - it('should not call if link is not present', () => { - component.resource = createDummyResource(); - - component.ngOnInit(); - - expect(userProfileService.getAssignedUserProfile).not.toHaveBeenCalled(); - }) - }) - }) + expect(userProfileService.getAssignedUserProfile).not.toHaveBeenCalled(); + }); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.ts b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.ts index 0ecd8e944af58852dfcaa4895d8b47d5c05ee6a4..17988b056319b39fcd51e397487efdb62a683cca 100644 --- a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip-container.component.ts @@ -28,24 +28,26 @@ import { hasLink, Resource } from '@ngxp/rest'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-link-with-user-name-tooltip-container', - templateUrl: './link-with-user-name-tooltip-container.component.html', - styleUrls: ['./link-with-user-name-tooltip-container.component.scss'], + selector: 'alfa-link-with-user-name-tooltip-container', + templateUrl: './link-with-user-name-tooltip-container.component.html', + styleUrls: ['./link-with-user-name-tooltip-container.component.scss'], }) export class LinkWithUserNameTooltipContainerComponent implements OnInit { + @Input() routerLinkString: string; + @Input() tooltipTemplate: string; + @Input() resource: Resource; + @Input() linkRel: string; - @Input() routerLinkString: string; - @Input() tooltipTemplate: string; - @Input() resource: Resource; - @Input() linkRel: string; + userProfileStateResource$: Observable<StateResource<UserProfileResource>>; - userProfileStateResource$: Observable<StateResource<UserProfileResource>>; + constructor(private userProfileService: UserProfileService) {} - constructor(private userProfileService: UserProfileService) { } - - ngOnInit(): void { - if (hasLink(this.resource, this.linkRel)) { - this.userProfileStateResource$ = this.userProfileService.getAssignedUserProfile(this.resource, this.linkRel); - } - } -} \ No newline at end of file + ngOnInit(): void { + if (hasLink(this.resource, this.linkRel)) { + this.userProfileStateResource$ = this.userProfileService.getAssignedUserProfile( + this.resource, + this.linkRel, + ); + } + } +} diff --git a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.html b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.html index 2afff21e94e4afafc9329900df01a6fe2a282804..fdff1a97bbb8081c30e6401ff6e39671395aefeb 100644 --- a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.html +++ b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.html @@ -23,6 +23,6 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<a routerLink="{{routerLinkString}}" [matTooltip]="tooltip" class="link"> - <ng-content></ng-content> -</a> \ No newline at end of file +<a routerLink="{{ routerLinkString }}" [matTooltip]="tooltip" class="link"> + <ng-content></ng-content> +</a> diff --git a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.scss b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.scss index 4c4b1a75e0472d90273c86ce374ad0e3a70e12b6..fd5fa658c13f50cce8072987654a31d6da4c5df3 100644 --- a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.scss +++ b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.scss @@ -22,15 +22,15 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .link { - display: inline-flex; - align-items: center; - text-decoration: none; - color: inherit; - outline: 0; - border-radius: 16px; - min-height: 32px; + display: inline-flex; + align-items: center; + text-decoration: none; + color: inherit; + outline: 0; + border-radius: 16px; + min-height: 32px; - &:focus-within { - background-color: rgba(#777, 0.16); - } -} \ No newline at end of file + &:focus-within { + background-color: rgba(#777, 0.16); + } +} diff --git a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.spec.ts b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.spec.ts index f6ff98e424106e453f0c7270d39f06d55b71899d..e4744d1ed7c6aa2da22ea3e94e2724c5171ec01e 100644 --- a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.spec.ts @@ -30,54 +30,49 @@ import { createUserProfileResource } from 'libs/user-profile-shared/test/user-pr import { LinkWithUserNameTooltipComponent } from './link-with-user-name-tooltip.component'; describe('LinkWithUserNameTooltipComponent', () => { - let component: LinkWithUserNameTooltipComponent; - let fixture: ComponentFixture<LinkWithUserNameTooltipComponent>; + let component: LinkWithUserNameTooltipComponent; + let fixture: ComponentFixture<LinkWithUserNameTooltipComponent>; - const userProfile: UserProfileResource = createUserProfileResource(); - const tooltipTemplate: string = 'TooltipTemplate with placeholder {firstName} {lastName}'; + const userProfile: UserProfileResource = createUserProfileResource(); + const tooltipTemplate: string = 'TooltipTemplate with placeholder {firstName} {lastName}'; - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - RouterTestingModule - ], - declarations: [ - LinkWithUserNameTooltipComponent, - MatTooltipDirective - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [RouterTestingModule], + declarations: [LinkWithUserNameTooltipComponent, MatTooltipDirective], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(LinkWithUserNameTooltipComponent); - component = fixture.componentInstance; - component.tooltipTemplate = tooltipTemplate; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(LinkWithUserNameTooltipComponent); + component = fixture.componentInstance; + component.tooltipTemplate = tooltipTemplate; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should build tooltip with empty userProfile', () => { + component.ngOnInit(); - it('should build tooltip with empty userProfile', () => { - component.ngOnInit(); + expect(component.tooltip).toEqual('TooltipTemplate with placeholder undefined undefined'); + }); + }); - expect(component.tooltip).toEqual('TooltipTemplate with placeholder undefined undefined'); - }) - }) + describe('tooltip', () => { + it('should be build with replaced placefolders', () => { + component.tooltipTemplate = tooltipTemplate; + component.userProfile = createStateResource(userProfile); + fixture.detectChanges(); - describe('tooltip', () => { + component.ngOnInit(); - it('should be build with replaced placefolders', () => { - component.tooltipTemplate = tooltipTemplate; - component.userProfile = createStateResource(userProfile); - fixture.detectChanges(); - - component.ngOnInit(); - - expect(component.tooltip).toBe(`TooltipTemplate with placeholder ${userProfile.firstName} ${userProfile.lastName}`); - }) - }) + expect(component.tooltip).toBe( + `TooltipTemplate with placeholder ${userProfile.firstName} ${userProfile.lastName}`, + ); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.ts b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.ts index 68cea0e04c83365b4117d05283be0c0bdaba582b..64846579fdbe5c4ee250fab3e8374cc030e4a5c0 100644 --- a/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.ts +++ b/alfa-client/libs/user-profile/src/lib/link-with-user-name-tooltip-container/link-with-user-name-tooltip/link-with-user-name-tooltip.component.ts @@ -22,31 +22,38 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Component, Input, OnInit } from '@angular/core'; -import { createEmptyStateResource, isNotNil, replacePlaceholders, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + isNotNil, + replacePlaceholders, + StateResource, +} from '@alfa-client/tech-shared'; import { UserProfileResource } from '@alfa-client/user-profile-shared'; @Component({ - selector: 'alfa-link-with-user-name-tooltip', - templateUrl: './link-with-user-name-tooltip.component.html', - styleUrls: ['./link-with-user-name-tooltip.component.scss'], + selector: 'alfa-link-with-user-name-tooltip', + templateUrl: './link-with-user-name-tooltip.component.html', + styleUrls: ['./link-with-user-name-tooltip.component.scss'], }) export class LinkWithUserNameTooltipComponent implements OnInit { + @Input() routerLinkString: string; + @Input() tooltipTemplate: string; + @Input() userProfile: StateResource<UserProfileResource> = createEmptyStateResource(); - @Input() routerLinkString: string; - @Input() tooltipTemplate: string; - @Input() userProfile: StateResource<UserProfileResource> = createEmptyStateResource(); + tooltip: string; - tooltip: string; + ngOnInit(): void { + this.tooltip = replacePlaceholders(this.tooltipTemplate, this.getPlaceholderValues()); + } - ngOnInit(): void { - this.tooltip = replacePlaceholders(this.tooltipTemplate, this.getPlaceholderValues()); - } + private getPlaceholderValues() { + if (isNotNil(this.userProfile.resource)) { + return { + firstName: this.userProfile.resource.firstName, + lastName: this.userProfile.resource.lastName, + }; + } - private getPlaceholderValues() { - if (isNotNil(this.userProfile.resource)) { - return { firstName: this.userProfile.resource.firstName, lastName: this.userProfile.resource.lastName }; - } - - return { firstName: undefined, lastName: undefined }; - } -} \ No newline at end of file + return { firstName: undefined, lastName: undefined }; + } +} diff --git a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.html b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.html index da6eb76d999eb712d94420f05d4b085e02c00625..c379f044c80d41965d9d0cd11a231726789bc0bb 100644 --- a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.html @@ -23,5 +23,10 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-text-with-user-name-tooltip [text]="text"[tooltipTemplate]="tooltipTemplate" [userProfile]="userProfileStateResource$ | async" data-test-id="text-with-user-name-tooltip"> -</alfa-text-with-user-name-tooltip> \ No newline at end of file +<alfa-text-with-user-name-tooltip + [text]="text" + [tooltipTemplate]="tooltipTemplate" + [userProfile]="userProfileStateResource$ | async" + data-test-id="text-with-user-name-tooltip" +> +</alfa-text-with-user-name-tooltip> diff --git a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.spec.ts index 2f3ef7bae86d624ca3347533dff24344d4cdf3ad..8474f647208c3f6b0974401af6274060e7fd61ff 100644 --- a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.spec.ts @@ -31,62 +31,61 @@ import { TextWithUserNameTooltipContainerComponent } from './text-with-user-name import { TextWithUserNameTooltipComponent } from './text-with-user-name-tooltip/text-with-user-name-tooltip.component'; describe('TextWithUserNameTooltipContainerComponent', () => { - let component: TextWithUserNameTooltipContainerComponent; - let fixture: ComponentFixture<TextWithUserNameTooltipContainerComponent>; + let component: TextWithUserNameTooltipContainerComponent; + let fixture: ComponentFixture<TextWithUserNameTooltipContainerComponent>; - const userProfileService = mock(UserProfileService); + const userProfileService = mock(UserProfileService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - TextWithUserNameTooltipContainerComponent, - MockComponent(TextWithUserNameTooltipComponent) - ], - providers: [ - { - provide: UserProfileService, - useValue: userProfileService - } - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + TextWithUserNameTooltipContainerComponent, + MockComponent(TextWithUserNameTooltipComponent), + ], + providers: [ + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent( - TextWithUserNameTooltipContainerComponent - ); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(TextWithUserNameTooltipContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + describe('user profile service', () => { + beforeEach(() => { + userProfileService.getAssignedUserProfile.mockClear(); + }); - describe('user profile service', () => { + it('should call if link is present', () => { + component.resource = createDummyResource([DummyLinkRel.DUMMY]); + component.linkRel = DummyLinkRel.DUMMY; - beforeEach(() => { - userProfileService.getAssignedUserProfile.mockClear(); - }) + component.ngOnInit(); - it('should call if link is present', () => { - component.resource = createDummyResource([DummyLinkRel.DUMMY]); - component.linkRel = DummyLinkRel.DUMMY; + expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith( + component.resource, + DummyLinkRel.DUMMY, + ); + }); - component.ngOnInit(); + it('should not call if link is not present', () => { + component.resource = createDummyResource(); - expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith(component.resource, DummyLinkRel.DUMMY); - }) + component.ngOnInit(); - it('should not call if link is not present', () => { - component.resource = createDummyResource(); - - component.ngOnInit(); - - expect(userProfileService.getAssignedUserProfile).not.toHaveBeenCalled(); - }) - }) - }) + expect(userProfileService.getAssignedUserProfile).not.toHaveBeenCalled(); + }); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.ts b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.ts index 9259ca20b2f46f5e3de7c8c1289ece252be03b1a..510af74c780219744ace5a2c02489dac81e9c801 100644 --- a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip-container.component.ts @@ -28,24 +28,26 @@ import { hasLink, Resource } from '@ngxp/rest'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-text-with-user-name-tooltip-container', - templateUrl: './text-with-user-name-tooltip-container.component.html', - styleUrls: ['./text-with-user-name-tooltip-container.component.scss'], + selector: 'alfa-text-with-user-name-tooltip-container', + templateUrl: './text-with-user-name-tooltip-container.component.html', + styleUrls: ['./text-with-user-name-tooltip-container.component.scss'], }) export class TextWithUserNameTooltipContainerComponent implements OnInit { + @Input() tooltipTemplate: string; + @Input() text: string; + @Input() resource: Resource; + @Input() linkRel: string; - @Input() tooltipTemplate: string; - @Input() text: string; - @Input() resource: Resource; - @Input() linkRel: string; + userProfileStateResource$: Observable<StateResource<UserProfileResource>>; - userProfileStateResource$: Observable<StateResource<UserProfileResource>>; + constructor(private userProfileService: UserProfileService) {} - constructor(private userProfileService: UserProfileService) { } - - ngOnInit(): void { - if (hasLink(this.resource, this.linkRel)) { - this.userProfileStateResource$ = this.userProfileService.getAssignedUserProfile(this.resource, this.linkRel); - } - } -} \ No newline at end of file + ngOnInit(): void { + if (hasLink(this.resource, this.linkRel)) { + this.userProfileStateResource$ = this.userProfileService.getAssignedUserProfile( + this.resource, + this.linkRel, + ); + } + } +} diff --git a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.html b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.html index 0e8531afcd6e1692efb7d1201d85a6bf75adb197..6bed7946b23188ebcc9e1efb536e5d59a103309a 100644 --- a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.html +++ b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.html @@ -23,4 +23,4 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<p [matTooltip]="tooltip">{{ text }}</p> \ No newline at end of file +<p [matTooltip]="tooltip">{{ text }}</p> diff --git a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.spec.ts b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.spec.ts index 8f8fb4afa0ed076fd1485f8ae1a621f32af82eb0..f3b28df09eddef757fc9fcc23590f6818d1fafce 100644 --- a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.spec.ts @@ -29,51 +29,48 @@ import { createUserProfileResource } from 'libs/user-profile-shared/test/user-pr import { TextWithUserNameTooltipComponent } from './text-with-user-name-tooltip.component'; describe('TextWithUserNameTooltipComponent', () => { - let component: TextWithUserNameTooltipComponent; - let fixture: ComponentFixture<TextWithUserNameTooltipComponent>; + let component: TextWithUserNameTooltipComponent; + let fixture: ComponentFixture<TextWithUserNameTooltipComponent>; - const userProfile: UserProfileResource = createUserProfileResource(); - const tooltipTemplate: string = 'TooltipTemplate with placeholder {firstName} {lastName}'; + const userProfile: UserProfileResource = createUserProfileResource(); + const tooltipTemplate: string = 'TooltipTemplate with placeholder {firstName} {lastName}'; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - TextWithUserNameTooltipComponent, - MatTooltipDirective, - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [TextWithUserNameTooltipComponent, MatTooltipDirective], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(TextWithUserNameTooltipComponent); - component = fixture.componentInstance; - component.tooltipTemplate = tooltipTemplate; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(TextWithUserNameTooltipComponent); + component = fixture.componentInstance; + component.tooltipTemplate = tooltipTemplate; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should build tooltip with empty userProfile', () => { + component.ngOnInit(); - it('should build tooltip with empty userProfile', () => { - component.ngOnInit(); + expect(component.tooltip).toEqual('TooltipTemplate with placeholder undefined undefined'); + }); + }); - expect(component.tooltip).toEqual('TooltipTemplate with placeholder undefined undefined'); - }) - }) + describe('tooltip', () => { + it('should be build with replaced placefolders', () => { + component.tooltipTemplate = tooltipTemplate; + component.userProfile = createStateResource(userProfile); + fixture.detectChanges(); - describe('tooltip', () => { + component.ngOnInit(); - it('should be build with replaced placefolders', () => { - component.tooltipTemplate = tooltipTemplate; - component.userProfile = createStateResource(userProfile); - fixture.detectChanges(); - - component.ngOnInit(); - - expect(component.tooltip).toBe(`TooltipTemplate with placeholder ${userProfile.firstName} ${userProfile.lastName}`); - }) - }) + expect(component.tooltip).toBe( + `TooltipTemplate with placeholder ${userProfile.firstName} ${userProfile.lastName}`, + ); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.ts b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.ts index 875765dfa1f019847d926242305d43c515796ebf..ccf4dbd427eae4adc5cf799ea2a79918f04c1c6c 100644 --- a/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.ts +++ b/alfa-client/libs/user-profile/src/lib/text-with-user-name-tooltip-container/text-with-user-name-tooltip/text-with-user-name-tooltip.component.ts @@ -22,31 +22,38 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Component, Input, OnInit } from '@angular/core'; -import { createEmptyStateResource, isNotNil, replacePlaceholders, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + isNotNil, + replacePlaceholders, + StateResource, +} from '@alfa-client/tech-shared'; import { UserProfileResource } from '@alfa-client/user-profile-shared'; @Component({ - selector: 'alfa-text-with-user-name-tooltip', - templateUrl: './text-with-user-name-tooltip.component.html', - styleUrls: ['./text-with-user-name-tooltip.component.scss'], + selector: 'alfa-text-with-user-name-tooltip', + templateUrl: './text-with-user-name-tooltip.component.html', + styleUrls: ['./text-with-user-name-tooltip.component.scss'], }) export class TextWithUserNameTooltipComponent implements OnInit { + @Input() tooltipTemplate: string; + @Input() text: string; + @Input() userProfile: StateResource<UserProfileResource> = createEmptyStateResource(); - @Input() tooltipTemplate: string; - @Input() text: string; - @Input() userProfile: StateResource<UserProfileResource> = createEmptyStateResource(); + tooltip: string; - tooltip: string; + ngOnInit(): void { + this.tooltip = replacePlaceholders(this.tooltipTemplate, this.getPlaceholderValues()); + } - ngOnInit(): void { - this.tooltip = replacePlaceholders(this.tooltipTemplate, this.getPlaceholderValues()); - } + private getPlaceholderValues() { + if (isNotNil(this.userProfile.resource)) { + return { + firstName: this.userProfile.resource.firstName, + lastName: this.userProfile.resource.lastName, + }; + } - private getPlaceholderValues() { - if (isNotNil(this.userProfile.resource)) { - return { firstName: this.userProfile.resource.firstName, lastName: this.userProfile.resource.lastName }; - } - - return { firstName: undefined, lastName: undefined }; - } -} \ No newline at end of file + return { firstName: undefined, lastName: undefined }; + } +} diff --git a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.html b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.html index 6c7d7ab539b6a95fef6d32cb0f9b8c0e2c5d5057..7c3ff6344729ceebe6372394587f6d6e09370a5d 100644 --- a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.html @@ -24,18 +24,32 @@ --> <ozgcloud-spinner [stateResource]="userProfileStateResource" diameter="30" padding="3"> - <div [matTooltipDisabled]="disableTooltip" data-test-class="user-profile-icon" - [class.initials]="!!userProfileStateResource.resource || userProfileStateResource.error" - class="user-profile" [matTooltip]="tooltip"> - - <ng-container *ngIf="userProfileStateResource.resource; else noUser"> - <span data-test-class="user-profile-assigned">{{ initials }}</span> - </ng-container> - <ng-template #noUser> - <mat-icon *ngIf="!userProfileStateResource.error" data-test-class="user-profile-unassigned">account_circle_outline</mat-icon> - <span *ngIf="errorMessageCode === messageCode.RESOURCE_NOT_FOUND" data-test-class="user-profile-user-not-found">!</span> - <mat-icon *ngIf="errorMessageCode === messageCode.SERVICE_UNAVAILABLE" class="unavailable" data-test-class="user-profile-service-unavailable">error_outline</mat-icon> - </ng-template> - <div class="picture"></div> - </div> + <div + [matTooltipDisabled]="disableTooltip" + data-test-class="user-profile-icon" + [class.initials]="!!userProfileStateResource.resource || userProfileStateResource.error" + class="user-profile" + [matTooltip]="tooltip" + > + <ng-container *ngIf="userProfileStateResource.resource; else noUser"> + <span data-test-class="user-profile-assigned">{{ initials }}</span> + </ng-container> + <ng-template #noUser> + <mat-icon *ngIf="!userProfileStateResource.error" data-test-class="user-profile-unassigned" + >account_circle_outline</mat-icon + > + <span + *ngIf="errorMessageCode === messageCode.RESOURCE_NOT_FOUND" + data-test-class="user-profile-user-not-found" + >!</span + > + <mat-icon + *ngIf="errorMessageCode === messageCode.SERVICE_UNAVAILABLE" + class="unavailable" + data-test-class="user-profile-service-unavailable" + >error_outline</mat-icon + > + </ng-template> + <div class="picture"></div> + </div> </ozgcloud-spinner> diff --git a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.scss b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.scss index ca9d41ae4bf0898241098cfcf8d57b8d53f9724c..dda9a87b9b1c6fb2dd5bca49aba7183be674d65c 100644 --- a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.scss +++ b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.scss @@ -26,36 +26,36 @@ @import 'variables'; .user-profile { - width: 36px; - height: 36px; - border-radius: 50%; - position: relative; - overflow: hidden; + width: 36px; + height: 36px; + border-radius: 50%; + position: relative; + overflow: hidden; - &.initials { - background-color: #3e3e3e; - color: #fff; - display: flex; - justify-content: center; - align-items: center; - font-size: 18px; - } + &.initials { + background-color: #3e3e3e; + color: #fff; + display: flex; + justify-content: center; + align-items: center; + font-size: 18px; + } } mat-icon { - color: $grey; - position: absolute; - left: 50%; - top: 50%; - transform: scale(1.78) translate(-50%, -50%); - transform-origin: left top; + color: $grey; + position: absolute; + left: 50%; + top: 50%; + transform: scale(1.78) translate(-50%, -50%); + transform-origin: left top; } span { - line-height: 1; + line-height: 1; } mat-icon.unavailable { - background-color: #fff; - color: mat.get-color-from-palette($warnPalette); + background-color: #fff; + color: mat.get-color-from-palette($warnPalette); } diff --git a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.spec.ts index 48aea63172cc4c38b31258d167066c8e41196c6f..af8f79ad791e7e28eddddcece342916ae14ad4ee 100644 --- a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.spec.ts @@ -24,165 +24,192 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatIcon } from '@angular/material/icon'; import { faker } from '@faker-js/faker'; -import { ApiError, EMPTY_STRING, MessageCode, createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + ApiError, + EMPTY_STRING, + MessageCode, + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { getElementFromFixture } from '@alfa-client/test-utils'; import { SpinnerComponent } from '@alfa-client/ui'; -import { NO_NAME_MESSAGE, UserProfileResource, userProfileMessage } from '@alfa-client/user-profile-shared'; +import { + NO_NAME_MESSAGE, + UserProfileResource, + userProfileMessage, +} from '@alfa-client/user-profile-shared'; import { getDataTestClassOf } from 'libs/tech-shared/test/data-test'; -import { MatTooltipDirective, MatTooltipDisabledDirective } from 'libs/ui/src/lib/ui/mattooltip/mattooltip.directive'; +import { + MatTooltipDirective, + MatTooltipDisabledDirective, +} from 'libs/ui/src/lib/ui/mattooltip/mattooltip.directive'; import { createUserProfileResource } from 'libs/user-profile-shared/test/user-profile'; import { MockComponent } from 'ng-mocks'; import { createApiError, createIssue } from '../../../../tech-shared/test/error'; import { UserIconComponent } from './user-icon.component'; describe('UserIconComponent', () => { - let component: UserIconComponent; - let fixture: ComponentFixture<UserIconComponent>; + let component: UserIconComponent; + let fixture: ComponentFixture<UserIconComponent>; - const profileAssignedIcon: string = getDataTestClassOf('user-profile-assigned'); - const profileUnassigned: string = getDataTestClassOf('user-profile-unassigned'); - const profileUserNotFound: string = getDataTestClassOf('user-profile-user-not-found'); - const profileServiceUnavailable: string = getDataTestClassOf('user-profile-service-unavailable'); + const profileAssignedIcon: string = getDataTestClassOf('user-profile-assigned'); + const profileUnassigned: string = getDataTestClassOf('user-profile-unassigned'); + const profileUserNotFound: string = getDataTestClassOf('user-profile-user-not-found'); + const profileServiceUnavailable: string = getDataTestClassOf('user-profile-service-unavailable'); - const userProfile: UserProfileResource = createUserProfileResource(); + const userProfile: UserProfileResource = createUserProfileResource(); - beforeEach(async () => { - TestBed.configureTestingModule({ - declarations: [ - UserIconComponent, - MatIcon, - MatTooltipDirective, - MatTooltipDisabledDirective, - MockComponent(SpinnerComponent) - ] - }) - }) + beforeEach(async () => { + TestBed.configureTestingModule({ + declarations: [ + UserIconComponent, + MatIcon, + MatTooltipDirective, + MatTooltipDisabledDirective, + MockComponent(SpinnerComponent), + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(UserIconComponent); - component = fixture.componentInstance; - component.userProfileStateResource = createStateResource(userProfile); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserIconComponent); + component = fixture.componentInstance; + component.userProfileStateResource = createStateResource(userProfile); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('on icon place', () => { + describe('on icon place', () => { + it('should show icon unassigned', () => { + component.userProfileStateResource = createEmptyStateResource(); - it('should show icon unassigned', () => { - component.userProfileStateResource = createEmptyStateResource(); + fixture.detectChanges(); + const element = getElementFromFixture(fixture, profileUnassigned); - fixture.detectChanges(); - const element = getElementFromFixture(fixture, profileUnassigned); + expect(element).toBeInstanceOf(HTMLElement); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) + it('should show icon assigned', () => { + component.userProfileStateResource = createStateResource(userProfile); - it('should show icon assigned', () => { - component.userProfileStateResource = createStateResource(userProfile); + fixture.detectChanges(); + const element = getElementFromFixture(fixture, profileAssignedIcon); - fixture.detectChanges(); - const element = getElementFromFixture(fixture, profileAssignedIcon); + expect(element).toBeInstanceOf(HTMLElement); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) + it('should show user not found icon', () => { + component.userProfileStateResource = createErrorStateResource( + createApiErrorWithMessageCode(MessageCode.RESOURCE_NOT_FOUND), + ); - it('should show user not found icon', () => { - component.userProfileStateResource = createErrorStateResource(createApiErrorWithMessageCode(MessageCode.RESOURCE_NOT_FOUND)); + fixture.detectChanges(); + const element = getElementFromFixture(fixture, profileUserNotFound); - fixture.detectChanges(); - const element = getElementFromFixture(fixture, profileUserNotFound); + expect(element).toBeInstanceOf(HTMLElement); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) + it('should show service unavailable icon', () => { + component.userProfileStateResource = createErrorStateResource( + createApiErrorWithMessageCode(MessageCode.SERVICE_UNAVAILABLE), + ); - it('should show service unavailable icon', () => { - component.userProfileStateResource = createErrorStateResource(createApiErrorWithMessageCode(MessageCode.SERVICE_UNAVAILABLE)); + fixture.detectChanges(); + const element = getElementFromFixture(fixture, profileServiceUnavailable); - fixture.detectChanges(); - const element = getElementFromFixture(fixture, profileServiceUnavailable); + expect(element).toBeInstanceOf(HTMLElement); + }); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) - }) + describe('tooltip', () => { + it('should return user name', () => { + component.userProfileStateResource = createStateResource(userProfile); - describe('tooltip', () => { + const tooltip = component.getTooltip(); - it('should return user name', () => { - component.userProfileStateResource = createStateResource(userProfile); + expect(tooltip).toEqual(userProfile.firstName + ' ' + userProfile.lastName); + }); - const tooltip = component.getTooltip(); + it('should return no user assigned', () => { + component.userProfileStateResource = createEmptyStateResource(); - expect(tooltip).toEqual(userProfile.firstName + ' ' + userProfile.lastName); - }) + const tooltip = component.getTooltip(); - it('should return no user assigned', () => { - component.userProfileStateResource = createEmptyStateResource(); + expect(tooltip).toEqual(userProfileMessage.UNASSIGNED); + }); - const tooltip = component.getTooltip(); + it('should return apiError as stateResource', () => { + component.userProfileStateResource = createErrorStateResource(createApiError()); + component.getErrorTooltip = jest.fn(); - expect(tooltip).toEqual(userProfileMessage.UNASSIGNED); - }) + component.getTooltip(); - it('should return apiError as stateResource', () => { - component.userProfileStateResource = createErrorStateResource(createApiError()); - component.getErrorTooltip = jest.fn(); + expect(component.getErrorTooltip).toHaveBeenCalled(); + }); - component.getTooltip(); + it('should return empty string on missing name', () => { + component.userProfileStateResource = createStateResource({ + ...userProfile, + firstName: EMPTY_STRING, + lastName: EMPTY_STRING, + }); - expect(component.getErrorTooltip).toHaveBeenCalled(); - }) + const tooltip = component.getTooltip(); - it('should return empty string on missing name', () => { - component.userProfileStateResource = createStateResource({ ...userProfile, firstName: EMPTY_STRING, lastName: EMPTY_STRING }); + expect(tooltip).toEqual(NO_NAME_MESSAGE); + }); + }); - const tooltip = component.getTooltip(); + describe('error tooltip', () => { + it('should return user not found', () => { + component.userProfileStateResource = createErrorStateResource( + createApiErrorWithMessageCode(MessageCode.RESOURCE_NOT_FOUND), + ); - expect(tooltip).toEqual(NO_NAME_MESSAGE); - }) - }); + const tooltip = component.getErrorTooltip(); - describe('error tooltip', () => { + expect(tooltip).toEqual(userProfileMessage[MessageCode.RESOURCE_NOT_FOUND]); + }); - it('should return user not found', () => { - component.userProfileStateResource = createErrorStateResource(createApiErrorWithMessageCode(MessageCode.RESOURCE_NOT_FOUND)); + it('should return backend service unavailable', () => { + component.userProfileStateResource = createErrorStateResource( + createApiErrorWithMessageCode(MessageCode.SERVICE_UNAVAILABLE), + ); - const tooltip = component.getErrorTooltip(); + const tooltip = component.getErrorTooltip(); - expect(tooltip).toEqual(userProfileMessage[MessageCode.RESOURCE_NOT_FOUND]); - }) + expect(tooltip).toEqual(userProfileMessage[MessageCode.SERVICE_UNAVAILABLE]); + }); - it('should return backend service unavailable', () => { - component.userProfileStateResource = createErrorStateResource(createApiErrorWithMessageCode(MessageCode.SERVICE_UNAVAILABLE)); + describe('on unexpected error', () => { + it('should return empty string on non existing messageCode issue', () => { + component.userProfileStateResource = createErrorStateResource( + createApiErrorWithMessageCode(faker.random.word()), + ); - const tooltip = component.getErrorTooltip(); + const tooltip = component.getErrorTooltip(); - expect(tooltip).toEqual(userProfileMessage[MessageCode.SERVICE_UNAVAILABLE]); - }) + expect(tooltip).toEqual(userProfileMessage.UNKNOW_ERROR); + }); - describe('on unexpected error', () => { + it('should return empty string on null issue', () => { + component.userProfileStateResource = createErrorStateResource({ + ...createApiError(), + issues: [null], + }); - it('should return empty string on non existing messageCode issue', () => { - component.userProfileStateResource = createErrorStateResource(createApiErrorWithMessageCode(faker.random.word())); + const tooltip = component.getErrorTooltip(); - const tooltip = component.getErrorTooltip(); + expect(tooltip).toEqual(userProfileMessage.UNKNOW_ERROR); + }); + }); + }); - expect(tooltip).toEqual(userProfileMessage.UNKNOW_ERROR); - }) - - it('should return empty string on null issue', () => { - component.userProfileStateResource = createErrorStateResource({ ...createApiError(), issues: [null] }); - - const tooltip = component.getErrorTooltip(); - - expect(tooltip).toEqual(userProfileMessage.UNKNOW_ERROR); - }) - }) - }) - - function createApiErrorWithMessageCode(messageCode: string): ApiError { - return { ...createApiError(), issues: [{ ...createIssue(), messageCode }] }; - } + function createApiErrorWithMessageCode(messageCode: string): ApiError { + return { ...createApiError(), issues: [{ ...createIssue(), messageCode }] }; + } }); diff --git a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.ts b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.ts index 5d9a396735d488d8d7aecf713b95b074df8bb583..589e5dcd9b4e7cdd81a702dc16d1544a4e0fa018 100644 --- a/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-icon/user-icon.component.ts @@ -22,54 +22,64 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Component, Input, SimpleChanges } from '@angular/core'; -import { createEmptyStateResource, hasError, MessageCode, StateResource } from '@alfa-client/tech-shared'; -import { getUserName, getUserNameInitials, userProfileMessage, UserProfileResource } from '@alfa-client/user-profile-shared'; +import { + createEmptyStateResource, + hasError, + MessageCode, + StateResource, +} from '@alfa-client/tech-shared'; +import { + getUserName, + getUserNameInitials, + userProfileMessage, + UserProfileResource, +} from '@alfa-client/user-profile-shared'; import { isUndefined } from 'lodash-es'; @Component({ - selector: 'alfa-user-icon', - templateUrl: './user-icon.component.html', - styleUrls: ['./user-icon.component.scss'] + selector: 'alfa-user-icon', + templateUrl: './user-icon.component.html', + styleUrls: ['./user-icon.component.scss'], }) export class UserIconComponent { + @Input() userProfileStateResource: StateResource<UserProfileResource> = + createEmptyStateResource<UserProfileResource>(); + @Input() disableTooltip: boolean = false; - @Input() userProfileStateResource: StateResource<UserProfileResource> = createEmptyStateResource<UserProfileResource>(); - @Input() disableTooltip: boolean = false; + readonly messageCode = MessageCode; - readonly messageCode = MessageCode; + tooltip: string; - tooltip: string; + ngOnChanges(changes: SimpleChanges): void { + if (changes.userProfileStateResource) { + this.tooltip = this.getTooltip(); + } + } - ngOnChanges(changes: SimpleChanges): void { - if (changes.userProfileStateResource) { - this.tooltip = this.getTooltip(); - } - } + getTooltip(): string { + if (this.userProfileStateResource.resource) { + return this.getUserTooltip(); + } + if (hasError(this.userProfileStateResource)) { + return this.getErrorTooltip(); + } + return userProfileMessage.UNASSIGNED; + } - getTooltip(): string { - if (this.userProfileStateResource.resource) { - return this.getUserTooltip(); - } - if (hasError(this.userProfileStateResource)) { - return this.getErrorTooltip(); - } - return userProfileMessage.UNASSIGNED; - } + getUserTooltip(): string { + return getUserName(this.userProfileStateResource.resource); + } - getUserTooltip(): string { - return getUserName(this.userProfileStateResource.resource); - } + getErrorTooltip(): string { + const message: string = userProfileMessage[this.errorMessageCode]; + return isUndefined(message) ? userProfileMessage.UNKNOW_ERROR : message; + } - getErrorTooltip(): string { - const message: string = userProfileMessage[this.errorMessageCode]; - return isUndefined(message) ? userProfileMessage.UNKNOW_ERROR : message; - } + get errorMessageCode(): string { + return this.userProfileStateResource.error?.issues[0]?.messageCode; + } - get errorMessageCode(): string { - return this.userProfileStateResource.error?.issues[0]?.messageCode; - } - - get initials(): string { - return getUserNameInitials(this.userProfileStateResource.resource); - } + get initials(): string { + return getUserNameInitials(this.userProfileStateResource.resource); + } } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.html index 819c440b52cedb34ef209dea1e6c393bdb66fe2a..7ffffe47fb7824d6484f4c875e3fbe5c9cbc35b9 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.html @@ -24,6 +24,7 @@ --> <alfa-user-profile-in-header - [currentUserResource]="currentUserResource$ | async" - (logoutEmitter)="logout()"> + [currentUserResource]="currentUserResource$ | async" + (logoutEmitter)="logout()" +> </alfa-user-profile-in-header> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.spec.ts index 98cceb9c99b75ec12ccfb82c341a157cbe578155..322323565a370674199a4e20db4e5d4f37b1b22a 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.spec.ts @@ -30,54 +30,52 @@ import { UserProfileInHeaderContainerComponent } from './user-profile-in-header- import { UserProfileInHeaderComponent } from './user-profile-in-header/user-profile-in-header.component'; describe('UserProfileInHeaderContainerComponent', () => { - let component: UserProfileInHeaderContainerComponent; - let fixture: ComponentFixture<UserProfileInHeaderContainerComponent>; + let component: UserProfileInHeaderContainerComponent; + let fixture: ComponentFixture<UserProfileInHeaderContainerComponent>; - const authService: Mock<AuthService> = mock(AuthService); - const userProfileService: Mock<UserProfileService> = mock(UserProfileService); + const authService: Mock<AuthService> = mock(AuthService); + const userProfileService: Mock<UserProfileService> = mock(UserProfileService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserProfileInHeaderContainerComponent, - MockComponent(UserProfileInHeaderComponent) - ], - providers: [ - { - provide: AuthService, - useValue: authService - }, - { - provide: UserProfileService, - useValue: userProfileService - } - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserProfileInHeaderContainerComponent, + MockComponent(UserProfileInHeaderComponent), + ], + providers: [ + { + provide: AuthService, + useValue: authService, + }, + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }).compileComponents(); - fixture = TestBed.createComponent(UserProfileInHeaderContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(UserProfileInHeaderContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should call service', () => { + component.ngOnInit(); - it('should call service', () => { - component.ngOnInit(); + expect(userProfileService.getCurrentUser).toHaveBeenCalled(); + }); + }); - expect(userProfileService.getCurrentUser).toHaveBeenCalled(); - }) - }) + describe('logout', () => { + it('should call authService', () => { + component.logout(); - describe('logout', () => { - - it('should call authService', () => { - component.logout(); - - expect(authService.logout).toHaveBeenCalled(); - }) - }) + expect(authService.logout).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.ts index 3d6d6a2f0e03ab0fee360471c24a19de626c6c6f..4f96fed47772c87b8e1dfe0a6e2d482f591dd76f 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header-container.component.ts @@ -28,21 +28,23 @@ import { UserProfileResource, UserProfileService } from '@alfa-client/user-profi import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-user-profile-in-header-container', - templateUrl: './user-profile-in-header-container.component.html', - styleUrls: ['./user-profile-in-header-container.component.scss'], + selector: 'alfa-user-profile-in-header-container', + templateUrl: './user-profile-in-header-container.component.html', + styleUrls: ['./user-profile-in-header-container.component.scss'], }) export class UserProfileInHeaderContainerComponent implements OnInit { + currentUserResource$: Observable<StateResource<UserProfileResource>>; - currentUserResource$: Observable<StateResource<UserProfileResource>>; + constructor( + private authService: AuthService, + private userProfileService: UserProfileService, + ) {} - constructor(private authService: AuthService, private userProfileService: UserProfileService) { } + ngOnInit(): void { + this.currentUserResource$ = this.userProfileService.getCurrentUser(); + } - ngOnInit(): void { - this.currentUserResource$ = this.userProfileService.getCurrentUser(); - } - - public logout(): void { - this.authService.logout(); - } + public logout(): void { + this.authService.logout(); + } } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html index 59c44f782751746884e0ca9038bbf534639724cc..3fb9f5af72a952068f8d799e64ab20156999d96f 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.html @@ -24,14 +24,20 @@ --> <ozgcloud-spinner [stateResource]="currentUserResource" [diameter]="30"> - <button mat-icon-button [matMenuTriggerFor]="accountMenu.matMenu" class="big-button" data-test-id="user-icon-button" [attr.aria-label]="buttonLabel"> - <alfa-user-icon [userProfileStateResource]="currentUserResource"></alfa-user-icon> - </button> + <button + mat-icon-button + [matMenuTriggerFor]="accountMenu.matMenu" + class="big-button" + data-test-id="user-icon-button" + [attr.aria-label]="buttonLabel" + > + <alfa-user-icon [userProfileStateResource]="currentUserResource"></alfa-user-icon> + </button> </ozgcloud-spinner> <ozgcloud-menu #accountMenu data-test-id="account-menu"> - <button mat-menu-item (click)="logoutEmitter.emit()" data-test-id="logout-button"> - <mat-icon>logout</mat-icon> - <span>Abmelden</span> - </button> + <button mat-menu-item (click)="logoutEmitter.emit()" data-test-id="logout-button"> + <mat-icon>logout</mat-icon> + <span>Abmelden</span> + </button> </ozgcloud-menu> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.scss b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.scss index 13c676bcf8e51513c9ddfa1fdb75b3bf1d8f0336..c5666d9743e182cff71a3ba333e706d625425baa 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.scss @@ -22,7 +22,7 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .big-button { - display: flex; - align-items: center; - justify-content: center; + display: flex; + align-items: center; + justify-content: center; } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts index fda6a23d2236a720662807086401d342eb863a2d..7e4375e4c86f179eef1987c90ee3017d3cf69650 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.spec.ts @@ -35,64 +35,62 @@ import { MockComponent } from 'ng-mocks'; import { UserProfileInHeaderComponent } from './user-profile-in-header.component'; describe('UserProfileInHeaderComponent', () => { - let component: UserProfileInHeaderComponent; - let fixture: ComponentFixture<UserProfileInHeaderComponent>; + let component: UserProfileInHeaderComponent; + let fixture: ComponentFixture<UserProfileInHeaderComponent>; - const logoutButton: string = getDataTestIdOf('logout-button'); - const userIconButton: string = getDataTestIdOf('user-icon-button'); + const logoutButton: string = getDataTestIdOf('logout-button'); + const userIconButton: string = getDataTestIdOf('user-icon-button'); - const userProfile: UserProfileResource = createUserProfileResource(); + const userProfile: UserProfileResource = createUserProfileResource(); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserProfileInHeaderComponent, - MatIcon, - MockComponent(UserIconComponent), - MockComponent(SpinnerComponent) - ], - imports: [ - NoopAnimationsModule, - UiModule - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserProfileInHeaderComponent, + MatIcon, + MockComponent(UserIconComponent), + MockComponent(SpinnerComponent), + ], + imports: [NoopAnimationsModule, UiModule], + }).compileComponents(); - fixture = TestBed.createComponent(UserProfileInHeaderComponent); - component = fixture.componentInstance; - component.currentUserResource = createStateResource(userProfile); - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(UserProfileInHeaderComponent); + component = fixture.componentInstance; + component.currentUserResource = createStateResource(userProfile); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('click on logout button', () => { - it('should emit logout event', () => { - jest.spyOn(component.logoutEmitter, 'emit'); + describe('click on logout button', () => { + it('should emit logout event', () => { + jest.spyOn(component.logoutEmitter, 'emit'); - getElementFromFixture(fixture, userIconButton).click(); - getElementFromDomRoot(fixture, logoutButton).click(); + getElementFromFixture(fixture, userIconButton).click(); + getElementFromDomRoot(fixture, logoutButton).click(); - expect(component.logoutEmitter.emit).toHaveBeenCalled(); - }) - }) + expect(component.logoutEmitter.emit).toHaveBeenCalled(); + }); + }); - describe('button', () => { - it('should have user name inside aria label', () => { - const button: HTMLButtonElement = getElementFromFixture(fixture, userIconButton); - const label: string = 'Benutzerkonto von ' + getUserName(component.currentUserResource.resource) + describe('button', () => { + it('should have user name inside aria label', () => { + const button: HTMLButtonElement = getElementFromFixture(fixture, userIconButton); + const label: string = + 'Benutzerkonto von ' + getUserName(component.currentUserResource.resource); - expect(button).toHaveAttribute('aria-label', expect.stringContaining(label)); - }) + expect(button).toHaveAttribute('aria-label', expect.stringContaining(label)); + }); - it('should not have user name inside aria label if no user loaded', () => { - const button: HTMLButtonElement = getElementFromFixture(fixture, userIconButton); - component.currentUserResource = createEmptyStateResource(); + it('should not have user name inside aria label if no user loaded', () => { + const button: HTMLButtonElement = getElementFromFixture(fixture, userIconButton); + component.currentUserResource = createEmptyStateResource(); - fixture.detectChanges(); + fixture.detectChanges(); - expect(button).toHaveAttribute('aria-label', expect.stringContaining('Benutzerkonto')); - }) - }) + expect(button).toHaveAttribute('aria-label', expect.stringContaining('Benutzerkonto')); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.ts index 8e29c15fa3232f57de8fd93af438152ff067ec34..31d36840e3efd9c38158bc8c6ce5405696170547 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-header-container/user-profile-in-header/user-profile-in-header.component.ts @@ -26,22 +26,21 @@ import { StateResource } from '@alfa-client/tech-shared'; import { getUserName, UserProfileResource } from '@alfa-client/user-profile-shared'; @Component({ - selector: 'alfa-user-profile-in-header', - templateUrl: './user-profile-in-header.component.html', - styleUrls: ['./user-profile-in-header.component.scss'], + selector: 'alfa-user-profile-in-header', + templateUrl: './user-profile-in-header.component.html', + styleUrls: ['./user-profile-in-header.component.scss'], }) export class UserProfileInHeaderComponent { + @Input() public currentUserResource: StateResource<UserProfileResource>; - @Input() public currentUserResource: StateResource<UserProfileResource>; + @Output() public logoutEmitter: EventEmitter<void> = new EventEmitter<void>(); - @Output() public logoutEmitter: EventEmitter<void> = new EventEmitter<void>() - - get buttonLabel(): string { - const label: string = this.currentUserResource - ? 'Benutzerkonto von ' + getUserName(this.currentUserResource.resource) - : 'Benutzerkonto'; - - return label; - } + get buttonLabel(): string { + const label: string = + this.currentUserResource ? + 'Benutzerkonto von ' + getUserName(this.currentUserResource.resource) + : 'Benutzerkonto'; + return label; + } } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.html index d29c7b095cb575fc83f422ac71603a1ad02f6379..ed2d5ac244cffefc04a9914cd17de0e75e572edf 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.html @@ -23,4 +23,8 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-user-profile class="user-profile" [userProfileStateResource]="userProfileStateResource$ | async" data-test-id="user-profile-in-historie"></alfa-user-profile> \ No newline at end of file +<alfa-user-profile + class="user-profile" + [userProfileStateResource]="userProfileStateResource$ | async" + data-test-id="user-profile-in-historie" +></alfa-user-profile> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.scss b/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.scss index 4505f565020f999313352bbf6d5d3180bfd0b28b..36435b0f57a8ce20736b277f986064ce0209ff26 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.scss @@ -22,21 +22,21 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - align-items: center; - justify-content: space-between; - position: relative; + display: flex; + align-items: center; + justify-content: space-between; + position: relative; } .user-profile { - display: flex; - align-items: center; - opacity: 0.4; + display: flex; + align-items: center; + opacity: 0.4; } :host ::ng-deep { - alfa-user-icon { - transform: scale(0.7); - margin-left: -4px; - } + alfa-user-icon { + transform: scale(0.7); + margin-left: -4px; + } } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.spec.ts index c42a4211bd892588df7018707d8595bf92fb3617..6156df3fd47968918c383ff83e97be497d71acab 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.spec.ts @@ -32,48 +32,45 @@ import { UserProfileComponent } from '../user-profile/user-profile.component'; import { UserProfileInHistorieContainerComponent } from './user-profile-in-historie-container.component'; describe('UserProfileInHistorieContainerComponent', () => { - let component: UserProfileInHistorieContainerComponent; - let fixture: ComponentFixture<UserProfileInHistorieContainerComponent>; + let component: UserProfileInHistorieContainerComponent; + let fixture: ComponentFixture<UserProfileInHistorieContainerComponent>; - const userProfileService = mock(UserProfileService); + const userProfileService = mock(UserProfileService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserProfileInHistorieContainerComponent, - MockComponent(UserProfileComponent), - ], - providers: [ - { - provide: UserProfileService, - useValue: userProfileService - } - ] - }).compileComponents(); - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UserProfileInHistorieContainerComponent, MockComponent(UserProfileComponent)], + providers: [ + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent( - UserProfileInHistorieContainerComponent - ); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileInHistorieContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + const command: CommandResource = createCommandResource(); - const command: CommandResource = createCommandResource(); + it('should call service', () => { + component.command = command; - it('should call service', () => { - component.command = command; + component.ngOnInit(); - component.ngOnInit(); - - expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith(command, CommandLinkRel.CREATED_BY); - }) - }) -}); \ No newline at end of file + expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith( + command, + CommandLinkRel.CREATED_BY, + ); + }); + }); +}); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.ts index 984fe5dc9aed86cffaf1de6aa1ad473a7adcf9a0..2e18b40a0921ee9ff05fa56de4ee7f95b1ff3e52 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-historie-container/user-profile-in-historie-container.component.ts @@ -29,19 +29,21 @@ import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-user-profile-in-historie-container', - templateUrl: './user-profile-in-historie-container.component.html', - styleUrls: ['./user-profile-in-historie-container.component.scss'], + selector: 'alfa-user-profile-in-historie-container', + templateUrl: './user-profile-in-historie-container.component.html', + styleUrls: ['./user-profile-in-historie-container.component.scss'], }) export class UserProfileInHistorieContainerComponent implements OnInit { + @Input() command: CommandResource; - @Input() command: CommandResource; + userProfileStateResource$: Observable<StateResource<UserProfileResource>>; - userProfileStateResource$: Observable<StateResource<UserProfileResource>>; + constructor(private userProfileService: UserProfileService) {} - constructor(private userProfileService: UserProfileService) { } - - ngOnInit(): void { - this.userProfileStateResource$ = this.userProfileService.getAssignedUserProfile(this.command, CommandLinkRel.CREATED_BY); - } -} \ No newline at end of file + ngOnInit(): void { + this.userProfileStateResource$ = this.userProfileService.getAssignedUserProfile( + this.command, + CommandLinkRel.CREATED_BY, + ); + } +} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.html index 7a2b6cc8382ba7795033e424bad626bb08425d8d..fb4af64e68f971cb49a3c35254080127efa7de09 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.html @@ -23,4 +23,8 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-user-profile class="user-profile" [userProfileStateResource]="userProfileStateResource$ | async" data-test-id="user-profile-in-kommentar"></alfa-user-profile> \ No newline at end of file +<alfa-user-profile + class="user-profile" + [userProfileStateResource]="userProfileStateResource$ | async" + data-test-id="user-profile-in-kommentar" +></alfa-user-profile> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.scss b/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.scss index 4fb20672d3ede357c92ed296a371025c9e14eb2d..d14c3777aa04200bf8cefe979bcb2da028ade016 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.scss @@ -22,14 +22,14 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - position: relative; + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + position: relative; } .user-profile { - display: flex; - align-items: center; + display: flex; + align-items: center; } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.spec.ts index 232c3d7f82597934cb11b945dfbce5a7c227bb0a..9fad4a696aca8fc99d1b8005cb3285eb350b3843 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.spec.ts @@ -32,55 +32,57 @@ import { UserProfileComponent } from '../user-profile/user-profile.component'; import { UserProfileInKommentarContainerComponent } from './user-profile-in-kommentar-container.component'; describe('UserProfileInKommentarContainerComponent', () => { - let component: UserProfileInKommentarContainerComponent; - let fixture: ComponentFixture<UserProfileInKommentarContainerComponent>; + let component: UserProfileInKommentarContainerComponent; + let fixture: ComponentFixture<UserProfileInKommentarContainerComponent>; - const userProfileService = mock(UserProfileService); + const userProfileService = mock(UserProfileService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserProfileInKommentarContainerComponent, - MockComponent(UserIconComponent), - MockComponent(UserProfileComponent) - ], - providers: [ - { - provide: UserProfileService, - useValue: userProfileService - } - ] - }).compileComponents(); - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserProfileInKommentarContainerComponent, + MockComponent(UserIconComponent), + MockComponent(UserProfileComponent), + ], + providers: [ + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileInKommentarContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileInKommentarContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + const kommentar: KommentarResource = createKommentarResource([KommentarLinkRel.CREATED_BY]); - const kommentar: KommentarResource = createKommentarResource([KommentarLinkRel.CREATED_BY]); + it('should call service if link exist', () => { + component.kommentar = kommentar; - it('should call service if link exist', () => { - component.kommentar = kommentar; + component.ngOnInit(); - component.ngOnInit(); + expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith( + kommentar, + KommentarLinkRel.CREATED_BY, + ); + }); - expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith(kommentar, KommentarLinkRel.CREATED_BY); - }) + it('should not call service if link is missing', () => { + component.kommentar = { ...createKommentarResource() }; - it('should not call service if link is missing', () => { - component.kommentar = { ...createKommentarResource() }; + component.ngOnInit(); - component.ngOnInit(); - - expect(userProfileService.getAssignedUserProfile).not.toHaveBeenCalledWith(); - }) - }) + expect(userProfileService.getAssignedUserProfile).not.toHaveBeenCalledWith(); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.ts index eeb01847bb2559a49a1a14d632e0cbfc746ceecc..cc7f2ff03967046a08b4e8f4fe10ce95c6fda994 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-kommentar-container/user-profile-in-kommentar-container.component.ts @@ -29,21 +29,23 @@ import { hasLink } from '@ngxp/rest'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-user-profile-in-kommentar-container', - templateUrl: './user-profile-in-kommentar-container.component.html', - styleUrls: ['./user-profile-in-kommentar-container.component.scss'] + selector: 'alfa-user-profile-in-kommentar-container', + templateUrl: './user-profile-in-kommentar-container.component.html', + styleUrls: ['./user-profile-in-kommentar-container.component.scss'], }) export class UserProfileInKommentarContainerComponent implements OnInit { + @Input() kommentar: KommentarResource; - @Input() kommentar: KommentarResource; + userProfileStateResource$: Observable<StateResource<UserProfileResource>>; - userProfileStateResource$: Observable<StateResource<UserProfileResource>>; + constructor(private userProfileService: UserProfileService) {} - constructor(private userProfileService: UserProfileService) { } - - ngOnInit(): void { - if (this.kommentar && hasLink(this.kommentar, KommentarLinkRel.CREATED_BY)) { - this.userProfileStateResource$ = this.userProfileService.getAssignedUserProfile(this.kommentar, KommentarLinkRel.CREATED_BY); - } - } -} \ No newline at end of file + ngOnInit(): void { + if (this.kommentar && hasLink(this.kommentar, KommentarLinkRel.CREATED_BY)) { + this.userProfileStateResource$ = this.userProfileService.getAssignedUserProfile( + this.kommentar, + KommentarLinkRel.CREATED_BY, + ); + } + } +} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.html index 6a1c45514ed59ab298734e8dc7aaaee79021d45d..4b57699c0cbc0873db97b09d9f2ca16a40f646da 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.html @@ -23,4 +23,7 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-user-profile class="user-profile" [userProfileStateResource]="userProfileStateResource$ | async"></alfa-user-profile> \ No newline at end of file +<alfa-user-profile + class="user-profile" + [userProfileStateResource]="userProfileStateResource$ | async" +></alfa-user-profile> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.scss b/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.scss index a94a4c466ef87256c9df0754168d72be7abe87ab..390ca67a50193c6126091657ceda6928d0e3b415 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.scss @@ -22,15 +22,15 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - position: relative; - overflow: hidden; + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + position: relative; + overflow: hidden; } .user-profile { - display: flex; - align-items: center; + display: flex; + align-items: center; } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.spec.ts index 7ece5838d4841d0c862e2700686c0c5d8d3034a7..c67dc474ad449ce118cbe82e13b8af1b9c604fa2 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.spec.ts @@ -32,47 +32,49 @@ import { UserProfileComponent } from '../user-profile/user-profile.component'; import { UserProfileInPostfachMailContainerComponent } from './user-profile-in-postfach-mail-container.component'; describe('UserProfileInPostfachMailComponent', () => { - let component: UserProfileInPostfachMailContainerComponent; - let fixture: ComponentFixture<UserProfileInPostfachMailContainerComponent>; + let component: UserProfileInPostfachMailContainerComponent; + let fixture: ComponentFixture<UserProfileInPostfachMailContainerComponent>; - const userProfileService = mock(UserProfileService); + const userProfileService = mock(UserProfileService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserProfileInPostfachMailContainerComponent, - MockComponent(UserIconComponent), - MockComponent(UserProfileComponent) - ], - providers: [ - { - provide: UserProfileService, - useValue: userProfileService - } - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserProfileInPostfachMailContainerComponent, + MockComponent(UserIconComponent), + MockComponent(UserProfileComponent), + ], + providers: [ + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileInPostfachMailContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileInPostfachMailContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnChanges', () => { + describe('ngOnChanges', () => { + const postfachMail: PostfachMailResource = createPostfachMailResource(); - const postfachMail: PostfachMailResource = createPostfachMailResource(); + it('should call service', () => { + component.postfachMail = postfachMail; - it('should call service', () => { - component.postfachMail = postfachMail; + component.ngOnChanges(); - component.ngOnChanges(); - - expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith(postfachMail, PostfachMailLinkRel.CREATED_BY); - }) - }) + expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith( + postfachMail, + PostfachMailLinkRel.CREATED_BY, + ); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.ts index bc1d396d4d022b00c7acf6834a9124c9de970d4f..567c853cdb4da2f7f815a386ec1b2da7f6755582 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-postfach-mail-container/user-profile-in-postfach-mail-container.component.ts @@ -28,21 +28,23 @@ import { UserProfileResource, UserProfileService } from '@alfa-client/user-profi import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-user-profile-in-postfach-mail-container', - templateUrl: './user-profile-in-postfach-mail-container.component.html', - styleUrls: ['./user-profile-in-postfach-mail-container.component.scss'] + selector: 'alfa-user-profile-in-postfach-mail-container', + templateUrl: './user-profile-in-postfach-mail-container.component.html', + styleUrls: ['./user-profile-in-postfach-mail-container.component.scss'], }) export class UserProfileInPostfachMailContainerComponent { + @Input() postfachMail: PostfachMailResource; - @Input() postfachMail: PostfachMailResource; + userProfileStateResource$: Observable<StateResource<UserProfileResource>>; - userProfileStateResource$: Observable<StateResource<UserProfileResource>>; + constructor(private userProfileService: UserProfileService) {} - constructor(private userProfileService: UserProfileService) { } - - ngOnChanges(): void { - if (this.postfachMail) { - this.userProfileStateResource$ = this.userProfileService.getAssignedUserProfile(this.postfachMail, PostfachMailLinkRel.CREATED_BY); - } - } -} \ No newline at end of file + ngOnChanges(): void { + if (this.postfachMail) { + this.userProfileStateResource$ = this.userProfileService.getAssignedUserProfile( + this.postfachMail, + PostfachMailLinkRel.CREATED_BY, + ); + } + } +} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.html index 0fb6c18a3ff6474747880a9eeefc636248258a15..74fce4b48f26bb5c06d59a5bd1986b8a20659637 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.html @@ -23,4 +23,7 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-user-profile-in-vorgang [vorgang]="vorgang" [userProfile]="userProfile$ | async"></alfa-user-profile-in-vorgang> +<alfa-user-profile-in-vorgang + [vorgang]="vorgang" + [userProfile]="userProfile$ | async" +></alfa-user-profile-in-vorgang> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.scss b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.scss index 4453de244bb1ed104408610c407244423e21ea96..c297c9c52d418cac9222abcdc02a5d08f83c3187 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.scss @@ -22,8 +22,8 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .user-profile-icon { - border-radius: 50%; - margin: 0; - padding: 2px; - display: block; + border-radius: 50%; + margin: 0; + padding: 2px; + display: block; } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.spec.ts index 66a0d6ab4dc2685f9226447edf75362b2ea0cd1a..52b0a1a84e0ddb2b763406161f598086289bdcd0 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.spec.ts @@ -32,54 +32,61 @@ import { UserProfileInVorgangContainerComponent } from './user-profile-in-vorgan import { UserProfileInVorgangComponent } from './user-profile-in-vorgang/user-profile-in-vorgang.component'; describe('UserProfileInVorgangContainerComponent', () => { - let component: UserProfileInVorgangContainerComponent; - let fixture: ComponentFixture<UserProfileInVorgangContainerComponent>; + let component: UserProfileInVorgangContainerComponent; + let fixture: ComponentFixture<UserProfileInVorgangContainerComponent>; - const visibilitySubj: BehaviorSubject<boolean> = new BehaviorSubject(false); - const userProfileService = { ...mock(UserProfileService), isUserProfileSearchVisible: () => visibilitySubj }; + const visibilitySubj: BehaviorSubject<boolean> = new BehaviorSubject(false); + const userProfileService = { + ...mock(UserProfileService), + isUserProfileSearchVisible: () => visibilitySubj, + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserProfileInVorgangContainerComponent, - MockComponent(UserProfileInVorgangComponent) - ], - providers: [ - { - provide: UserProfileService, - useValue: userProfileService - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserProfileInVorgangContainerComponent, + MockComponent(UserProfileInVorgangComponent), + ], + providers: [ + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileInVorgangContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileInVorgangContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnChanges', () => { + describe('ngOnChanges', () => { + it('should call userProfileService if link is present', () => { + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangHeaderLinkRel.ASSIGNED_TO, + ]); + component.vorgang = vorgang; - it('should call userProfileService if link is present', () => { - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangHeaderLinkRel.ASSIGNED_TO]); - component.vorgang = vorgang + component.ngOnChanges({ vorgang: <any>{} }); - component.ngOnChanges({ vorgang: <any>{} }); + expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith( + vorgang, + VorgangHeaderLinkRel.ASSIGNED_TO, + ); + }); - expect(userProfileService.getAssignedUserProfile).toHaveBeenCalledWith(vorgang, VorgangHeaderLinkRel.ASSIGNED_TO); - }) + it('should NOT call userProfileService', () => { + component.vorgang = createVorgangWithEingangResource(); - it('should NOT call userProfileService', () => { - component.vorgang = createVorgangWithEingangResource(); + component.ngOnChanges({ vorgang: <any>{} }); - component.ngOnChanges({ vorgang: <any>{} }); - - expect(userProfileService.getAssignedUserProfile).not.toHaveBeenCalledWith(); - }) - }) + expect(userProfileService.getAssignedUserProfile).not.toHaveBeenCalledWith(); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.ts index f7f2bf90b0862cb345d39f72f013b856fea90c37..ef401b89d33bab97c1f9b6faadee68c6cb6b7ae1 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component.ts @@ -30,21 +30,29 @@ import { isNil } from 'lodash-es'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-user-profile-in-vorgang-container', - templateUrl: './user-profile-in-vorgang-container.component.html', - styleUrls: ['./user-profile-in-vorgang-container.component.scss'] + selector: 'alfa-user-profile-in-vorgang-container', + templateUrl: './user-profile-in-vorgang-container.component.html', + styleUrls: ['./user-profile-in-vorgang-container.component.scss'], }) export class UserProfileInVorgangContainerComponent { + @Input() vorgang: VorgangWithEingangResource; - @Input() vorgang: VorgangWithEingangResource; + userProfile$: Observable<StateResource<UserProfileResource>> = of( + createEmptyStateResource<UserProfileResource>(), + ); - userProfile$: Observable<StateResource<UserProfileResource>> = of(createEmptyStateResource<UserProfileResource>()); + constructor(public userProfileService: UserProfileService) {} - constructor(public userProfileService: UserProfileService) { } - - ngOnChanges(changes: SimpleChanges): void { - if (changes.vorgang && !isNil(this.vorgang) && hasLink(this.vorgang, VorgangHeaderLinkRel.ASSIGNED_TO)) { - this.userProfile$ = this.userProfileService.getAssignedUserProfile(this.vorgang, VorgangHeaderLinkRel.ASSIGNED_TO); - } - } -} \ No newline at end of file + ngOnChanges(changes: SimpleChanges): void { + if ( + changes.vorgang && + !isNil(this.vorgang) && + hasLink(this.vorgang, VorgangHeaderLinkRel.ASSIGNED_TO) + ) { + this.userProfile$ = this.userProfileService.getAssignedUserProfile( + this.vorgang, + VorgangHeaderLinkRel.ASSIGNED_TO, + ); + } + } +} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/_user-profile-in-vorgang.theme.scss b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/_user-profile-in-vorgang.theme.scss index 7b717458091b9416f8633032301244af35a16df9..1b0eb8d65a7a5e03744ebe3bbdfcd300f3a35d5b 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/_user-profile-in-vorgang.theme.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/_user-profile-in-vorgang.theme.scss @@ -25,21 +25,20 @@ @use '@angular/material' as mat; @mixin user-profile-icon($theme) { - $color-config: mat.get-color-config($theme); - $primary: map.get($color-config, 'primary'); + $color-config: mat.get-color-config($theme); + $primary: map.get($color-config, 'primary'); - alfa-user-profile-in-vorgang-container { + alfa-user-profile-in-vorgang-container { + .user-profile-button { + &:focus-within { + .user-profile-icon { + box-shadow: 0 0 0 2px mat.get-color-from-palette($primary); + } + } - .user-profile-button { - &:focus-within { - .user-profile-icon { - box-shadow: 0 0 0 2px mat.get-color-from-palette($primary); - } - } - - .user-profile-icon { - box-shadow: 0 0 0 1px mat.get-color-from-palette($primary); - } - } - } + .user-profile-icon { + box-shadow: 0 0 0 1px mat.get-color-from-palette($primary); + } + } + } } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.html index 35957f2abe98069d15d73449b4aa0af40d103e5b..5fa5cdf3ab2ef420c6aba8fdafb9fe6b64f8dd17 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.html @@ -23,20 +23,28 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<button #menuTrigger="matMenuTrigger" - [matMenuTriggerFor]="menu.matMenu" - (menuOpened)="showUserProfileSearch()" (menuClosed)="hideUserProfileSearch()" - aria-label="Bearbeiter ändern" - class="user-profile-button"> - - <alfa-user-icon data-test-id="user-profile-icon" - [userProfileStateResource]="userProfile" - class="user-profile-icon"> - </alfa-user-icon> +<button + #menuTrigger="matMenuTrigger" + [matMenuTriggerFor]="menu.matMenu" + (menuOpened)="showUserProfileSearch()" + (menuClosed)="hideUserProfileSearch()" + aria-label="Bearbeiter ändern" + class="user-profile-button" +> + <alfa-user-icon + data-test-id="user-profile-icon" + [userProfileStateResource]="userProfile" + class="user-profile-icon" + > + </alfa-user-icon> </button> <ozgcloud-menu #menu> - <alfa-user-profile-search-container *ngIf="showUserProfileSearch$ | async" data-test-id="user-profile-search-container" - (click)="$event.stopPropagation()" (assigned)="menuTrigger.closeMenu()"> - </alfa-user-profile-search-container> + <alfa-user-profile-search-container + *ngIf="showUserProfileSearch$ | async" + data-test-id="user-profile-search-container" + (click)="$event.stopPropagation()" + (assigned)="menuTrigger.closeMenu()" + > + </alfa-user-profile-search-container> </ozgcloud-menu> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.scss b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.scss index 03209bebef753f062bb961da45cb2194e949bbd8..ba63d042640d49669acd20a201043d2cc5b85e16 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.scss @@ -22,18 +22,18 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .user-profile-button { - border: 0; - background-color: transparent; - margin: 0; - padding: 0; - display: block; - outline: 0; - cursor: pointer; + border: 0; + background-color: transparent; + margin: 0; + padding: 0; + display: block; + outline: 0; + cursor: pointer; } .user-profile-icon { - border-radius: 50%; - margin: 0; - padding: 2px; - display: block; -} \ No newline at end of file + border-radius: 50%; + margin: 0; + padding: 2px; + display: block; +} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.spec.ts index 6657204a27459e5a909cd2c57bbd3a227d7a1006..4464f2f109503b0424b404266a04c7bd80bee70b 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.spec.ts @@ -32,90 +32,86 @@ import { UserProfileSearchContainerComponent } from '../../../user-profile-searc import { UserProfileButtonContainerComponent } from './user-profile-button-container.component'; describe('UserProfileButtonContainerComponent', () => { - let component: UserProfileButtonContainerComponent; - let fixture: ComponentFixture<UserProfileButtonContainerComponent>; - - const userProfileSearchVisbilitySubj: BehaviorSubject<boolean> = new BehaviorSubject(false); - const userProfileService = { ...mock(UserProfileService), getUserProfileSearchVisibility: () => userProfileSearchVisbilitySubj}; - - beforeEach(async () => { - TestBed.configureTestingModule({ - declarations: [ - UserProfileButtonContainerComponent, - MockComponent(UserIconComponent), - MockComponent(UserProfileSearchContainerComponent), - MockComponent(OzgcloudMenuComponent) - ], - providers: [ - { - provide: UserProfileService, - useValue: userProfileService - } - ], - imports:[ - UiModule - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileButtonContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call getUserProfileSearchVisibility', () => { - component.getUserProfileSearchVisibility = jest.fn(); - - component.ngOnInit(); - - expect(component.getUserProfileSearchVisibility).toHaveBeenCalled(); - }) - }) - - describe('getUserProfileSearchVisibility', () => { - - it('should call handleVisibilityChange', () => { - component.handleVisibilityChange = jest.fn(); - - component.getUserProfileSearchVisibility().subscribe(); - - expect(component.handleVisibilityChange).toHaveBeenCalled(); - }) - }) - - describe('handleVisibilityChange', () => { - - it('should openMenu if changed to true', () => { - component.menuTrigger.openMenu = jest.fn(); - - component.handleVisibilityChange(true); - - expect(component.menuTrigger.openMenu).toHaveBeenCalled(); - }) - }) - - describe('showUserProfileSearch', () => { - - it('should call userProfileService.showUserProfileSearch', () => { - component.showUserProfileSearch(); - - expect(userProfileService.showUserProfileSearch).toHaveBeenCalled(); - }) - }) - - describe('hideUserProfileSearch', () => { - - it('should call userProfileService.hideUserProfileSearch', () => { - component.hideUserProfileSearch(); - - expect(userProfileService.hideUserProfileSearch).toHaveBeenCalled(); - }) - }) + let component: UserProfileButtonContainerComponent; + let fixture: ComponentFixture<UserProfileButtonContainerComponent>; + + const userProfileSearchVisbilitySubj: BehaviorSubject<boolean> = new BehaviorSubject(false); + const userProfileService = { + ...mock(UserProfileService), + getUserProfileSearchVisibility: () => userProfileSearchVisbilitySubj, + }; + + beforeEach(async () => { + TestBed.configureTestingModule({ + declarations: [ + UserProfileButtonContainerComponent, + MockComponent(UserIconComponent), + MockComponent(UserProfileSearchContainerComponent), + MockComponent(OzgcloudMenuComponent), + ], + providers: [ + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + imports: [UiModule], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileButtonContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call getUserProfileSearchVisibility', () => { + component.getUserProfileSearchVisibility = jest.fn(); + + component.ngOnInit(); + + expect(component.getUserProfileSearchVisibility).toHaveBeenCalled(); + }); + }); + + describe('getUserProfileSearchVisibility', () => { + it('should call handleVisibilityChange', () => { + component.handleVisibilityChange = jest.fn(); + + component.getUserProfileSearchVisibility().subscribe(); + + expect(component.handleVisibilityChange).toHaveBeenCalled(); + }); + }); + + describe('handleVisibilityChange', () => { + it('should openMenu if changed to true', () => { + component.menuTrigger.openMenu = jest.fn(); + + component.handleVisibilityChange(true); + + expect(component.menuTrigger.openMenu).toHaveBeenCalled(); + }); + }); + + describe('showUserProfileSearch', () => { + it('should call userProfileService.showUserProfileSearch', () => { + component.showUserProfileSearch(); + + expect(userProfileService.showUserProfileSearch).toHaveBeenCalled(); + }); + }); + + describe('hideUserProfileSearch', () => { + it('should call userProfileService.hideUserProfileSearch', () => { + component.hideUserProfileSearch(); + + expect(userProfileService.hideUserProfileSearch).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.ts index 5661a4b8a41eea85cc4b2706d0d358520040e226..1c7451882382e8bdd72e1b6a66b44c48a3b1dc01 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-button-container/user-profile-button-container.component.ts @@ -28,39 +28,40 @@ import { UserProfileResource, UserProfileService } from '@alfa-client/user-profi import { Observable, tap } from 'rxjs'; @Component({ - selector: 'alfa-user-profile-button-container', - templateUrl: './user-profile-button-container.component.html', - styleUrls: ['./user-profile-button-container.component.scss'] + selector: 'alfa-user-profile-button-container', + templateUrl: './user-profile-button-container.component.html', + styleUrls: ['./user-profile-button-container.component.scss'], }) export class UserProfileButtonContainerComponent implements OnInit { + @Input() userProfile: StateResource<UserProfileResource>; - @Input() userProfile: StateResource<UserProfileResource>; + @ViewChild(MatMenuTrigger) menuTrigger: MatMenuTrigger; - @ViewChild(MatMenuTrigger) menuTrigger: MatMenuTrigger; + showUserProfileSearch$: Observable<boolean>; - showUserProfileSearch$: Observable<boolean>; + constructor(public userProfileService: UserProfileService) {} - constructor(public userProfileService: UserProfileService) { } + ngOnInit(): void { + this.showUserProfileSearch$ = this.getUserProfileSearchVisibility(); + } - ngOnInit(): void { - this.showUserProfileSearch$ = this.getUserProfileSearchVisibility(); - } + getUserProfileSearchVisibility(): Observable<boolean> { + return this.userProfileService + .getUserProfileSearchVisibility() + .pipe(tap((visibility: boolean) => this.handleVisibilityChange(visibility))); + } - getUserProfileSearchVisibility(): Observable<boolean> { - return this.userProfileService.getUserProfileSearchVisibility().pipe(tap((visibility: boolean) => this.handleVisibilityChange(visibility))); - } + handleVisibilityChange(visibility: boolean): void { + if (visibility) { + this.menuTrigger.openMenu(); + } + } - handleVisibilityChange(visibility: boolean): void { - if(visibility) { - this.menuTrigger.openMenu(); - } - } + public showUserProfileSearch(): void { + this.userProfileService.showUserProfileSearch(); + } - public showUserProfileSearch(): void { - this.userProfileService.showUserProfileSearch(); - } - - public hideUserProfileSearch(): void { - this.userProfileService.hideUserProfileSearch(); - } -} \ No newline at end of file + public hideUserProfileSearch(): void { + this.userProfileService.hideUserProfileSearch(); + } +} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.html index 30c554c1604dc2de620b7d98dd760b41d837a105..79b2ab0f5e4f60ceea92af54fbb6a0dcaa62119f 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.html @@ -23,13 +23,23 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ng-container *ngIf="(vorgang | hasLink: vorgangLinkRel.SEARCH_USER_PROFILES) && isUserServiceAvailable(userProfile); else iconOnly"> - <alfa-user-profile-button-container [userProfile]="userProfile" data-test-id="user-profile-button-container"></alfa-user-profile-button-container> +<ng-container + *ngIf=" + (vorgang | hasLink: vorgangLinkRel.SEARCH_USER_PROFILES) && isUserServiceAvailable(userProfile); + else iconOnly + " +> + <alfa-user-profile-button-container + [userProfile]="userProfile" + data-test-id="user-profile-button-container" + ></alfa-user-profile-button-container> </ng-container> <ng-template #iconOnly> - <alfa-user-icon data-test-id="vorgang-detail-user-profile-icon" - [userProfileStateResource]="userProfile" - class="user-profile-icon"> - </alfa-user-icon> -</ng-template> \ No newline at end of file + <alfa-user-icon + data-test-id="vorgang-detail-user-profile-icon" + [userProfileStateResource]="userProfile" + class="user-profile-icon" + > + </alfa-user-icon> +</ng-template> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.spec.ts index 0283a243330ed5cc7c10af4eeca323ca82872e10..d0baa0f8861824caadd99a48c7b5db4b9535c3c3 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.spec.ts @@ -22,7 +22,14 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { HasLinkPipe, MessageCode, StateResource, createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + HasLinkPipe, + MessageCode, + StateResource, + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { getElementFromFixture } from '@alfa-client/test-utils'; import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -35,127 +42,141 @@ import { UserProfileButtonContainerComponent } from './user-profile-button-conta import { UserProfileInVorgangComponent } from './user-profile-in-vorgang.component'; describe('UserProfileInVorgangComponent', () => { - let component: UserProfileInVorgangComponent; - let fixture: ComponentFixture<UserProfileInVorgangComponent>; + let component: UserProfileInVorgangComponent; + let fixture: ComponentFixture<UserProfileInVorgangComponent>; + + const buttonContainer: string = getDataTestIdOf('user-profile-button-container'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserProfileInVorgangComponent, + HasLinkPipe, + MockComponent(UserIconComponent), + MockComponent(UserProfileButtonContainerComponent), + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileInVorgangComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('isUserServiceAvailable', () => { + it('should return false on service unavailable error', () => { + const userProfileStateResource: StateResource<any> = createErrorStateResource({ + ...createApiError(), + issues: [<any>{ messageCode: MessageCode.SERVICE_UNAVAILABLE }], + }); + + const isUserServiceAvailable: boolean = + component.isUserServiceAvailable(userProfileStateResource); + + expect(isUserServiceAvailable).toBeFalsy(); + }); + + it('should return true on empty user profile', () => { + const isUserServiceAvailable: boolean = component.isUserServiceAvailable( + createEmptyStateResource(), + ); + + expect(isUserServiceAvailable).toBeTruthy(); + }); + + it('should return true on resource not found error', () => { + const userProfileStateResource: StateResource<any> = createErrorStateResource({ + ...createApiError(), + issues: [<any>{ messageCode: MessageCode.RESOURCE_NOT_FOUND }], + }); + + const isUserServiceAvailable: boolean = + component.isUserServiceAvailable(userProfileStateResource); + + expect(isUserServiceAvailable).toBeTruthy(); + }); + }); + + describe('search possibility', () => { + describe('by "search-user-profile" link', () => { + it('should be included if link is present', () => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.SEARCH_USER_PROFILES, + ]); + + fixture.detectChanges(); + const element = getElementFromFixture(fixture, buttonContainer); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should NOT be included if link is NOT present', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const element = getElementFromFixture(fixture, buttonContainer); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('by service', () => { + beforeEach(() => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.SEARCH_USER_PROFILES, + ]); + }); + + describe('on unavailable service(503)', () => { + it('should be included if is available(response of userProfile request is valid)', () => { + component.userProfile = createStateResource(createUserProfileResource()); + + fixture.detectChanges(); + const element = getElementFromFixture(fixture, buttonContainer); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should NOT be included if is unavailable', () => { + component.userProfile = createErrorStateResource({ + ...createApiError(), + issues: [<any>{ messageCode: MessageCode.SERVICE_UNAVAILABLE }], + }); + + fixture.detectChanges(); + const element = getElementFromFixture(fixture, buttonContainer); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('on resource not found(404)', () => { + it('should be included if is available', () => { + component.userProfile = createStateResource(createUserProfileResource()); + + fixture.detectChanges(); + const element = getElementFromFixture(fixture, buttonContainer); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should be included if is available but resource not found', () => { + component.userProfile = createErrorStateResource({ + ...createApiError(), + issues: [<any>{ messageCode: MessageCode.RESOURCE_NOT_FOUND }], + }); + + fixture.detectChanges(); + const element = getElementFromFixture(fixture, buttonContainer); - const buttonContainer: string = getDataTestIdOf('user-profile-button-container'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserProfileInVorgangComponent, - HasLinkPipe, - MockComponent(UserIconComponent), - MockComponent(UserProfileButtonContainerComponent) - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileInVorgangComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('isUserServiceAvailable', () => { - - it('should return false on service unavailable error', () => { - const userProfileStateResource: StateResource<any> = createErrorStateResource({ ...createApiError(), issues: [<any>{ messageCode: MessageCode.SERVICE_UNAVAILABLE }] }); - - const isUserServiceAvailable: boolean = component.isUserServiceAvailable(userProfileStateResource); - - expect(isUserServiceAvailable).toBeFalsy(); - }) - - it('should return true on empty user profile', () => { - const isUserServiceAvailable: boolean = component.isUserServiceAvailable(createEmptyStateResource()); - - expect(isUserServiceAvailable).toBeTruthy(); - }) - - it('should return true on resource not found error', () => { - const userProfileStateResource: StateResource<any> = createErrorStateResource({ ...createApiError(), issues: [<any>{ messageCode: MessageCode.RESOURCE_NOT_FOUND }] }); - - const isUserServiceAvailable: boolean = component.isUserServiceAvailable(userProfileStateResource); - - expect(isUserServiceAvailable).toBeTruthy(); - }) - }) - - describe('search possibility', () => { - - describe('by "search-user-profile" link', () => { - - it('should be included if link is present', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.SEARCH_USER_PROFILES]); - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, buttonContainer); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should NOT be included if link is NOT present', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, buttonContainer); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('by service', () => { - - beforeEach(() => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.SEARCH_USER_PROFILES]); - }) - - describe('on unavailable service(503)', () => { - - it('should be included if is available(response of userProfile request is valid)', () => { - component.userProfile = createStateResource(createUserProfileResource()); - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, buttonContainer); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should NOT be included if is unavailable', () => { - component.userProfile = createErrorStateResource({ ...createApiError(), issues: [<any>{ messageCode: MessageCode.SERVICE_UNAVAILABLE }] }); - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, buttonContainer); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('on resource not found(404)', () => { - - it('should be included if is available', () => { - component.userProfile = createStateResource(createUserProfileResource()); - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, buttonContainer); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should be included if is available but resource not found', () => { - component.userProfile = createErrorStateResource({ ...createApiError(), issues: [<any>{ messageCode: MessageCode.RESOURCE_NOT_FOUND }] }); - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, buttonContainer); - - expect(element).toBeInstanceOf(HTMLElement); - }) - }) - }) - }) + expect(element).toBeInstanceOf(HTMLElement); + }); + }); + }); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.ts index d1526245467a918ec313fc6684178396fcc2de8d..a255e3a75afd20a9085cae37f92e405d00fc0fd8 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang/user-profile-in-vorgang.component.ts @@ -22,27 +22,32 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Component, Input } from '@angular/core'; -import { StateResource, createEmptyStateResource, hasError, isServiceUnavailableMessageCode } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + hasError, + isServiceUnavailableMessageCode, +} from '@alfa-client/tech-shared'; import { UserProfileResource } from '@alfa-client/user-profile-shared'; import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { Resource } from '@ngxp/rest'; @Component({ - selector: 'alfa-user-profile-in-vorgang', - templateUrl: './user-profile-in-vorgang.component.html', - styleUrls: ['./user-profile-in-vorgang.component.scss'] + selector: 'alfa-user-profile-in-vorgang', + templateUrl: './user-profile-in-vorgang.component.html', + styleUrls: ['./user-profile-in-vorgang.component.scss'], }) export class UserProfileInVorgangComponent { + @Input() vorgang: VorgangWithEingangResource; + @Input() userProfile: StateResource<UserProfileResource> = + createEmptyStateResource<UserProfileResource>(); - @Input() vorgang: VorgangWithEingangResource; - @Input() userProfile: StateResource<UserProfileResource> = createEmptyStateResource<UserProfileResource>(); + readonly vorgangLinkRel = VorgangWithEingangLinkRel; - readonly vorgangLinkRel = VorgangWithEingangLinkRel; - - public isUserServiceAvailable(stateResource: StateResource<Resource>): boolean { - if (hasError(stateResource) && isServiceUnavailableMessageCode(stateResource.error)) { - return false; - } - return true; - } + public isUserServiceAvailable(stateResource: StateResource<Resource>): boolean { + if (hasError(stateResource) && isServiceUnavailableMessageCode(stateResource.error)) { + return false; + } + return true; + } } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.html index 0fb4834ea682607e1f5898cfd9a243a17057c209..bbe43b91b47df2ae22deaf6298b3ae19d500b556 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.html @@ -23,4 +23,7 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-user-icon [userProfileStateResource]="userProfile$ | async" class="user-profile-icon"></alfa-user-icon> \ No newline at end of file +<alfa-user-icon + [userProfileStateResource]="userProfile$ | async" + class="user-profile-icon" +></alfa-user-icon> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.spec.ts index 53b2ed50101c6c9727ff349b234fd6a1db7f62d1..d05d8010aed6e63e1c480fb6c334e8b0ffb7ed28 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.spec.ts @@ -29,33 +29,33 @@ import { UserIconComponent } from '../user-icon/user-icon.component'; import { UserProfileInVorgangListItemContainerComponent } from './user-profile-in-vorgang-list-item-container.component'; describe('UserProfileInVorgangListItemContainerComponent', () => { - let component: UserProfileInVorgangListItemContainerComponent; - let fixture: ComponentFixture<UserProfileInVorgangListItemContainerComponent>; + let component: UserProfileInVorgangListItemContainerComponent; + let fixture: ComponentFixture<UserProfileInVorgangListItemContainerComponent>; - const userProfileService = mock(UserProfileService); + const userProfileService = mock(UserProfileService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserProfileInVorgangListItemContainerComponent, - MockComponent(UserIconComponent) - ], - providers: [ - { - provide: UserProfileService, - useValue: userProfileService - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserProfileInVorgangListItemContainerComponent, + MockComponent(UserIconComponent), + ], + providers: [ + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileInVorgangListItemContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileInVorgangListItemContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.ts index 8e31e3dcecfa6ce8e7c56da8a918596e292973da..469ff7247fe8c3c077751c1a8de37ad98723ba12 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-in-vorgang-list-item-container/user-profile-in-vorgang-list-item-container.component.ts @@ -30,21 +30,25 @@ import { isNil } from 'lodash-es'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-user-profile-in-vorgang-list-item-container', - templateUrl: './user-profile-in-vorgang-list-item-container.component.html', - styleUrls: ['./user-profile-in-vorgang-list-item-container.component.scss'] + selector: 'alfa-user-profile-in-vorgang-list-item-container', + templateUrl: './user-profile-in-vorgang-list-item-container.component.html', + styleUrls: ['./user-profile-in-vorgang-list-item-container.component.scss'], }) export class UserProfileInVorgangListItemContainerComponent { + @Input() vorgang: VorgangWithEingangResource; - @Input() vorgang: VorgangWithEingangResource; + userProfile$: Observable<StateResource<UserProfileResource>> = of( + createEmptyStateResource<UserProfileResource>(), + ); - userProfile$: Observable<StateResource<UserProfileResource>> = of(createEmptyStateResource<UserProfileResource>()); + constructor(public userProfileService: UserProfileService) {} - constructor(public userProfileService: UserProfileService) { } - - ngOnChanges(): void { - if (!isNil(this.vorgang) && hasLink(this.vorgang, VorgangHeaderLinkRel.ASSIGNED_TO)) { - this.userProfile$ = this.userProfileService.getAssignedUserProfile(this.vorgang, VorgangHeaderLinkRel.ASSIGNED_TO); - } - } + ngOnChanges(): void { + if (!isNil(this.vorgang) && hasLink(this.vorgang, VorgangHeaderLinkRel.ASSIGNED_TO)) { + this.userProfile$ = this.userProfileService.getAssignedUserProfile( + this.vorgang, + VorgangHeaderLinkRel.ASSIGNED_TO, + ); + } + } } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.html index 7dd03fbbaba7df0cfc38dbf08c72f4e9ce6129d0..f43a61a3788b060e6c8f85a9661eafc714c4e70b 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.html @@ -23,7 +23,12 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<span *ngIf="userProfileStateResource.error; else user" class="username" data-test-class="user-profile-name-unknown">Unbekannter Benutzer</span> +<span + *ngIf="userProfileStateResource.error; else user" + class="username" + data-test-class="user-profile-name-unknown" + >Unbekannter Benutzer</span +> <ng-template #user> - <span class="username" data-test-class="user-profile-name">{{userName}}</span> -</ng-template> \ No newline at end of file + <span class="username" data-test-class="user-profile-name">{{ userName }}</span> +</ng-template> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.scss b/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.scss index 3cd4310751d12557932c20bc0fa4e241c07fb51e..c9457a818f6880d9cecb107a6fbb1679a8ba7c64 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.scss @@ -23,12 +23,12 @@ */ :host { - min-width: 0; + min-width: 0; } .username { - display: block; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} \ No newline at end of file + display: block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.spec.ts index 7253d7b3263c1e65db80bad04f9a6077874b2771..b774df38c0459aebc49efc7a9621253b7a5e04e7 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.spec.ts @@ -22,7 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { createEmptyStateResource, createErrorStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createErrorStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { UserProfileResource } from '@alfa-client/user-profile-shared'; import { getDataTestClassOf } from 'libs/tech-shared/test/data-test'; import { createApiError } from 'libs/tech-shared/test/error'; @@ -30,57 +34,55 @@ import { createUserProfileResource } from 'libs/user-profile-shared/test/user-pr import { UserProfileNameComponent } from './user-profile-name.component'; describe('UserProfileNameComponent', () => { - let component: UserProfileNameComponent; - let fixture: ComponentFixture<UserProfileNameComponent>; + let component: UserProfileNameComponent; + let fixture: ComponentFixture<UserProfileNameComponent>; - const userProfileName: string = getDataTestClassOf('user-profile-name'); - const userProfileNameUnknown: string = getDataTestClassOf('user-profile-name-unknown'); + const userProfileName: string = getDataTestClassOf('user-profile-name'); + const userProfileNameUnknown: string = getDataTestClassOf('user-profile-name-unknown'); - const userProfile: UserProfileResource = createUserProfileResource(); + const userProfile: UserProfileResource = createUserProfileResource(); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [UserProfileNameComponent], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UserProfileNameComponent], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileNameComponent); - component = fixture.componentInstance; - component.userProfileStateResource = createEmptyStateResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileNameComponent); + component = fixture.componentInstance; + component.userProfileStateResource = createEmptyStateResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('if user-profile exists', () => { + describe('if user-profile exists', () => { + beforeEach(() => { + component.userProfileStateResource = createStateResource(userProfile); + fixture.detectChanges(); + }); - beforeEach(() => { - component.userProfileStateResource = createStateResource(userProfile); - fixture.detectChanges(); - }) + it('show user name', () => { + const element = fixture.nativeElement.querySelector(userProfileName); - it('show user name', () => { - const element = fixture.nativeElement.querySelector(userProfileName); + expect(element).toBeInstanceOf(HTMLElement); + }); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) - }) + describe('if user profile loading error', () => { + beforeEach(() => { + component.userProfileStateResource = createErrorStateResource(createApiError()); + fixture.detectChanges(); + }); - describe('if user profile loading error', () => { + it('should show "Unbekannter Benutzer" as userName', () => { + const element = fixture.nativeElement.querySelector(userProfileNameUnknown); - beforeEach(() => { - component.userProfileStateResource = createErrorStateResource(createApiError()); - fixture.detectChanges(); - }) - - it('should show "Unbekannter Benutzer" as userName', () => { - const element = fixture.nativeElement.querySelector(userProfileNameUnknown); - - expect(element).toBeInstanceOf(HTMLElement); - expect((<HTMLElement>element).innerHTML).toContain('Unbekannter Benutzer'); - }) - }) -}); \ No newline at end of file + expect(element).toBeInstanceOf(HTMLElement); + expect((<HTMLElement>element).innerHTML).toContain('Unbekannter Benutzer'); + }); + }); +}); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.ts index 58cddd63f308d631294ef86f1307764627ab4844..54c721c3ea568b318fef19a8daa59781e8205765 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-name/user-profile-name.component.ts @@ -26,18 +26,17 @@ import { StateResource } from '@alfa-client/tech-shared'; import { getUserName, UserProfileResource } from '@alfa-client/user-profile-shared'; @Component({ - selector: 'alfa-user-profile-name', - templateUrl: './user-profile-name.component.html', - styleUrls: ['./user-profile-name.component.scss'], + selector: 'alfa-user-profile-name', + templateUrl: './user-profile-name.component.html', + styleUrls: ['./user-profile-name.component.scss'], }) export class UserProfileNameComponent { + @Input('userProfileStateResource') + public set userProfile(userProfileStateResource: StateResource<UserProfileResource>) { + this.userProfileStateResource = userProfileStateResource; + this.userName = getUserName(userProfileStateResource.resource); + } - @Input('userProfileStateResource') - public set userProfile(userProfileStateResource: StateResource<UserProfileResource>) { - this.userProfileStateResource = userProfileStateResource; - this.userName = getUserName(userProfileStateResource.resource); - } - - userProfileStateResource: StateResource<UserProfileResource>; - userName: string; -} \ No newline at end of file + userProfileStateResource: StateResource<UserProfileResource>; + userName: string; +} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/_user-profile-search-container.theme.scss b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/_user-profile-search-container.theme.scss index 911539e2caf485a94f4b6af27e75479562a403e0..13b5656789180a0cb63a1934cf44637996b150c3 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/_user-profile-search-container.theme.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/_user-profile-search-container.theme.scss @@ -22,9 +22,9 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ alfa-user-profile-search-container .search-overlay { - background-color: #fff; + background-color: #fff; } body.dark alfa-user-profile-search-container .search-overlay { - background-color: #424242; + background-color: #424242; } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.html index 70231b9db45155b351976b630f2d2a6240a69375..2bb8917b970e2d321c079d86380827b3b579da74 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.html @@ -24,17 +24,17 @@ --> <div *ngIf="assignTo$ | async as assignTo" class="container"> - - <ozgcloud-spinner [stateResource]="assignTo" - diameter="30" class="spinner"> - </ozgcloud-spinner> - - <div *ngIf="assignedToName" class="search-overlay">{{assignedToName}}</div> - - <alfa-user-profile-search data-test-id="user-profile-search" - class="user-profile-search" - [searchedUserProfiles]="searchedUserProfiles$ | async" - (assignTo)="assign($event)"> - </alfa-user-profile-search> - + <ozgcloud-spinner [stateResource]="assignTo" diameter="30" class="spinner"> </ozgcloud-spinner> + + <div *ngIf="assignedToName" class="search-overlay"> + {{ assignedToName }} + </div> + + <alfa-user-profile-search + data-test-id="user-profile-search" + class="user-profile-search" + [searchedUserProfiles]="searchedUserProfiles$ | async" + (assignTo)="assign($event)" + > + </alfa-user-profile-search> </div> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.scss b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.scss index 531535a65aa85814de742d6305b89a0d62682b25..c4d9dee8908bdc381f06254d718b838f2dcd0e2a 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.scss @@ -22,29 +22,29 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - padding: 8px 16px; - display: block; - background-color: inherit; + padding: 8px 16px; + display: block; + background-color: inherit; } .container { - position: relative; + position: relative; } .spinner { - position: absolute; - right: -5px; - top: -3px; - z-index: 2; + position: absolute; + right: -5px; + top: -3px; + z-index: 2; } .search-overlay { - position: absolute; - top: 12px; - left: 2px; - right: 2px; - bottom: 30px; - z-index: 1; - pointer-events: none; - padding: 10px 8px; + position: absolute; + top: 12px; + left: 2px; + right: 2px; + bottom: 30px; + z-index: 1; + pointer-events: none; + padding: 10px 8px; } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.spec.ts index 2e03e2d038b84edeca2de043aea2068887d28ce5..0d75810cf07c464460abfd629e04dd7e1cbb3567 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.spec.ts @@ -37,50 +37,55 @@ import { UserProfileSearchComponent } from './user-profile-search/user-profile-s import { UserProfileSearchFormService } from './user-profile-search/user-profile.search.formservice'; describe('UserProfileSearchContainerComponent', () => { - let component: UserProfileSearchContainerComponent; - let fixture: ComponentFixture<UserProfileSearchContainerComponent>; + let component: UserProfileSearchContainerComponent; + let fixture: ComponentFixture<UserProfileSearchContainerComponent>; - const userProfileSearchFormService = mock(UserProfileSearchFormService); + const userProfileSearchFormService = mock(UserProfileSearchFormService); - const userProfileListResource: UserProfileListResource = createUserProfileListResource(); - const userProfileService = { ...mock(UserProfileService), getSearchedUserProfiles: () => of(userProfileListResource) }; + const userProfileListResource: UserProfileListResource = createUserProfileListResource(); + const userProfileService = { + ...mock(UserProfileService), + getSearchedUserProfiles: () => of(userProfileListResource), + }; - const vorgangService = mock(VorgangService); + const vorgangService = mock(VorgangService); - beforeEach(async () => { - TestBed.configureTestingModule({ - declarations: [ - UserProfileSearchContainerComponent, - MockComponent(SpinnerComponent), - MockComponent(UserProfileSearchComponent) - ], - providers: [ - UntypedFormBuilder, - { - provide: UserProfileSearchFormService, - useValue: userProfileSearchFormService - }, - { - provide: UserProfileService, - useValue: userProfileService - }, - { - provide: VorgangService, - useValue: vorgangService - } - ] - }) + beforeEach(async () => { + TestBed.configureTestingModule({ + declarations: [ + UserProfileSearchContainerComponent, + MockComponent(SpinnerComponent), + MockComponent(UserProfileSearchComponent), + ], + providers: [ + UntypedFormBuilder, + { + provide: UserProfileSearchFormService, + useValue: userProfileSearchFormService, + }, + { + provide: UserProfileService, + useValue: userProfileService, + }, + { + provide: VorgangService, + useValue: vorgangService, + }, + ], + }); - vorgangService.getAssignUserCommand.mockReturnValue(of(createStateResource(createCommandResource()))); - }) + vorgangService.getAssignUserCommand.mockReturnValue( + of(createStateResource(createCommandResource())), + ); + }); - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileSearchContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileSearchContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.ts index 3d7b8d1d0d61323ac449c70a548ddf4b0647433b..1c7f0c130b4566dbf2aa552bf3d4064b708ad608 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search-container.component.ts @@ -23,59 +23,86 @@ */ import { Component, EventEmitter, Output } from '@angular/core'; import { CommandResource, isDone } from '@alfa-client/command-shared'; -import { StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Selectable } from '@alfa-client/ui'; -import { UserProfileListLinkRel, UserProfileListResource, UserProfileResource, UserProfileService } from '@alfa-client/user-profile-shared'; +import { + UserProfileListLinkRel, + UserProfileListResource, + UserProfileResource, + UserProfileService, +} from '@alfa-client/user-profile-shared'; import { VorgangService } from '@alfa-client/vorgang-shared'; import { getEmbeddedResource, getUrl } from '@ngxp/rest'; import { Observable, of } from 'rxjs'; import { map, tap } from 'rxjs/operators'; @Component({ - selector: 'alfa-user-profile-search-container', - templateUrl: './user-profile-search-container.component.html', - styleUrls: ['./user-profile-search-container.component.scss'] + selector: 'alfa-user-profile-search-container', + templateUrl: './user-profile-search-container.component.html', + styleUrls: ['./user-profile-search-container.component.scss'], }) export class UserProfileSearchContainerComponent { + @Output() assigned: EventEmitter<void> = new EventEmitter(); - @Output() assigned: EventEmitter<void> = new EventEmitter(); + readonly EMPTY_LIST = []; - readonly EMPTY_LIST = []; + assignTo$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); + searchedUserProfiles$: Observable<StateResource<Selectable[]>> = of( + createStateResource<Selectable[]>([]), + ); - assignTo$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); - searchedUserProfiles$: Observable<StateResource<Selectable[]>> = of(createStateResource<Selectable[]>([])); + assignedToName: string = ''; - assignedToName: string = ''; + constructor( + private vorgangService: VorgangService, + private service: UserProfileService, + ) { + //TODO Das Parsen im Service machen bzw. mit NGRX ueber einen Selector + this.searchedUserProfiles$ = this.getSearchUserProfiles(); + } - constructor(private vorgangService: VorgangService, private service: UserProfileService) { - //TODO Das Parsen im Service machen bzw. mit NGRX ueber einen Selector - this.searchedUserProfiles$ = this.getSearchUserProfiles(); - } + private getSearchUserProfiles(): Observable<StateResource<Selectable[]>> { + return this.service.getSearchedUserProfiles().pipe( + map((userProfileListStateResource) => { + if (userProfileListStateResource.loaded) { + return createStateResource( + this.parseToSelectables(userProfileListStateResource.resource), + ); + } + return { ...userProfileListStateResource, resource: this.EMPTY_LIST }; + }), + ); + } - private getSearchUserProfiles(): Observable<StateResource<Selectable[]>> { - return this.service.getSearchedUserProfiles().pipe(map(userProfileListStateResource => { - if (userProfileListStateResource.loaded) { - return createStateResource(this.parseToSelectables(userProfileListStateResource.resource)); - } - return { ...userProfileListStateResource, resource: this.EMPTY_LIST }; - })); - } + parseToSelectables(userProfileListResource: UserProfileListResource): Selectable[] { + const resources: UserProfileResource[] = getEmbeddedResource( + userProfileListResource, + UserProfileListLinkRel.USER_PROFILE_LIST, + ); + return resources ? resources.map((userProfile) => this.parseToSelectable(userProfile)) : []; + } - parseToSelectables(userProfileListResource: UserProfileListResource): Selectable[] { - const resources: UserProfileResource[] = getEmbeddedResource(userProfileListResource, UserProfileListLinkRel.USER_PROFILE_LIST); - return resources ? resources.map(userProfile => this.parseToSelectable(userProfile)) : []; - } + parseToSelectable(userProfile: UserProfileResource) { + return <Selectable>{ + label: userProfile.firstName + ' ' + userProfile.lastName, + value: getUrl(userProfile), + }; + } - parseToSelectable(userProfile: UserProfileResource) { - return <Selectable>{ label: userProfile.firstName + ' ' + userProfile.lastName, value: getUrl(userProfile) }; - } - - public assign(userProfile: Selectable): void { - this.assignedToName = userProfile.label; - this.assignTo$ = this.vorgangService.assignUser(userProfile.value).pipe(tap((commandStateResource: StateResource<CommandResource>) => { - if (isDone(commandStateResource.resource)) { - this.assigned.emit(); - } - })); - } + public assign(userProfile: Selectable): void { + this.assignedToName = userProfile.label; + this.assignTo$ = this.vorgangService.assignUser(userProfile.value).pipe( + tap((commandStateResource: StateResource<CommandResource>) => { + if (isDone(commandStateResource.resource)) { + this.assigned.emit(); + } + }), + ); + } } diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.html b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.html index d99f7f5502ac44267cb72fad6b8150160fce80b0..e88bfb77885c00c29ac5eb6955ca5a63d8f18211 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.html @@ -24,14 +24,14 @@ --> <form class="form" [formGroup]="form"> - - <ozgcloud-autocomplete-editor data-test-id="user-search" - label="Bearbeiter" - [formControlName]="formServiceClass.SEARCH_FIELD" - [values]="searchedUserProfiles.resource" - (onKeyUp)="onKeyUp()" - (onOptionSelected)="assign($event)" - (enterOnNoSelection)="setEmptySelectionError()"> - </ozgcloud-autocomplete-editor> - + <ozgcloud-autocomplete-editor + data-test-id="user-search" + label="Bearbeiter" + [formControlName]="formServiceClass.SEARCH_FIELD" + [values]="searchedUserProfiles.resource" + (onKeyUp)="onKeyUp()" + (onOptionSelected)="assign($event)" + (enterOnNoSelection)="setEmptySelectionError()" + > + </ozgcloud-autocomplete-editor> </form> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.spec.ts index 27a4ccb76852d230f3be06ca759f723bd392419f..5e81965cbfcb2844f00f25482cfe5e5f65cd0548 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.spec.ts @@ -33,44 +33,37 @@ import { UserProfileSearchComponent } from './user-profile-search.component'; import { UserProfileSearchFormService } from './user-profile.search.formservice'; describe('UserProfileSearchComponent', () => { - let component: UserProfileSearchComponent; - let fixture: ComponentFixture<UserProfileSearchComponent>; + let component: UserProfileSearchComponent; + let fixture: ComponentFixture<UserProfileSearchComponent>; - const userProfileSearchFormService = mock(UserProfileSearchFormService); - const userProfileService = mock(UserProfileService); + const userProfileSearchFormService = mock(UserProfileSearchFormService); + const userProfileService = mock(UserProfileService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserProfileSearchComponent, - MockComponent(AutocompleteEditorComponent) - ], - imports: [ - MatFormFieldModule, - ReactiveFormsModule, - BrowserAnimationsModule - ], - providers: [ - UntypedFormBuilder, - { - provide: UserProfileSearchFormService, - useValue: userProfileSearchFormService - }, - { - provide: UserProfileService, - useValue: userProfileService - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UserProfileSearchComponent, MockComponent(AutocompleteEditorComponent)], + imports: [MatFormFieldModule, ReactiveFormsModule, BrowserAnimationsModule], + providers: [ + UntypedFormBuilder, + { + provide: UserProfileSearchFormService, + useValue: userProfileSearchFormService, + }, + { + provide: UserProfileService, + useValue: userProfileService, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileSearchComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.ts index 546a69c4da193bd72ff74108f87cbb2031c01ef8..4a83981d0ca77af9c2063376d46372b9a003a8ab 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile-search.component.ts @@ -29,40 +29,39 @@ import { isNull } from 'lodash-es'; import { UserProfileSearchFormService } from './user-profile.search.formservice'; @Component({ - selector: 'alfa-user-profile-search', - templateUrl: './user-profile-search.component.html', - styleUrls: ['./user-profile-search.component.scss'], - providers: [UserProfileSearchFormService] + selector: 'alfa-user-profile-search', + templateUrl: './user-profile-search.component.html', + styleUrls: ['./user-profile-search.component.scss'], + providers: [UserProfileSearchFormService], }) export class UserProfileSearchComponent { + @Input() searchedUserProfiles: StateResource<Selectable[]> = createStateResource<Selectable[]>( + [], + ); - @Input() searchedUserProfiles: StateResource<Selectable[]> = createStateResource<Selectable[]>([]); + @Output() assignTo: EventEmitter<Selectable> = new EventEmitter(); - @Output() assignTo: EventEmitter<Selectable> = new EventEmitter(); + readonly formServiceClass = UserProfileSearchFormService; - readonly formServiceClass = UserProfileSearchFormService; + constructor(private formService: UserProfileSearchFormService) {} - constructor(private formService: UserProfileSearchFormService) { } + get form(): UntypedFormGroup { + return this.formService.form; + } - get form(): UntypedFormGroup { - return this.formService.form; - } + assign(userProfile: Selectable): void { + isNull(userProfile) ? this.setNoUserProfileFoundError() : this.assignTo.emit(userProfile); + } - assign(userProfile: Selectable): void { - isNull(userProfile) - ? this.setNoUserProfileFoundError() - : this.assignTo.emit(userProfile); - } + setEmptySelectionError(): void { + this.formService.setEmptyUserProfileError(); + } - setEmptySelectionError(): void { - this.formService.setEmptyUserProfileError(); - } + setNoUserProfileFoundError(): void { + this.formService.setNoUserProfileFoundError(); + } - setNoUserProfileFoundError(): void { - this.formService.setNoUserProfileFoundError(); - } - - onKeyUp(): void { - this.formService.submit(); - } -} \ No newline at end of file + onKeyUp(): void { + this.formService.submit(); + } +} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile.search.formservice.ts b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile.search.formservice.ts index c0217d0d9ea79be4ad9a81b11f5f42ada6cdf6b5..12d7f3fa7dfa380d681d263104350b32d7b382e0 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile.search.formservice.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile-search-container/user-profile-search/user-profile.search.formservice.ts @@ -21,56 +21,76 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Injectable, OnDestroy } from "@angular/core"; -import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from "@angular/forms"; -import { AbstractFormService, StateResource } from "@alfa-client/tech-shared"; -import { UserProfileListResource, UserProfileService } from "@alfa-client/user-profile-shared"; -import { isNil } from "lodash-es"; -import { Observable, Subscription } from "rxjs"; +import { Injectable, OnDestroy } from '@angular/core'; +import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { AbstractFormService, StateResource } from '@alfa-client/tech-shared'; +import { UserProfileListResource, UserProfileService } from '@alfa-client/user-profile-shared'; +import { isNil } from 'lodash-es'; +import { Observable, Subscription } from 'rxjs'; @Injectable() export class UserProfileSearchFormService extends AbstractFormService implements OnDestroy { + public static readonly SEARCH_FIELD = 'searchBy'; - public static readonly SEARCH_FIELD = 'searchBy'; + private FIELD_PATH: string = 'only.fe'; - private FIELD_PATH: string = 'only.fe'; + private valueSubscription: Subscription; - private valueSubscription: Subscription; + constructor( + formBuilder: UntypedFormBuilder, + private userProfileService: UserProfileService, + ) { + super(formBuilder); + } - constructor(formBuilder: UntypedFormBuilder, private userProfileService: UserProfileService) { - super(formBuilder); - } + protected initForm(): UntypedFormGroup { + return this.formBuilder.group({ + [UserProfileSearchFormService.SEARCH_FIELD]: new UntypedFormControl(), + }); + } - protected initForm(): UntypedFormGroup { - return this.formBuilder.group({ - [UserProfileSearchFormService.SEARCH_FIELD]: new UntypedFormControl() - }) - } + protected doSubmit(): Observable<StateResource<UserProfileListResource>> { + return this.userProfileService.search(this.getSearchString()); + } - protected doSubmit(): Observable<StateResource<UserProfileListResource>> { - return this.userProfileService.search(this.getSearchString()); - } + private getSearchString(): string { + return this.getFormValue()[UserProfileSearchFormService.SEARCH_FIELD]; + } - private getSearchString(): string { - return this.getFormValue()[UserProfileSearchFormService.SEARCH_FIELD]; - } + protected getPathPrefix(): string { + return this.FIELD_PATH; + } - protected getPathPrefix(): string { - return this.FIELD_PATH; - } + public setEmptyUserProfileError(): void { + this.setError(emptyUserProfileError); + } - public setEmptyUserProfileError(): void { - this.setError(emptyUserProfileError); - } + public setNoUserProfileFoundError(): void { + this.setError(noUserProfileFoundError); + } - public setNoUserProfileFoundError(): void { - this.setError(noUserProfileFoundError); - } - - ngOnDestroy(): void { - if (!isNil(this.valueSubscription)) this.valueSubscription.unsubscribe(); - } + ngOnDestroy(): void { + if (!isNil(this.valueSubscription)) this.valueSubscription.unsubscribe(); + } } -const noUserProfileFoundError = { issues: [{ field: 'only.fe.searchBy', message: 'fe_only_validation_bearbeiter_not_exist', messageCode: 'fe_only_validation_bearbeiter_not_exist', parameters: [] }] }; -const emptyUserProfileError = { issues: [{ field: 'only.fe.searchBy', message: 'validation_field_empty', messageCode: 'validation_field_empty', parameters: [] }] }; \ No newline at end of file +const noUserProfileFoundError = { + issues: [ + { + field: 'only.fe.searchBy', + message: 'fe_only_validation_bearbeiter_not_exist', + messageCode: 'fe_only_validation_bearbeiter_not_exist', + parameters: [], + }, + ], +}; +const emptyUserProfileError = { + issues: [ + { + field: 'only.fe.searchBy', + message: 'validation_field_empty', + messageCode: 'validation_field_empty', + parameters: [], + }, + ], +}; diff --git a/alfa-client/libs/user-profile/src/lib/user-profile.module.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile.module.spec.ts index 699593f0750cdfeaa2e9458c58c90d3f24e52135..20a8e0b7e9956a2fb10835099b0a7a9ed5fb81a0 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile.module.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { UserProfileModule } from './user-profile.module'; describe('UserProfileModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [UserProfileModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [UserProfileModule], + }).compileComponents(); + }); - it('should create', () => { - expect(UserProfileModule).toBeDefined(); - }); + it('should create', () => { + expect(UserProfileModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile.module.ts b/alfa-client/libs/user-profile/src/lib/user-profile.module.ts index ba57f98c98960b91e9b38cd2d0f702e0c2599624..fe2547f6551c42cbb2da5564357dddd5b6c56ae0 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile.module.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile.module.ts @@ -48,45 +48,39 @@ import { UserProfileSearchComponent } from './user-profile-search-container/user import { UserProfileComponent } from './user-profile/user-profile.component'; @NgModule({ - imports: [ - CommonModule, - TechSharedModule, - UiModule, - UserProfileSharedModule, - RouterModule, - ], - declarations: [ - UserIconComponent, - UserProfileInVorgangContainerComponent, - UserProfileSearchComponent, - UserProfileSearchContainerComponent, - AssignUserProfileButtonContainerComponent, - UserProfileInKommentarContainerComponent, - UserProfileInVorgangListItemContainerComponent, - UserProfileButtonContainerComponent, - UserProfileInPostfachMailContainerComponent, - UserProfileComponent, - UserProfileInVorgangComponent, - LinkWithUserNameTooltipContainerComponent, - LinkWithUserNameTooltipComponent, - TextWithUserNameTooltipContainerComponent, - TextWithUserNameTooltipComponent, - UserProfileInHistorieContainerComponent, - UserProfileNameComponent, - UserProfileInHeaderContainerComponent, - UserProfileInHeaderComponent, - ], - exports: [ - UserProfileInVorgangContainerComponent, - UserIconComponent, - AssignUserProfileButtonContainerComponent, - UserProfileInKommentarContainerComponent, - UserProfileInVorgangListItemContainerComponent, - UserProfileInPostfachMailContainerComponent, - LinkWithUserNameTooltipContainerComponent, - TextWithUserNameTooltipContainerComponent, - UserProfileInHistorieContainerComponent, - UserProfileInHeaderContainerComponent, - ], + imports: [CommonModule, TechSharedModule, UiModule, UserProfileSharedModule, RouterModule], + declarations: [ + UserIconComponent, + UserProfileInVorgangContainerComponent, + UserProfileSearchComponent, + UserProfileSearchContainerComponent, + AssignUserProfileButtonContainerComponent, + UserProfileInKommentarContainerComponent, + UserProfileInVorgangListItemContainerComponent, + UserProfileButtonContainerComponent, + UserProfileInPostfachMailContainerComponent, + UserProfileComponent, + UserProfileInVorgangComponent, + LinkWithUserNameTooltipContainerComponent, + LinkWithUserNameTooltipComponent, + TextWithUserNameTooltipContainerComponent, + TextWithUserNameTooltipComponent, + UserProfileInHistorieContainerComponent, + UserProfileNameComponent, + UserProfileInHeaderContainerComponent, + UserProfileInHeaderComponent, + ], + exports: [ + UserProfileInVorgangContainerComponent, + UserIconComponent, + AssignUserProfileButtonContainerComponent, + UserProfileInKommentarContainerComponent, + UserProfileInVorgangListItemContainerComponent, + UserProfileInPostfachMailContainerComponent, + LinkWithUserNameTooltipContainerComponent, + TextWithUserNameTooltipContainerComponent, + UserProfileInHistorieContainerComponent, + UserProfileInHeaderContainerComponent, + ], }) -export class UserProfileModule { } +export class UserProfileModule {} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.html b/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.html index f81f311d268cf62088da6321f26b601bea1f5012..314fba7b28bf6306a974d1d342047d04f57e1e0c 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.html +++ b/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.html @@ -23,5 +23,12 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-user-icon class="icon" [userProfileStateResource]="userProfileStateResource" data-test-id="user-profile-icon"></alfa-user-icon> -<alfa-user-profile-name class="username" [userProfileStateResource]="userProfileStateResource"></alfa-user-profile-name> \ No newline at end of file +<alfa-user-icon + class="icon" + [userProfileStateResource]="userProfileStateResource" + data-test-id="user-profile-icon" +></alfa-user-icon> +<alfa-user-profile-name + class="username" + [userProfileStateResource]="userProfileStateResource" +></alfa-user-profile-name> diff --git a/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.scss b/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.scss index 0996ad879ea883f155686fd59899f1a2acc598d3..ebe60997a4a7c8cd0b4ba25751d6f85ef7be661e 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.scss +++ b/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.scss @@ -33,4 +33,4 @@ .username { flex-shrink: 1; -} \ No newline at end of file +} diff --git a/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.spec.ts b/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.spec.ts index d3f2d6be34b4b2c77785bb97a7259c212234bf9c..f1486bf023f194c5f1c4244da8c3a1b9068484df 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.spec.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.spec.ts @@ -28,27 +28,26 @@ import { UserProfileNameComponent } from '../user-profile-name/user-profile-name import { UserProfileComponent } from './user-profile.component'; describe('UserProfileComponent', () => { - let component: UserProfileComponent; - let fixture: ComponentFixture<UserProfileComponent>; + let component: UserProfileComponent; + let fixture: ComponentFixture<UserProfileComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserProfileComponent, - MockComponent(UserIconComponent), - MockComponent(UserProfileNameComponent) - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserProfileComponent, + MockComponent(UserIconComponent), + MockComponent(UserProfileNameComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(UserProfileComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserProfileComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.ts b/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.ts index d7f0b81c47dfd0125121f609310035c06e55e31e..ca99c44d80be25b43ad768aeab7f478e36103da1 100644 --- a/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.ts +++ b/alfa-client/libs/user-profile/src/lib/user-profile/user-profile.component.ts @@ -26,11 +26,10 @@ import { StateResource } from '@alfa-client/tech-shared'; import { UserProfileResource } from '@alfa-client/user-profile-shared'; @Component({ - selector: 'alfa-user-profile', - templateUrl: './user-profile.component.html', - styleUrls: ['./user-profile.component.scss'] + selector: 'alfa-user-profile', + templateUrl: './user-profile.component.html', + styleUrls: ['./user-profile.component.scss'], }) export class UserProfileComponent { - - @Input() userProfileStateResource: StateResource<UserProfileResource>; + @Input() userProfileStateResource: StateResource<UserProfileResource>; } diff --git a/alfa-client/libs/user-profile/src/test-setup.ts b/alfa-client/libs/user-profile/src/test-setup.ts index 5870fdabb6470fd0f6f3f63be3d4f6b8041b4dd2..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/user-profile/src/test-setup.ts +++ b/alfa-client/libs/user-profile/src/test-setup.ts @@ -26,17 +26,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/user-profile/tsconfig.json b/alfa-client/libs/user-profile/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/user-profile/tsconfig.json +++ b/alfa-client/libs/user-profile/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/user-profile/tsconfig.lib.json b/alfa-client/libs/user-profile/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/user-profile/tsconfig.lib.json +++ b/alfa-client/libs/user-profile/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/user-profile/tsconfig.spec.json b/alfa-client/libs/user-profile/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/user-profile/tsconfig.spec.json +++ b/alfa-client/libs/user-profile/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/user-settings-shared/.eslintrc.json b/alfa-client/libs/user-settings-shared/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/user-settings-shared/.eslintrc.json +++ b/alfa-client/libs/user-settings-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/user-settings-shared/jest.config.ts b/alfa-client/libs/user-settings-shared/jest.config.ts index c40371e9dc68a2f7a2ed4dc0855f2a7425327ee5..858a398bbb0fb7f204ea26a937f4acdfec18b5c3 100644 --- a/alfa-client/libs/user-settings-shared/jest.config.ts +++ b/alfa-client/libs/user-settings-shared/jest.config.ts @@ -24,24 +24,24 @@ */ /* eslint-disable */ export default { - displayName: 'user-settings-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/user-settings-shared', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'user-settings-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/user-settings-shared', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/user-settings-shared/project.json b/alfa-client/libs/user-settings-shared/project.json index 4dea715b014f69816b9f06da18e7e84a810eca88..fc5d9b9a720af796e6c4bccb0a84fc590b122d72 100644 --- a/alfa-client/libs/user-settings-shared/project.json +++ b/alfa-client/libs/user-settings-shared/project.json @@ -1,28 +1,28 @@ { - "name": "user-settings-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/user-settings-shared/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/user-settings-shared"], - "options": { - "tsConfig": "libs/user-settings-shared/tsconfig.spec.json", - "jestConfig": "libs/user-settings-shared/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/user-settings-shared/**/*.ts", - "libs/user-settings-shared/**/*.html" - ] - } - } - }, - "tags": [] + "name": "user-settings-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/user-settings-shared/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/user-settings-shared"], + "options": { + "tsConfig": "libs/user-settings-shared/tsconfig.spec.json", + "jestConfig": "libs/user-settings-shared/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/user-settings-shared/**/*.ts", + "libs/user-settings-shared/**/*.html" + ] + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/user-settings-shared/src/index.ts b/alfa-client/libs/user-settings-shared/src/index.ts index c0c2ccfb3fb93f336ad312757a07b3f83d4aac8a..eaddff3023e818f059fdb1c33ee13ce0436f988f 100644 --- a/alfa-client/libs/user-settings-shared/src/index.ts +++ b/alfa-client/libs/user-settings-shared/src/index.ts @@ -30,4 +30,3 @@ export * from './lib/user-settings-shared.module'; export * from './lib/user-settings.linkrel'; export * from './lib/user-settings.model'; export * from './lib/user-settings.service'; - diff --git a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.actions.ts b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.actions.ts index 5dc4be9cf08ba4babd1bc5fec8fc2c1fdff84f0c..22406c1bac4d9c375e13dfca6681273d7f389fbd 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.actions.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.actions.ts @@ -27,47 +27,49 @@ import { createAction, props } from '@ngrx/store'; import { UserSettings, UserSettingsResource } from '../user-settings.model'; export interface UserProfileAction { - currentUser: UserProfileResource + currentUser: UserProfileResource; } export interface LoadedUserSettingsAction { - userSettings: UserSettingsResource + userSettings: UserSettingsResource; } export interface SetUserSettingsAction { - userSettings: UserSettings + userSettings: UserSettings; } export interface ApiErrorAction { - apiError: ApiError + apiError: ApiError; } export const loadUserSettings: TypedActionCreatorWithProps<UserProfileAction> = createAction( - '[UserSettings] Load UserSettings', - props<{ currentUser: UserProfileResource }>() + '[UserSettings] Load UserSettings', + props<{ currentUser: UserProfileResource }>(), ); -export const loadUserSettingsSuccess: TypedActionCreatorWithProps<LoadedUserSettingsAction> = createAction( - '[UserSettings/API] Load UserSettings Success', - props<{ userSettings: UserSettingsResource }>() -); +export const loadUserSettingsSuccess: TypedActionCreatorWithProps<LoadedUserSettingsAction> = + createAction( + '[UserSettings/API] Load UserSettings Success', + props<{ userSettings: UserSettingsResource }>(), + ); export const loadUserSettingsFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction( - '[UserSettings/API] Load UserSettings Failure', - props<ApiErrorAction>() + '[UserSettings/API] Load UserSettings Failure', + props<ApiErrorAction>(), ); export const setUserSettings: TypedActionCreatorWithProps<SetUserSettingsAction> = createAction( - '[UserSettings] Set UserSettings', - props<{ userSettings: UserSettings }>() + '[UserSettings] Set UserSettings', + props<{ userSettings: UserSettings }>(), ); -export const setUserSettingsSuccess: TypedActionCreatorWithProps<LoadedUserSettingsAction> = createAction( - '[UserSettings/API] Set UserSettings Success', - props<{ userSettings: UserSettingsResource }>() -); +export const setUserSettingsSuccess: TypedActionCreatorWithProps<LoadedUserSettingsAction> = + createAction( + '[UserSettings/API] Set UserSettings Success', + props<{ userSettings: UserSettingsResource }>(), + ); export const setUserSettingsFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction( - '[UserSettings/API] Set UserSettings Failure', - props<ApiErrorAction>() + '[UserSettings/API] Set UserSettings Failure', + props<ApiErrorAction>(), ); diff --git a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.effects.spec.ts b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.effects.spec.ts index e7491ba2e04f660bbf711e614baccfe1616e7830..94b56084be0e18d1b54c5b191e67cd37556e89aa 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.effects.spec.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.effects.spec.ts @@ -31,7 +31,10 @@ import { provideMockStore } from '@ngrx/store/testing'; import { cold, hot } from 'jest-marbles'; import { createApiError } from 'libs/tech-shared/test/error'; import { createUserProfileResource } from 'libs/user-profile-shared/test/user-profile'; -import { createUserSettings, createUserSettingsResource } from 'libs/user-settings-shared/test/user-settings'; +import { + createUserSettings, + createUserSettingsResource, +} from 'libs/user-settings-shared/test/user-settings'; import { Observable, of } from 'rxjs'; import { UserSettings, UserSettingsResource } from '../user-settings.model'; import { UserSettingsRepository } from '../user-settings.repository'; @@ -40,105 +43,115 @@ import { UserSettingsEffects } from './user-settings.effects'; import { UserSettingsFacade } from './user-settings.facade'; describe('UserSettingsEffects', () => { - let actions: Observable<Action>; - let effects: UserSettingsEffects; - - const userSettingsFacade: Mock<UserSettingsFacade> = mock(UserSettingsFacade); - const userSettingsRepository: Mock<UserSettingsRepository> = mock(UserSettingsRepository); - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - UserSettingsEffects, - provideMockActions(() => actions), - provideMockStore(), - { - provide: UserSettingsRepository, - useValue: userSettingsRepository - }, - { - provide: UserSettingsFacade, - useValue: userSettingsFacade - } - ], - }); - - effects = TestBed.inject(UserSettingsEffects); - }); - - describe('loadUserSettings', () => { - const currentUser: UserProfileResource = createUserProfileResource(); - const action = UserSettingsActions.loadUserSettings({ currentUser }); - const userSettings: UserSettingsResource = createUserSettingsResource(); - - it('should call repository', () => { - actions = of(action); - - effects.loadUserSettings$.subscribe(); - - expect(userSettingsRepository.getUserSettings).toHaveBeenCalledWith(currentUser); - }) - - it('should dispatch success action', () => { - userSettingsRepository.getUserSettings.mockReturnValue(of(userSettings)); - - actions = hot('-a', { a: action }); - - const expected = cold('-b', { b: UserSettingsActions.loadUserSettingsSuccess({ userSettings }) }); - expect(effects.loadUserSettings$).toBeObservable(expected); - }) - - it('should dispatch error action', () => { - const apiError: ApiError = createApiError() - const error = { error: { error: apiError } }; - const errorResponse = cold('-#', {}, error); - userSettingsRepository.getUserSettings = jest.fn(() => errorResponse); - - const expected = cold('--b', { b: UserSettingsActions.loadUserSettingsFailure({ apiError }) }); - actions = hot('-a', { a: action }); - - expect(effects.loadUserSettings$).toBeObservable(expected); - }) - }) - - describe('set user settings', () => { - - const userSettingsResource: UserSettingsResource = createUserSettingsResource(); - const userSettings: UserSettings = createUserSettings(); - const action = UserSettingsActions.setUserSettings({ userSettings }); - - beforeEach(() => { - userSettingsFacade.getUserSettings.mockReturnValue(of(createStateResource(userSettingsResource))); - userSettingsRepository.setUserSettings.mockReturnValue(of(userSettingsResource)); - }) - - it('should call repository', () => { - actions = of(action); - - effects.setUserSettings$.subscribe(); - - expect(userSettingsRepository.setUserSettings).toHaveBeenCalledWith(userSettingsResource, userSettings); - }) - - it('should dispatch success action', () => { - userSettingsRepository.setUserSettings.mockReturnValue(of(userSettingsResource)); - - actions = hot('-a-|', { a: action }); - - const expected = cold('-a-|', { a: UserSettingsActions.setUserSettingsSuccess({ userSettings: userSettingsResource }) }); - expect(effects.setUserSettings$).toBeObservable(expected); - }) - - it('should dispatch error action', () => { - const apiError: ApiError = createApiError() - const error = { error: { error: apiError } }; - const errorResponse = cold('-#', {}, error); - userSettingsRepository.setUserSettings = jest.fn(() => errorResponse); - - const expected = cold('--b', { b: UserSettingsActions.setUserSettingsFailure({ apiError }) }); - actions = hot('-a', { a: action }); - - expect(effects.setUserSettings$).toBeObservable(expected); - }) - }) + let actions: Observable<Action>; + let effects: UserSettingsEffects; + + const userSettingsFacade: Mock<UserSettingsFacade> = mock(UserSettingsFacade); + const userSettingsRepository: Mock<UserSettingsRepository> = mock(UserSettingsRepository); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + UserSettingsEffects, + provideMockActions(() => actions), + provideMockStore(), + { + provide: UserSettingsRepository, + useValue: userSettingsRepository, + }, + { + provide: UserSettingsFacade, + useValue: userSettingsFacade, + }, + ], + }); + + effects = TestBed.inject(UserSettingsEffects); + }); + + describe('loadUserSettings', () => { + const currentUser: UserProfileResource = createUserProfileResource(); + const action = UserSettingsActions.loadUserSettings({ currentUser }); + const userSettings: UserSettingsResource = createUserSettingsResource(); + + it('should call repository', () => { + actions = of(action); + + effects.loadUserSettings$.subscribe(); + + expect(userSettingsRepository.getUserSettings).toHaveBeenCalledWith(currentUser); + }); + + it('should dispatch success action', () => { + userSettingsRepository.getUserSettings.mockReturnValue(of(userSettings)); + + actions = hot('-a', { a: action }); + + const expected = cold('-b', { + b: UserSettingsActions.loadUserSettingsSuccess({ userSettings }), + }); + expect(effects.loadUserSettings$).toBeObservable(expected); + }); + + it('should dispatch error action', () => { + const apiError: ApiError = createApiError(); + const error = { error: { error: apiError } }; + const errorResponse = cold('-#', {}, error); + userSettingsRepository.getUserSettings = jest.fn(() => errorResponse); + + const expected = cold('--b', { + b: UserSettingsActions.loadUserSettingsFailure({ apiError }), + }); + actions = hot('-a', { a: action }); + + expect(effects.loadUserSettings$).toBeObservable(expected); + }); + }); + + describe('set user settings', () => { + const userSettingsResource: UserSettingsResource = createUserSettingsResource(); + const userSettings: UserSettings = createUserSettings(); + const action = UserSettingsActions.setUserSettings({ userSettings }); + + beforeEach(() => { + userSettingsFacade.getUserSettings.mockReturnValue( + of(createStateResource(userSettingsResource)), + ); + userSettingsRepository.setUserSettings.mockReturnValue(of(userSettingsResource)); + }); + + it('should call repository', () => { + actions = of(action); + + effects.setUserSettings$.subscribe(); + + expect(userSettingsRepository.setUserSettings).toHaveBeenCalledWith( + userSettingsResource, + userSettings, + ); + }); + + it('should dispatch success action', () => { + userSettingsRepository.setUserSettings.mockReturnValue(of(userSettingsResource)); + + actions = hot('-a-|', { a: action }); + + const expected = cold('-a-|', { + a: UserSettingsActions.setUserSettingsSuccess({ userSettings: userSettingsResource }), + }); + expect(effects.setUserSettings$).toBeObservable(expected); + }); + + it('should dispatch error action', () => { + const apiError: ApiError = createApiError(); + const error = { error: { error: apiError } }; + const errorResponse = cold('-#', {}, error); + userSettingsRepository.setUserSettings = jest.fn(() => errorResponse); + + const expected = cold('--b', { b: UserSettingsActions.setUserSettingsFailure({ apiError }) }); + actions = hot('-a', { a: action }); + + expect(effects.setUserSettings$).toBeObservable(expected); + }); + }); }); diff --git a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.effects.ts b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.effects.ts index a3902f5a1567fa077150d00e0a30463737ba5100..604bdd307c52631ef40a60205e5eaf95606eddcc 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.effects.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.effects.ts @@ -32,31 +32,46 @@ import { UserSettingsFacade } from './user-settings.facade'; @Injectable() export class UserSettingsEffects { + constructor( + private readonly actions$: Actions, + private readonly repository: UserSettingsRepository, + private readonly userSettingsFacade: UserSettingsFacade, + ) {} - constructor( - private readonly actions$: Actions, - private readonly repository: UserSettingsRepository, - private readonly userSettingsFacade: UserSettingsFacade - ) { } + loadUserSettings$ = createEffect(() => + this.actions$.pipe( + ofType(UserSettingsActions.loadUserSettings), + switchMap((action) => + this.repository.getUserSettings(action.currentUser).pipe( + map((userSettings) => UserSettingsActions.loadUserSettingsSuccess({ userSettings })), + catchError((error) => + of( + UserSettingsActions.loadUserSettingsFailure({ + apiError: getApiErrorFromHttpErrorResponse(error), + }), + ), + ), + ), + ), + ), + ); - loadUserSettings$ = createEffect(() => - this.actions$.pipe( - ofType(UserSettingsActions.loadUserSettings), - switchMap((action) => this.repository.getUserSettings(action.currentUser).pipe( - map(userSettings => UserSettingsActions.loadUserSettingsSuccess({ userSettings })), - catchError(error => of(UserSettingsActions.loadUserSettingsFailure({ apiError: getApiErrorFromHttpErrorResponse(error) }))) - )) - ) - ) - - setUserSettings$ = createEffect(() => - this.actions$.pipe( - ofType(UserSettingsActions.setUserSettings), - concatLatestFrom(() => this.userSettingsFacade.getUserSettings()), - switchMap(([action, userSettingsResource]) => this.repository.setUserSettings(userSettingsResource.resource, action.userSettings).pipe( - map(userSettings => UserSettingsActions.setUserSettingsSuccess({ userSettings })), - catchError(error => of(UserSettingsActions.setUserSettingsFailure({ apiError: getApiErrorFromHttpErrorResponse(error) }))) - )) - ) - ) -} \ No newline at end of file + setUserSettings$ = createEffect(() => + this.actions$.pipe( + ofType(UserSettingsActions.setUserSettings), + concatLatestFrom(() => this.userSettingsFacade.getUserSettings()), + switchMap(([action, userSettingsResource]) => + this.repository.setUserSettings(userSettingsResource.resource, action.userSettings).pipe( + map((userSettings) => UserSettingsActions.setUserSettingsSuccess({ userSettings })), + catchError((error) => + of( + UserSettingsActions.setUserSettingsFailure({ + apiError: getApiErrorFromHttpErrorResponse(error), + }), + ), + ), + ), + ), + ), + ); +} diff --git a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.facade.spec.ts b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.facade.spec.ts index dd53d35324201495f5a183c56cfec7c49d11107b..e39ebb6ddc3b3f8b2b5bcb9d848825825a4bebba 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.facade.spec.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.facade.spec.ts @@ -26,55 +26,63 @@ import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { UserProfileResource } from '@alfa-client/user-profile-shared'; import { Store } from '@ngrx/store'; import { createUserProfileResource } from 'libs/user-profile-shared/test/user-profile'; -import { createUserSettings, createUserSettingsResource } from 'libs/user-settings-shared/test/user-settings'; +import { + createUserSettings, + createUserSettingsResource, +} from 'libs/user-settings-shared/test/user-settings'; import { Subject } from 'rxjs'; import { UserSettings, UserSettingsResource } from '../user-settings.model'; import * as UserSettingsActions from './user-settings.actions'; import { UserSettingsFacade } from './user-settings.facade'; - describe('UserSettingsFacade', () => { - const store: Mock<Store> = mock(Store); - let facade: UserSettingsFacade; - let userSettingsSubj: Subject<StateResource<UserSettingsResource>>; + const store: Mock<Store> = mock(Store); + let facade: UserSettingsFacade; + let userSettingsSubj: Subject<StateResource<UserSettingsResource>>; - beforeEach(() => { - userSettingsSubj = new Subject(); - store.select.mockReturnValue(userSettingsSubj); + beforeEach(() => { + userSettingsSubj = new Subject(); + store.select.mockReturnValue(userSettingsSubj); - facade = new UserSettingsFacade(useFromMock(store)); - }); + facade = new UserSettingsFacade(useFromMock(store)); + }); - describe('loadUserSettings', () => { - it('should dispatch "loadUserSettings"', () => { - const currentUser: UserProfileResource = createUserProfileResource(); + describe('loadUserSettings', () => { + it('should dispatch "loadUserSettings"', () => { + const currentUser: UserProfileResource = createUserProfileResource(); - facade.loadUserSettings(currentUser); + facade.loadUserSettings(currentUser); - expect(store.dispatch).toHaveBeenCalledWith(UserSettingsActions.loadUserSettings({ currentUser })) - }) - }) + expect(store.dispatch).toHaveBeenCalledWith( + UserSettingsActions.loadUserSettings({ currentUser }), + ); + }); + }); - describe('getUserSettings', () => { - it('should return selected value', (done) => { - const expected: StateResource<UserSettingsResource> = createStateResource(createUserSettingsResource()); + describe('getUserSettings', () => { + it('should return selected value', (done) => { + const expected: StateResource<UserSettingsResource> = createStateResource( + createUserSettingsResource(), + ); - facade.getUserSettings().subscribe(userSettings => { - expect(userSettings).toBe(expected); - done(); - }); + facade.getUserSettings().subscribe((userSettings) => { + expect(userSettings).toBe(expected); + done(); + }); - userSettingsSubj.next(expected); - }) - }) + userSettingsSubj.next(expected); + }); + }); - describe('setUserSettings', () => { - it('should dispatch "setUserSettings"', () => { - const userSettings: UserSettings = createUserSettings(); + describe('setUserSettings', () => { + it('should dispatch "setUserSettings"', () => { + const userSettings: UserSettings = createUserSettings(); - facade.setUserSettings(userSettings); + facade.setUserSettings(userSettings); - expect(store.dispatch).toHaveBeenCalledWith(UserSettingsActions.setUserSettings({ userSettings })); - }) - }) + expect(store.dispatch).toHaveBeenCalledWith( + UserSettingsActions.setUserSettings({ userSettings }), + ); + }); + }); }); diff --git a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.facade.ts b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.facade.ts index 45e83e8fd280b6e6e6acfb0ef95d792e57e935a7..df28dcd911595fbdb12f7dbcd440acaa90f394ee 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.facade.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.facade.ts @@ -32,18 +32,17 @@ import * as UserSettingsSelectors from './user-settings.selectors'; @Injectable() export class UserSettingsFacade { + constructor(private readonly store: Store) {} - constructor(private readonly store: Store) { } + public loadUserSettings(currentUser: UserProfileResource): void { + this.store.dispatch(UserSettingsAction.loadUserSettings({ currentUser })); + } - public loadUserSettings(currentUser: UserProfileResource): void { - this.store.dispatch(UserSettingsAction.loadUserSettings({ currentUser })); - } + public getUserSettings(): Observable<StateResource<UserSettingsResource>> { + return this.store.select(UserSettingsSelectors.userSettings); + } - public getUserSettings(): Observable<StateResource<UserSettingsResource>> { - return this.store.select(UserSettingsSelectors.userSettings) - } - - public setUserSettings(userSettings: UserSettings): void { - this.store.dispatch(UserSettingsAction.setUserSettings({ userSettings })) - } + public setUserSettings(userSettings: UserSettings): void { + this.store.dispatch(UserSettingsAction.setUserSettings({ userSettings })); + } } diff --git a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.models.ts b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.models.ts index 90ff3dccc9f6f747f4f22d674df76ab254d80132..29baf6a6f7ec3c54da209003d209173dcc932e82 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.models.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.models.ts @@ -25,6 +25,6 @@ * Interface for the 'UserSettings' data */ export interface UserSettingsEntity { - id: string | number; // Primary ID - name: string; + id: string | number; // Primary ID + name: string; } diff --git a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.reducer.spec.ts b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.reducer.spec.ts index 904797ca29a18349007101df00cf3a3ec8bf91df..d842b16be4c38296a9e7cabe319a04ec8c5239c7 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.reducer.spec.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.reducer.spec.ts @@ -24,100 +24,107 @@ import { ApiError, createStateResource } from '@alfa-client/tech-shared'; import { Action } from '@ngrx/store'; import { createUserProfileResource } from 'libs/user-profile-shared/test/user-profile'; -import { createUserSettings, createUserSettingsResource } from 'libs/user-settings-shared/test/user-settings'; +import { + createUserSettings, + createUserSettingsResource, +} from 'libs/user-settings-shared/test/user-settings'; import { createApiError } from '../../../../tech-shared/test/error'; import { UserSettingsResource } from '../user-settings.model'; import * as UserSettingsActions from './user-settings.actions'; -import { initialUserSettingsState, userSettingsReducer, UserSettingsState } from './user-settings.reducer'; +import { + initialUserSettingsState, + userSettingsReducer, + UserSettingsState, +} from './user-settings.reducer'; describe('User Settings Reducer', () => { + describe('unknown action', () => { + it('should return current state', () => { + const action: Action = {} as Action; - describe('unknown action', () => { + const result = userSettingsReducer(initialUserSettingsState, action); - it('should return current state', () => { - const action: Action = {} as Action; + expect(result).toBe(initialUserSettingsState); + }); + }); - const result = userSettingsReducer(initialUserSettingsState, action); + describe('loadUserSettings', () => { + describe('on "loadUserSettings" action', () => { + it('should set loading to true', () => { + const action: Action = UserSettingsActions.loadUserSettings({ + currentUser: createUserProfileResource(), + }); - expect(result).toBe(initialUserSettingsState); - }) - }) + const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); - describe('loadUserSettings', () => { - describe('on "loadUserSettings" action', () => { - it('should set loading to true', () => { - const action: Action = UserSettingsActions.loadUserSettings({ currentUser: createUserProfileResource() }); + expect(state.userSettings.loading).toBeTruthy(); + }); + }); + }); - const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); + describe('on "loadUserSettingsSuccess"', () => { + const userSettings: UserSettingsResource = createUserSettingsResource(); + const action: Action = UserSettingsActions.loadUserSettingsSuccess({ userSettings }); - expect(state.userSettings.loading).toBeTruthy(); - }) - }) - }) + it('should set loaded resource', () => { + const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); - describe('on "loadUserSettingsSuccess"', () => { - const userSettings: UserSettingsResource = createUserSettingsResource(); - const action: Action = UserSettingsActions.loadUserSettingsSuccess({ userSettings }); + expect(state.userSettings).toEqual(createStateResource(userSettings)); + }); - it('should set loaded resource', () => { - const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); + it('should has property "notificationsSendFor"', () => { + const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); - expect(state.userSettings).toEqual(createStateResource(userSettings)); - }) + expect(state.userSettings).toHaveProperty('resource.notificationsSendFor'); + }); + }); - it('should has property "notificationsSendFor"', () => { - const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); + describe('on "loadUserSettingsFailure"', () => { + it('should set apiError', () => { + const apiError: ApiError = createApiError(); + const action: Action = UserSettingsActions.loadUserSettingsFailure({ apiError }); - expect(state.userSettings).toHaveProperty('resource.notificationsSendFor'); - }) - }) + const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); - describe('on "loadUserSettingsFailure"', () => { - it('should set apiError', () => { - const apiError: ApiError = createApiError(); - const action: Action = UserSettingsActions.loadUserSettingsFailure({ apiError }); + expect(state.userSettings.error).toStrictEqual(apiError); + }); + }); - const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); + describe('setUserSettings', () => { + describe('on "setUserSettings" action', () => { + it('should set state resource to loading', () => { + const action: Action = UserSettingsActions.setUserSettings({ + userSettings: createUserSettings(), + }); - expect(state.userSettings.error).toStrictEqual(apiError); - }) - }) + const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); - describe('setUserSettings', () => { + expect(state.userSettings.loading).toBeTruthy(); + }); + }); - describe('on "setUserSettings" action', () => { + describe('on "setUserSettingsSuccess" action', () => { + const userSettingsResource: UserSettingsResource = createUserSettingsResource(); + const action: Action = UserSettingsActions.setUserSettingsSuccess({ + userSettings: userSettingsResource, + }); - it('should set state resource to loading', () => { - const action: Action = UserSettingsActions.setUserSettings({ userSettings: createUserSettings() }); + it('should set loaded resource', () => { + const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); - const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); + expect(state.userSettings).toEqual(createStateResource(userSettingsResource)); + }); + }); - expect(state.userSettings.loading).toBeTruthy(); - }) - }) + describe('on "setUserSettingsFailure" action', () => { + it('should set API Error', () => { + const apiError: ApiError = createApiError(); + const action: Action = UserSettingsActions.setUserSettingsFailure({ apiError }); - describe('on "setUserSettingsSuccess" action', () => { + const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); - const userSettingsResource: UserSettingsResource = createUserSettingsResource(); - const action: Action = UserSettingsActions.setUserSettingsSuccess({ userSettings: userSettingsResource }); - - it('should set loaded resource', () => { - const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); - - expect(state.userSettings).toEqual(createStateResource(userSettingsResource)); - }) - }) - - describe('on "setUserSettingsFailure" action', () => { - - it('should set API Error', () => { - const apiError: ApiError = createApiError(); - const action: Action = UserSettingsActions.setUserSettingsFailure({ apiError }); - - const state: UserSettingsState = userSettingsReducer(initialUserSettingsState, action); - - expect(state.userSettings.error).toStrictEqual(apiError); - }) - }) - }) -}) \ No newline at end of file + expect(state.userSettings.error).toStrictEqual(apiError); + }); + }); + }); +}); diff --git a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.reducer.ts b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.reducer.ts index 6cef7b1ccc197cbf87bfcfbe722e3e1a8a44bcc2..6f216d9a26c4bce3a94a338d1df995cf63eb2edd 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.reducer.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.reducer.ts @@ -21,7 +21,12 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { createEmptyStateResource, createErrorStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createErrorStateResource, + createStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { Action, ActionReducer, createReducer, on } from '@ngrx/store'; import { UserSettingsResource } from '../user-settings.model'; import * as UserSettingsActions from './user-settings.actions'; @@ -30,46 +35,64 @@ import { ApiErrorAction, LoadedUserSettingsAction } from './user-settings.action export const SETTINGS_FEATURE_KEY = 'UserSettingsState'; export interface UserSettingsPartialState { - readonly [SETTINGS_FEATURE_KEY]: UserSettingsState; + readonly [SETTINGS_FEATURE_KEY]: UserSettingsState; } export interface UserSettingsState { - userSettings: StateResource<UserSettingsResource> + userSettings: StateResource<UserSettingsResource>; } export const initialUserSettingsState: UserSettingsState = { - userSettings: createEmptyStateResource() + userSettings: createEmptyStateResource(), }; const reducer: ActionReducer<UserSettingsState, Action> = createReducer( - initialUserSettingsState, - on(UserSettingsActions.loadUserSettings, (state: UserSettingsState): UserSettingsState => ({ - ...state, - userSettings: { ...state.userSettings, loading: true } - })), - on(UserSettingsActions.loadUserSettingsSuccess, (state: UserSettingsState, action: LoadedUserSettingsAction) => ({ - ...state, - userSettings: createStateResource<UserSettingsResource>(action.userSettings) - })), - on(UserSettingsActions.loadUserSettingsFailure, (state: UserSettingsState, action: ApiErrorAction) => ({ - ...state, - userSettings: createErrorStateResource<UserSettingsResource>(action.apiError) - })), + initialUserSettingsState, + on( + UserSettingsActions.loadUserSettings, + (state: UserSettingsState): UserSettingsState => ({ + ...state, + userSettings: { ...state.userSettings, loading: true }, + }), + ), + on( + UserSettingsActions.loadUserSettingsSuccess, + (state: UserSettingsState, action: LoadedUserSettingsAction) => ({ + ...state, + userSettings: createStateResource<UserSettingsResource>(action.userSettings), + }), + ), + on( + UserSettingsActions.loadUserSettingsFailure, + (state: UserSettingsState, action: ApiErrorAction) => ({ + ...state, + userSettings: createErrorStateResource<UserSettingsResource>(action.apiError), + }), + ), - on(UserSettingsActions.setUserSettings, (state: UserSettingsState): UserSettingsState => ({ - ...state, - userSettings: { ...state.userSettings, loading: true } - })), - on(UserSettingsActions.setUserSettingsSuccess, (state: UserSettingsState, action: LoadedUserSettingsAction) => ({ - ...state, - userSettings: createStateResource<UserSettingsResource>(action.userSettings) - })), - on(UserSettingsActions.setUserSettingsFailure, (state: UserSettingsState, action: ApiErrorAction) => ({ - ...state, - userSettings: createErrorStateResource<UserSettingsResource>(action.apiError) - })) + on( + UserSettingsActions.setUserSettings, + (state: UserSettingsState): UserSettingsState => ({ + ...state, + userSettings: { ...state.userSettings, loading: true }, + }), + ), + on( + UserSettingsActions.setUserSettingsSuccess, + (state: UserSettingsState, action: LoadedUserSettingsAction) => ({ + ...state, + userSettings: createStateResource<UserSettingsResource>(action.userSettings), + }), + ), + on( + UserSettingsActions.setUserSettingsFailure, + (state: UserSettingsState, action: ApiErrorAction) => ({ + ...state, + userSettings: createErrorStateResource<UserSettingsResource>(action.apiError), + }), + ), ); export function userSettingsReducer(state: UserSettingsState, action: Action): UserSettingsState { - return reducer(state, action); + return reducer(state, action); } diff --git a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.selectors.spec.ts b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.selectors.spec.ts index 02a85596743298804c51d7b620ec6f3d5f1adffd..f53024e8a15e945f40eab52d77961f445f2fe80f 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.selectors.spec.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.selectors.spec.ts @@ -28,24 +28,26 @@ import { initialUserSettingsState, UserSettingsPartialState } from './user-setti import * as UserSettingsSelectors from './user-settings.selectors'; describe('UserSettings Selectors', () => { + let state: UserSettingsPartialState; - let state: UserSettingsPartialState; + const userSettings: StateResource<UserSettingsResource> = createStateResource( + createUserSettingsResource(), + ); - const userSettings: StateResource<UserSettingsResource> = createStateResource(createUserSettingsResource()); + beforeEach(() => { + state = { + UserSettingsState: { + ...initialUserSettingsState, + userSettings, + }, + }; + }); - beforeEach(() => { - state = { - UserSettingsState: { - ...initialUserSettingsState, - userSettings - } - } - }) - - describe('userSettingsSelector', () => { - - it('should return userSettings from state', () => { - expect(UserSettingsSelectors.userSettings.projector(state.UserSettingsState)).toEqual(userSettings); - }) - }) -}) \ No newline at end of file + describe('userSettingsSelector', () => { + it('should return userSettings from state', () => { + expect(UserSettingsSelectors.userSettings.projector(state.UserSettingsState)).toEqual( + userSettings, + ); + }); + }); +}); diff --git a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.selectors.ts b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.selectors.ts index f3a7d848f20068293b3d70b95f4d3c0e0c5a1349..c91cba99d4968140e775ff208f3b8094fdb2d450 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.selectors.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/+state/user-settings.selectors.ts @@ -26,6 +26,10 @@ import { createFeatureSelector, createSelector, MemoizedSelector } from '@ngrx/s import { UserSettingsResource } from '../user-settings.model'; import { SETTINGS_FEATURE_KEY, UserSettingsState } from './user-settings.reducer'; -export const getUserSettingsState: MemoizedSelector<object, UserSettingsState> = createFeatureSelector<UserSettingsState>(SETTINGS_FEATURE_KEY); +export const getUserSettingsState: MemoizedSelector<object, UserSettingsState> = + createFeatureSelector<UserSettingsState>(SETTINGS_FEATURE_KEY); -export const userSettings: MemoizedSelector<UserSettingsState, StateResource<UserSettingsResource>> = createSelector(getUserSettingsState, (state: UserSettingsState) => state.userSettings); \ No newline at end of file +export const userSettings: MemoizedSelector< + UserSettingsState, + StateResource<UserSettingsResource> +> = createSelector(getUserSettingsState, (state: UserSettingsState) => state.userSettings); diff --git a/alfa-client/libs/user-settings-shared/src/lib/user-settings-shared.module.ts b/alfa-client/libs/user-settings-shared/src/lib/user-settings-shared.module.ts index 878006975d614ce598609931ac48b5d7b24a19e0..54bc8186d614aaa430c8ededefc2ea60fb5ca7e3 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/user-settings-shared.module.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/user-settings-shared.module.ts @@ -31,14 +31,14 @@ import { UserSettingsFacade } from './+state/user-settings.facade'; import * as fromUserSettings from './+state/user-settings.reducer'; @NgModule({ - imports: [ - CommonModule, - EffectsModule.forFeature([UserSettingsEffects]), - StoreModule.forFeature( - fromUserSettings.SETTINGS_FEATURE_KEY, - fromUserSettings.userSettingsReducer - ), - ], - providers: [UserSettingsFacade], + imports: [ + CommonModule, + EffectsModule.forFeature([UserSettingsEffects]), + StoreModule.forFeature( + fromUserSettings.SETTINGS_FEATURE_KEY, + fromUserSettings.userSettingsReducer, + ), + ], + providers: [UserSettingsFacade], }) -export class UserSettingsSharedModule { } +export class UserSettingsSharedModule {} diff --git a/alfa-client/libs/user-settings-shared/src/lib/user-settings.linkrel.ts b/alfa-client/libs/user-settings-shared/src/lib/user-settings.linkrel.ts index 5a9596037fb26eeda271d2507199b653304f0bfe..0bbd4ff25d3e78ec1754728b7e33857a97c86d7b 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/user-settings.linkrel.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/user-settings.linkrel.ts @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum UserSettingsLinkRel { - EDIT = 'edit', + EDIT = 'edit', } diff --git a/alfa-client/libs/user-settings-shared/src/lib/user-settings.model.ts b/alfa-client/libs/user-settings-shared/src/lib/user-settings.model.ts index abd3e2b9da9ddebd7c5aa8debbcf1c1c06954518..c9cbd96900720d290a6d77f98f9194fee3a2c313 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/user-settings.model.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/user-settings.model.ts @@ -24,12 +24,12 @@ import { Resource } from '@ngxp/rest'; export enum NotificationsSendFor { - NONE = "NONE", - ALL = "ALL" + NONE = 'NONE', + ALL = 'ALL', } export interface UserSettings { - notificationsSendFor: string; + notificationsSendFor: string; } -export interface UserSettingsResource extends UserSettings, Resource { } +export interface UserSettingsResource extends UserSettings, Resource {} diff --git a/alfa-client/libs/user-settings-shared/src/lib/user-settings.repository.spec.ts b/alfa-client/libs/user-settings-shared/src/lib/user-settings.repository.spec.ts index ce6d1235fb55f4965e223b4a92cc450be7a6dea8..b373c52a6ef03fe12caaa4005d3533231d726b1c 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/user-settings.repository.spec.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/user-settings.repository.spec.ts @@ -26,76 +26,79 @@ import { UserProfileLinkRel, UserProfileResource } from '@alfa-client/user-profi import { ResourceFactory } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; import { createUserProfileResource } from 'libs/user-profile-shared/test/user-profile'; -import { createUserSettings, createUserSettingsResource } from 'libs/user-settings-shared/test/user-settings'; +import { + createUserSettings, + createUserSettingsResource, +} from 'libs/user-settings-shared/test/user-settings'; import { UserSettingsLinkRel } from './user-settings.linkrel'; import { UserSettings, UserSettingsResource } from './user-settings.model'; import { UserSettingsRepository } from './user-settings.repository'; describe('UserSettingsRepository', () => { - let repository: UserSettingsRepository; - let resourceFactory = mock(ResourceFactory); - let resourceWrapper = { get: jest.fn(), patch: jest.fn() }; + let repository: UserSettingsRepository; + let resourceFactory = mock(ResourceFactory); + let resourceWrapper = { get: jest.fn(), patch: jest.fn() }; - beforeEach(() => { - repository = new UserSettingsRepository(useFromMock(resourceFactory)); + beforeEach(() => { + repository = new UserSettingsRepository(useFromMock(resourceFactory)); - resourceFactory.from.mockReturnValue(resourceWrapper); - }) + resourceFactory.from.mockReturnValue(resourceWrapper); + }); - describe('get user settings', () => { - const userProfileResource: UserProfileResource = createUserProfileResource(); - const responseResource: UserProfileResource = createUserProfileResource(); + describe('get user settings', () => { + const userProfileResource: UserProfileResource = createUserProfileResource(); + const responseResource: UserProfileResource = createUserProfileResource(); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: responseResource })); - }) + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: responseResource })); + }); - it('should call resourceFactory with resource', () => { - repository.getUserSettings(userProfileResource); + it('should call resourceFactory with resource', () => { + repository.getUserSettings(userProfileResource); - expect(resourceFactory.from).toHaveBeenCalledWith(userProfileResource); - }) + expect(resourceFactory.from).toHaveBeenCalledWith(userProfileResource); + }); - it('should call resourceWrapper with link', () => { - repository.getUserSettings(userProfileResource); + it('should call resourceWrapper with link', () => { + repository.getUserSettings(userProfileResource); - expect(resourceWrapper.get).toHaveBeenCalledWith(UserProfileLinkRel.SETTINGS) - }) + expect(resourceWrapper.get).toHaveBeenCalledWith(UserProfileLinkRel.SETTINGS); + }); - it('should return result', () => { - let result = repository.getUserSettings(userProfileResource); + it('should return result', () => { + let result = repository.getUserSettings(userProfileResource); - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: responseResource })); - }) - }) + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: responseResource })); + }); + }); - describe('set user settings', () => { - const userSettingsResource: UserSettingsResource = createUserSettingsResource(); - const responseResource: UserProfileResource = createUserProfileResource(); - const userSettings: UserSettings = createUserSettings(); + describe('set user settings', () => { + const userSettingsResource: UserSettingsResource = createUserSettingsResource(); + const responseResource: UserProfileResource = createUserProfileResource(); + const userSettings: UserSettings = createUserSettings(); - beforeEach(() => { - resourceWrapper.patch.mockReturnValue(hot('a', { a: responseResource })); - }) + beforeEach(() => { + resourceWrapper.patch.mockReturnValue(hot('a', { a: responseResource })); + }); - it('should call resourceFactory with resource', () => { - repository.setUserSettings(userSettingsResource, userSettings); + it('should call resourceFactory with resource', () => { + repository.setUserSettings(userSettingsResource, userSettings); - expect(resourceFactory.from).toHaveBeenCalledWith(userSettingsResource); - }) + expect(resourceFactory.from).toHaveBeenCalledWith(userSettingsResource); + }); - it('should call resourceWrapper with link', () => { - repository.setUserSettings(userSettingsResource, userSettings); + it('should call resourceWrapper with link', () => { + repository.setUserSettings(userSettingsResource, userSettings); - expect(resourceWrapper.patch).toHaveBeenCalledWith(UserSettingsLinkRel.EDIT, userSettings) - }) + expect(resourceWrapper.patch).toHaveBeenCalledWith(UserSettingsLinkRel.EDIT, userSettings); + }); - it('should return result', () => { - let result = repository.setUserSettings(userSettingsResource, userSettings); + it('should return result', () => { + let result = repository.setUserSettings(userSettingsResource, userSettings); - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: responseResource })); - }) - }) -}) \ No newline at end of file + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: responseResource })); + }); + }); +}); diff --git a/alfa-client/libs/user-settings-shared/src/lib/user-settings.repository.ts b/alfa-client/libs/user-settings-shared/src/lib/user-settings.repository.ts index c8b3530aa2fd5216b6a3e54b1992ccc2b3ac3153..c51fee5ef13b1ebed2f3aa6ba652471393bf8ecd 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/user-settings.repository.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/user-settings.repository.ts @@ -30,14 +30,20 @@ import { UserSettings, UserSettingsResource } from './user-settings.model'; @Injectable({ providedIn: 'root' }) export class UserSettingsRepository { + constructor(private resourceFactory: ResourceFactory) {} - constructor(private resourceFactory: ResourceFactory) { } + public getUserSettings( + userProfileResource: UserProfileResource, + ): Observable<UserSettingsResource> { + return this.resourceFactory.from(userProfileResource).get(UserProfileLinkRel.SETTINGS); + } - public getUserSettings(userProfileResource: UserProfileResource): Observable<UserSettingsResource> { - return this.resourceFactory.from(userProfileResource).get(UserProfileLinkRel.SETTINGS); - } - - public setUserSettings(userSettingsResource: UserSettingsResource, userSettings: UserSettings): Observable<UserSettingsResource> { - return this.resourceFactory.from(userSettingsResource).patch(UserSettingsLinkRel.EDIT, userSettings); - } -} \ No newline at end of file + public setUserSettings( + userSettingsResource: UserSettingsResource, + userSettings: UserSettings, + ): Observable<UserSettingsResource> { + return this.resourceFactory + .from(userSettingsResource) + .patch(UserSettingsLinkRel.EDIT, userSettings); + } +} diff --git a/alfa-client/libs/user-settings-shared/src/lib/user-settings.service.spec.ts b/alfa-client/libs/user-settings-shared/src/lib/user-settings.service.spec.ts index 5d75f3321438445dcbed4eec783577c66ef21e54..fc61b2f8b15897e4298a51d9d4b848fece1ded5e 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/user-settings.service.spec.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/user-settings.service.spec.ts @@ -21,74 +21,84 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { mock, Mock, useFromMock } from '@alfa-client/test-utils'; import { UserProfileResource, UserProfileService } from '@alfa-client/user-profile-shared'; import { cold, hot } from 'jest-marbles'; import { createUserProfileResource } from 'libs/user-profile-shared/test/user-profile'; -import { createUserSettings, createUserSettingsResource } from 'libs/user-settings-shared/test/user-settings'; +import { + createUserSettings, + createUserSettingsResource, +} from 'libs/user-settings-shared/test/user-settings'; import { Observable } from 'rxjs'; import { UserSettingsFacade } from './+state/user-settings.facade'; import { UserSettings, UserSettingsResource } from './user-settings.model'; import { UserSettingsService } from './user-settings.service'; describe('UserSettingsService', () => { - let facade: Mock<UserSettingsFacade>; - let userProfileService: Mock<UserProfileService>; + let facade: Mock<UserSettingsFacade>; + let userProfileService: Mock<UserProfileService>; - let service: UserSettingsService; + let service: UserSettingsService; - beforeEach(() => { - facade = mock(UserSettingsFacade); - userProfileService = mock(UserProfileService); + beforeEach(() => { + facade = mock(UserSettingsFacade); + userProfileService = mock(UserProfileService); - service = new UserSettingsService(useFromMock(facade), useFromMock(userProfileService)); - }); + service = new UserSettingsService(useFromMock(facade), useFromMock(userProfileService)); + }); - it('should be created', () => { - expect(service).toBeTruthy(); - }); + it('should be created', () => { + expect(service).toBeTruthy(); + }); - describe('get user settings', () => { - const userProfileResource: UserProfileResource = createUserProfileResource(); - const stateResourceCU = createStateResource(createUserSettingsResource()); - const emptyStateResourceCU = createEmptyStateResource<UserProfileResource>(true); + describe('get user settings', () => { + const userProfileResource: UserProfileResource = createUserProfileResource(); + const stateResourceCU = createStateResource(createUserSettingsResource()); + const emptyStateResourceCU = createEmptyStateResource<UserProfileResource>(true); - beforeEach(() => { - const stateResourceUP: StateResource<UserProfileResource> = createStateResource(userProfileResource); - userProfileService.getCurrentUser.mockReturnValue(hot('a', { a: stateResourceUP })); + beforeEach(() => { + const stateResourceUP: StateResource<UserProfileResource> = + createStateResource(userProfileResource); + userProfileService.getCurrentUser.mockReturnValue(hot('a', { a: stateResourceUP })); - facade.getUserSettings.mockReturnValue(hot('-a', { a: stateResourceCU })); - }) + facade.getUserSettings.mockReturnValue(hot('-a', { a: stateResourceCU })); + }); - it('should call userProfileService.getCurrentUser', () => { - service.getUserSettings(); + it('should call userProfileService.getCurrentUser', () => { + service.getUserSettings(); - expect(userProfileService.getCurrentUser).toHaveBeenCalled(); - }) + expect(userProfileService.getCurrentUser).toHaveBeenCalled(); + }); - it.skip('should load user settings from facade', (done) => { - service.getUserSettings().subscribe(() => { - expect(facade.loadUserSettings).toHaveBeenCalledWith(userProfileResource); - done(); - }); - }) + it.skip('should load user settings from facade', (done) => { + service.getUserSettings().subscribe(() => { + expect(facade.loadUserSettings).toHaveBeenCalledWith(userProfileResource); + done(); + }); + }); - it('should return user settings', () => { - const userSettings$: Observable<StateResource<UserSettingsResource>> = service.getUserSettings(); + it('should return user settings', () => { + const userSettings$: Observable<StateResource<UserSettingsResource>> = + service.getUserSettings(); - expect(userSettings$).toBeObservable(cold('ab', { a: emptyStateResourceCU, b: stateResourceCU })); - }) + expect(userSettings$).toBeObservable( + cold('ab', { a: emptyStateResourceCU, b: stateResourceCU }), + ); + }); + }); - }) + describe('set UserSettings', () => { + it('should call set method in facade', () => { + const userSettings: UserSettings = createUserSettings(); - describe('set UserSettings', () => { - it('should call set method in facade', () => { - const userSettings: UserSettings = createUserSettings(); + service.setUserSettings(userSettings); - service.setUserSettings(userSettings); - - expect(facade.setUserSettings).toHaveBeenCalledWith(userSettings); - }) - }) + expect(facade.setUserSettings).toHaveBeenCalledWith(userSettings); + }); + }); }); diff --git a/alfa-client/libs/user-settings-shared/src/lib/user-settings.service.ts b/alfa-client/libs/user-settings-shared/src/lib/user-settings.service.ts index 16e13aa9348623a5bfe3be0b1f2db868f24a1ba7..57c852f96077aa864686a02b55e46b24184f727f 100644 --- a/alfa-client/libs/user-settings-shared/src/lib/user-settings.service.ts +++ b/alfa-client/libs/user-settings-shared/src/lib/user-settings.service.ts @@ -22,7 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Injectable } from '@angular/core'; -import { createEmptyStateResource, doIfLoadingRequired, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + doIfLoadingRequired, + StateResource, +} from '@alfa-client/tech-shared'; import { UserProfileService } from '@alfa-client/user-profile-shared'; import { combineLatest, Observable } from 'rxjs'; import { map, startWith, tap } from 'rxjs/operators'; @@ -31,25 +35,29 @@ import { UserSettings, UserSettingsResource } from './user-settings.model'; @Injectable({ providedIn: 'root' }) export class UserSettingsService { + constructor( + private userSettingsFacade: UserSettingsFacade, + private userProfileService: UserProfileService, + ) {} - constructor( - private userSettingsFacade: UserSettingsFacade, - private userProfileService: UserProfileService, - ) { } + public getUserSettings(): Observable<StateResource<UserSettingsResource>> { + return combineLatest([ + this.userProfileService.getCurrentUser(), + this.userSettingsFacade.getUserSettings(), + ]).pipe( + tap(([userProfile, userSettings]) => + doIfLoadingRequired(userSettings, () => { + if (userProfile.resource) { + this.userSettingsFacade.loadUserSettings(userProfile.resource); + } + }), + ), + map(([, userSettings]) => userSettings), + startWith(createEmptyStateResource<UserSettingsResource>(true)), + ); + } - public getUserSettings(): Observable<StateResource<UserSettingsResource>> { - return combineLatest([this.userProfileService.getCurrentUser(), this.userSettingsFacade.getUserSettings()]).pipe( - tap(([userProfile, userSettings]) => doIfLoadingRequired(userSettings, () => { - if (userProfile.resource) { - this.userSettingsFacade.loadUserSettings(userProfile.resource); - } - })), - map(([, userSettings]) => userSettings), - startWith(createEmptyStateResource<UserSettingsResource>(true)) - ); - } - - public setUserSettings(userSettings: UserSettings): void { - this.userSettingsFacade.setUserSettings(userSettings); - } + public setUserSettings(userSettings: UserSettings): void { + this.userSettingsFacade.setUserSettings(userSettings); + } } diff --git a/alfa-client/libs/user-settings-shared/src/test-setup.ts b/alfa-client/libs/user-settings-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/user-settings-shared/src/test-setup.ts +++ b/alfa-client/libs/user-settings-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/user-settings-shared/test/user-settings.ts b/alfa-client/libs/user-settings-shared/test/user-settings.ts index db428b392f442be3d86e4a6b2a41602c1612e85c..5e787b1be075b6784b619a3abbe5eda8d1a4f91c 100644 --- a/alfa-client/libs/user-settings-shared/test/user-settings.ts +++ b/alfa-client/libs/user-settings-shared/test/user-settings.ts @@ -22,15 +22,18 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { toResource } from 'libs/tech-shared/test/resource'; -import { NotificationsSendFor, UserSettings, UserSettingsResource } from '../src/lib/user-settings.model'; +import { + NotificationsSendFor, + UserSettings, + UserSettingsResource, +} from '../src/lib/user-settings.model'; export function createUserSettingsResource(linkRelations: string[] = []): UserSettingsResource { - return toResource(createUserSettings(), linkRelations); + return toResource(createUserSettings(), linkRelations); } export function createUserSettings(): UserSettings { - return { - notificationsSendFor: NotificationsSendFor.ALL - } + return { + notificationsSendFor: NotificationsSendFor.ALL, + }; } - diff --git a/alfa-client/libs/user-settings-shared/tsconfig.json b/alfa-client/libs/user-settings-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/user-settings-shared/tsconfig.json +++ b/alfa-client/libs/user-settings-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/user-settings-shared/tsconfig.lib.json b/alfa-client/libs/user-settings-shared/tsconfig.lib.json index ead8f8bdba5aca4d713f65c9003b06695a69c2f4..2e762bd23944def694724f2ce7c0ea2d922ae1e5 100644 --- a/alfa-client/libs/user-settings-shared/tsconfig.lib.json +++ b/alfa-client/libs/user-settings-shared/tsconfig.lib.json @@ -1,17 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [] - }, - "exclude": [ - "src/test-setup.ts", - "**/*.spec.ts", - "**/*.test.ts", - "jest.config.ts" - ], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "**/*.test.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/user-settings-shared/tsconfig.spec.json b/alfa-client/libs/user-settings-shared/tsconfig.spec.json index 8aebb990f5ab78e0220092403b1217ead2e8fa94..a6ea32cf1965d401df75804a35fdcab4ad04ef0e 100644 --- a/alfa-client/libs/user-settings-shared/tsconfig.spec.json +++ b/alfa-client/libs/user-settings-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] } diff --git a/alfa-client/libs/user-settings/.eslintrc.json b/alfa-client/libs/user-settings/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/user-settings/.eslintrc.json +++ b/alfa-client/libs/user-settings/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/user-settings/jest.config.ts b/alfa-client/libs/user-settings/jest.config.ts index b6cb94ecdf55f5fe1fb6195356fa9e68b4f683e4..0bbf2e70783493b250b09d7d3abb7ac2372d20ca 100644 --- a/alfa-client/libs/user-settings/jest.config.ts +++ b/alfa-client/libs/user-settings/jest.config.ts @@ -24,24 +24,24 @@ */ /* eslint-disable */ export default { - displayName: 'user-settings', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/user-settings', - transform: { - '^.+\\.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], + displayName: 'user-settings', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/user-settings', + transform: { + '^.+\\.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], }; diff --git a/alfa-client/libs/user-settings/project.json b/alfa-client/libs/user-settings/project.json index 7ef53990ec4fb5e1729edae8be9bf33d38426b38..7babef7d9fe369b0937dc207394f25614a987117 100644 --- a/alfa-client/libs/user-settings/project.json +++ b/alfa-client/libs/user-settings/project.json @@ -1,28 +1,25 @@ { - "name": "user-settings", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/user-settings/src", - "prefix": "alfa", - "targets": { - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/user-settings"], - "options": { - "tsConfig": "libs/user-settings/tsconfig.spec.json", - "jestConfig": "libs/user-settings/jest.config.ts", - "passWithNoTests": true - } - }, - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/user-settings/**/*.ts", - "libs/user-settings/**/*.html" - ] - } - } - }, - "tags": [] + "name": "user-settings", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/user-settings/src", + "prefix": "alfa", + "targets": { + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/user-settings"], + "options": { + "tsConfig": "libs/user-settings/tsconfig.spec.json", + "jestConfig": "libs/user-settings/jest.config.ts", + "passWithNoTests": true + } + }, + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/user-settings/**/*.ts", "libs/user-settings/**/*.html"] + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/user-settings/src/index.ts b/alfa-client/libs/user-settings/src/index.ts index 4e7abcc1aee88e9f38f46bc4edfa64259b2924ef..b8278b8161b47f023b308d7e0f720a038ad1173f 100644 --- a/alfa-client/libs/user-settings/src/index.ts +++ b/alfa-client/libs/user-settings/src/index.ts @@ -23,4 +23,3 @@ */ export * from './lib/user-settings-container/user-settings-container.component'; export * from './lib/user-settings.module'; - diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.scss b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.scss index 0efb6f1808218879a86711603e05b98c26951214..de3f141eefcffe2769df15f50da230097eb95d8c 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.scss +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.scss @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - margin: 0 16px 0 10px; -} \ No newline at end of file + margin: 0 16px 0 10px; +} diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts index 65fa875ed052f94f2f8885357d257c172a34e6dd..07c7f1980a5205030294d2ffcfa6e2d0e1972bba 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.spec.ts @@ -29,42 +29,38 @@ import { UserSettingsContainerComponent } from './user-settings-container.compon import { UserSettingsComponent } from './user-settings/user-settings.component'; describe('UserSettingsContainerComponent', () => { - let component: UserSettingsContainerComponent; - let fixture: ComponentFixture<UserSettingsContainerComponent>; + let component: UserSettingsContainerComponent; + let fixture: ComponentFixture<UserSettingsContainerComponent>; - const apiRootFacade: Mock<ApiRootFacade> = { ...mock(ApiRootFacade), getApiRoot: jest.fn() }; + const apiRootFacade: Mock<ApiRootFacade> = { ...mock(ApiRootFacade), getApiRoot: jest.fn() }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserSettingsContainerComponent, - MockComponent(UserSettingsComponent) - ], - providers: [ - { - provide: ApiRootFacade, - useValue: apiRootFacade - } - ], - }); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UserSettingsContainerComponent, MockComponent(UserSettingsComponent)], + providers: [ + { + provide: ApiRootFacade, + useValue: apiRootFacade, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(UserSettingsContainerComponent); - component = fixture.componentInstance; - fixture.autoDetectChanges(true); - }); + beforeEach(() => { + fixture = TestBed.createComponent(UserSettingsContainerComponent); + component = fixture.componentInstance; + fixture.autoDetectChanges(true); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should call apiRoot facade', () => { + component.ngOnInit(); - it('should call apiRoot facade', () => { - component.ngOnInit(); - - expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); - }) - }) + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts index ba61590b4d0fda18db1852143f6781d8689b645e..1b2f012771524fcc2f8898567e8a0154ba60c1ec 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings-container.component.ts @@ -27,17 +27,18 @@ import { createEmptyStateResource, StateResource } from '@alfa-client/tech-share import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-user-settings-container', - templateUrl: './user-settings-container.component.html', - styleUrls: ['./user-settings-container.component.scss'], + selector: 'alfa-user-settings-container', + templateUrl: './user-settings-container.component.html', + styleUrls: ['./user-settings-container.component.scss'], }) export class UserSettingsContainerComponent implements OnInit { + apiRoot$: Observable<StateResource<ApiRootResource>> = of( + createEmptyStateResource<ApiRootResource>(), + ); - apiRoot$: Observable<StateResource<ApiRootResource>> = of(createEmptyStateResource<ApiRootResource>()); + constructor(private apiRootFacade: ApiRootFacade) {} - constructor(private apiRootFacade: ApiRootFacade) { } - - ngOnInit(): void { - this.apiRoot$ = this.apiRootFacade.getApiRoot(); - } -} \ No newline at end of file + ngOnInit(): void { + this.apiRoot$ = this.apiRootFacade.getApiRoot(); + } +} diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.html b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.html index b1b1b783a846f219e6fb45f52ce9c2fae10fa307..3f00258a73c288ba0805b3a46050150fa5016897 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.html +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.html @@ -24,6 +24,7 @@ --> <alfa-user-settings-darkmode - [darkMode]="darkMode$ | async" - (valueChanged)="changeColorMode($event)"> -</alfa-user-settings-darkmode> \ No newline at end of file + [darkMode]="darkMode$ | async" + (valueChanged)="changeColorMode($event)" +> +</alfa-user-settings-darkmode> diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.spec.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.spec.ts index a6ec69f2307a4b109ccc44dc4072429876227a6a..5ae103c6a3ca8a318ac3f45268d7c2d75585763a 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.spec.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.spec.ts @@ -30,41 +30,40 @@ import { UserSettingsDarkmodeContainerComponent } from './user-settings-darkmode import { UserSettingsDarkmodeComponent } from './user-settings-darkmode/user-settings-darkmode.component'; describe('UserSettingsDarkmodeContainerComponent', () => { - let component: UserSettingsDarkmodeContainerComponent; - let fixture: ComponentFixture<UserSettingsDarkmodeContainerComponent>; + let component: UserSettingsDarkmodeContainerComponent; + let fixture: ComponentFixture<UserSettingsDarkmodeContainerComponent>; - const darkModeSubj: BehaviorSubject<boolean> = new BehaviorSubject(false); - const appService = { ...mock(AppService), getDarkMode: () => darkModeSubj }; + const darkModeSubj: BehaviorSubject<boolean> = new BehaviorSubject(false); + const appService = { ...mock(AppService), getDarkMode: () => darkModeSubj }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserSettingsDarkmodeContainerComponent, - MockComponent(UserSettingsDarkmodeComponent) - ], - providers: [ - { - provide: AppService, - useValue: appService, - } - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserSettingsDarkmodeContainerComponent, + MockComponent(UserSettingsDarkmodeComponent), + ], + providers: [ + { + provide: AppService, + useValue: appService, + }, + ], + }).compileComponents(); - fixture = TestBed.createComponent(UserSettingsDarkmodeContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(UserSettingsDarkmodeContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('change color mode', () => { + describe('change color mode', () => { + it('should call app service', () => { + component.changeColorMode(true); - it('should call app service', () => { - component.changeColorMode(true); - - expect(appService.setDarkMode).toHaveBeenCalledWith(true); - }) - }) -}); \ No newline at end of file + expect(appService.setDarkMode).toHaveBeenCalledWith(true); + }); + }); +}); diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.ts index 85e1a7dd827ad2b8bac932082a5d2ef9bf1456fc..5039d964cba91f75633f185a45369f6286d25c20 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode-container.component.ts @@ -27,43 +27,40 @@ import { AppService, localStorageDark } from '@alfa-client/app-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-user-settings-darkmode-container', - templateUrl: './user-settings-darkmode-container.component.html', - styleUrls: ['./user-settings-darkmode-container.component.scss'], + selector: 'alfa-user-settings-darkmode-container', + templateUrl: './user-settings-darkmode-container.component.html', + styleUrls: ['./user-settings-darkmode-container.component.scss'], }) export class UserSettingsDarkmodeContainerComponent implements OnInit { + darkMode$: Observable<boolean>; - darkMode$: Observable<boolean>; + constructor( + private renderer: Renderer2, + private appService: AppService, + @Inject(DOCUMENT) private document: Document, + ) {} - constructor( - private renderer: Renderer2, - private appService: AppService, - @Inject(DOCUMENT) private document: Document - ) { } + ngOnInit(): void { + this.darkMode$ = this.appService.getDarkMode(); - ngOnInit(): void { - this.darkMode$ = this.appService.getDarkMode(); + this.subscribeToDarkMode(); + } - this.subscribeToDarkMode(); - } + private subscribeToDarkMode(): void { + this.darkMode$.subscribe((darkMode) => + darkMode ? this.addClass(localStorageDark) : this.removeClass(localStorageDark), + ); + } - private subscribeToDarkMode(): void { - this.darkMode$.subscribe((darkMode) => - darkMode - ? this.addClass(localStorageDark) - : this.removeClass(localStorageDark) - ); - } + private addClass(styleClass: string): void { + this.renderer.addClass(this.document.body, styleClass); + } - private addClass(styleClass: string): void { - this.renderer.addClass(this.document.body, styleClass); - } + private removeClass(styleClass: string): void { + this.renderer.removeClass(this.document.body, styleClass); + } - private removeClass(styleClass: string): void { - this.renderer.removeClass(this.document.body, styleClass); - } - - public changeColorMode(darkMode: boolean): void { - this.appService.setDarkMode(darkMode); - } -} \ No newline at end of file + public changeColorMode(darkMode: boolean): void { + this.appService.setDarkMode(darkMode); + } +} diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.html b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.html index a95d8d4d092851f8f54905c1315bb98257b16dde..28fea30cf904ee5306eef7930d56bcbdde0ad616 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.html +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.html @@ -23,9 +23,10 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ozgcloud-slide-toggle data-test-id="dark-mode" - label="Dark Mode" - [checked]="darkMode" - (valueChanged)="valueChanged.emit($event)"> +<ozgcloud-slide-toggle + data-test-id="dark-mode" + label="Dark Mode" + [checked]="darkMode" + (valueChanged)="valueChanged.emit($event)" +> </ozgcloud-slide-toggle> - diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.scss b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.scss index dd73ed80dd0d4065713a6d5126ca7316fba14ee9..f5f3222fb136bac0b7c69922c9e9f4a59424b862 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.scss +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.scss @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ ozgcloud-slide-toggle { - display: block; -} \ No newline at end of file + display: block; +} diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.spec.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.spec.ts index 9e2958db067a67a3c16c9233d6ccab15c3d7c0bf..de0067842beb3705fe6cfaf16e752f48cae35559 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.spec.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.spec.ts @@ -27,23 +27,20 @@ import { MockComponent } from 'ng-mocks'; import { UserSettingsDarkmodeComponent } from './user-settings-darkmode.component'; describe('UserSettingsDarkmodeComponent', () => { - let component: UserSettingsDarkmodeComponent; - let fixture: ComponentFixture<UserSettingsDarkmodeComponent>; + let component: UserSettingsDarkmodeComponent; + let fixture: ComponentFixture<UserSettingsDarkmodeComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserSettingsDarkmodeComponent, - MockComponent(SlideToggleComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [UserSettingsDarkmodeComponent, MockComponent(SlideToggleComponent)], + }).compileComponents(); - fixture = TestBed.createComponent(UserSettingsDarkmodeComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(UserSettingsDarkmodeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.ts index 2caf0be4f13e29357942255375b799dd4feb110c..19c6f65dbdb33c42ce4556a4b65104a27ef5ad3d 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-darkmode-container/user-settings-darkmode/user-settings-darkmode.component.ts @@ -24,13 +24,12 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ - selector: 'alfa-user-settings-darkmode', - templateUrl: './user-settings-darkmode.component.html', - styleUrls: ['./user-settings-darkmode.component.scss'], + selector: 'alfa-user-settings-darkmode', + templateUrl: './user-settings-darkmode.component.html', + styleUrls: ['./user-settings-darkmode.component.scss'], }) export class UserSettingsDarkmodeComponent { + @Input() darkMode: boolean; - @Input() darkMode: boolean; - - @Output() valueChanged: EventEmitter<boolean> = new EventEmitter(); + @Output() valueChanged: EventEmitter<boolean> = new EventEmitter(); } diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.html b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.html index a75f2295f39804d29837c2bbac611549b1ef836c..ca5108e414a5dc65071051bdcacf9eeb7505cb13 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.html +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.html @@ -24,6 +24,7 @@ --> <alfa-user-settings-email-benachrichtigung - [userSettings]="userSettings$ | async" - (valueChanged)="changeNotificationsSendFor($event)"> -</alfa-user-settings-email-benachrichtigung> \ No newline at end of file + [userSettings]="userSettings$ | async" + (valueChanged)="changeNotificationsSendFor($event)" +> +</alfa-user-settings-email-benachrichtigung> diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.spec.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.spec.ts index d2886f4c5082d46b02ee9a98faabbe9ec59739c6..25b285ff3eb86bf18d04a549292eee9690b46b35 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.spec.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.spec.ts @@ -29,55 +29,57 @@ import { UserSettingsEmailBenachrichtigungContainerComponent } from './user-sett import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component'; describe('UserSettingsEmailBenachrichtigungContainerComponent', () => { - let component: UserSettingsEmailBenachrichtigungContainerComponent; - let fixture: ComponentFixture<UserSettingsEmailBenachrichtigungContainerComponent>; + let component: UserSettingsEmailBenachrichtigungContainerComponent; + let fixture: ComponentFixture<UserSettingsEmailBenachrichtigungContainerComponent>; - const userSettingsService = { ...mock(UserSettingsService), setUserSettings: jest.fn() }; + const userSettingsService = { ...mock(UserSettingsService), setUserSettings: jest.fn() }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserSettingsEmailBenachrichtigungContainerComponent, - MockComponent(UserSettingsEmailBenachrichtigungComponent) - ], - providers: [ - { - provide: UserSettingsService, - useValue: userSettingsService - } - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserSettingsEmailBenachrichtigungContainerComponent, + MockComponent(UserSettingsEmailBenachrichtigungComponent), + ], + providers: [ + { + provide: UserSettingsService, + useValue: userSettingsService, + }, + ], + }).compileComponents(); - fixture = TestBed.createComponent(UserSettingsEmailBenachrichtigungContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(UserSettingsEmailBenachrichtigungContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should call userSettings service', () => { + component.ngOnInit(); - it('should call userSettings service', () => { - component.ngOnInit(); + expect(userSettingsService.getUserSettings).toHaveBeenCalled(); + }); + }); - expect(userSettingsService.getUserSettings).toHaveBeenCalled(); - }) - }) + describe('change notifications send for', () => { + it('should call service with ALL', () => { + component.changeNotificationsSendFor(true); - describe('change notifications send for', () => { + expect(userSettingsService.setUserSettings).toHaveBeenCalledWith({ + notificationsSendFor: NotificationsSendFor.ALL, + }); + }); - it('should call service with ALL', () => { - component.changeNotificationsSendFor(true); + it('should call service with NONE', () => { + component.changeNotificationsSendFor(false); - expect(userSettingsService.setUserSettings).toHaveBeenCalledWith({ notificationsSendFor: NotificationsSendFor.ALL }); - }) - - it('should call service with NONE', () => { - component.changeNotificationsSendFor(false); - - expect(userSettingsService.setUserSettings).toHaveBeenCalledWith({ notificationsSendFor: NotificationsSendFor.NONE }); - }) - }) + expect(userSettingsService.setUserSettings).toHaveBeenCalledWith({ + notificationsSendFor: NotificationsSendFor.NONE, + }); + }); + }); }); diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.ts index b4e7e94722c2d3d4b6fa867c6da30ec79cb20d96..6d0aae2e294f836c7bd4cb3aeb558215ac8e2085 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung-container.component.ts @@ -23,30 +23,35 @@ */ import { Component } from '@angular/core'; import { StateResource } from '@alfa-client/tech-shared'; -import { NotificationsSendFor, UserSettings, UserSettingsResource, UserSettingsService } from '@alfa-client/user-settings-shared'; +import { + NotificationsSendFor, + UserSettings, + UserSettingsResource, + UserSettingsService, +} from '@alfa-client/user-settings-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-user-settings-email-benachrichtigung-container', - templateUrl: './user-settings-email-benachrichtigung-container.component.html', - styleUrls: ['./user-settings-email-benachrichtigung-container.component.scss'] + selector: 'alfa-user-settings-email-benachrichtigung-container', + templateUrl: './user-settings-email-benachrichtigung-container.component.html', + styleUrls: ['./user-settings-email-benachrichtigung-container.component.scss'], }) export class UserSettingsEmailBenachrichtigungContainerComponent { + userSettings$: Observable<StateResource<UserSettingsResource>>; - userSettings$: Observable<StateResource<UserSettingsResource>>; + constructor(private userSettingsService: UserSettingsService) {} - constructor(private userSettingsService: UserSettingsService) { } + ngOnInit(): void { + this.userSettings$ = this.userSettingsService.getUserSettings(); + } - ngOnInit(): void { - this.userSettings$ = this.userSettingsService.getUserSettings(); - } + changeNotificationsSendFor(toggleValue: boolean): void { + this.userSettingsService.setUserSettings(this.createUserSettings(toggleValue)); + } - changeNotificationsSendFor(toggleValue: boolean): void { - this.userSettingsService.setUserSettings(this.createUserSettings(toggleValue)); - } - - private createUserSettings(toggleValue: boolean): UserSettings { - const notificationsSendFor: NotificationsSendFor = toggleValue ? NotificationsSendFor.ALL : NotificationsSendFor.NONE; - return { notificationsSendFor }; - } + private createUserSettings(toggleValue: boolean): UserSettings { + const notificationsSendFor: NotificationsSendFor = + toggleValue ? NotificationsSendFor.ALL : NotificationsSendFor.NONE; + return { notificationsSendFor }; + } } diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html index ea752f8abb1f8cf8643e6b54b81432f1749304c6..2ba838cdb5bf7ce62c19a46dc40064719c2ede8c 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.html @@ -24,12 +24,13 @@ --> <ng-container *ngIf="userSettings.resource"> - - <ozgcloud-slide-toggle *ngIf="userSettings.resource | hasLink: userSettingsLinkRel.EDIT" data-test-id="email-benachrichtigung" - label="Benachrichtigung per E-Mail" - toolTip="Benachrichtigung per E-Mail bei Eingang eines Antrags" - [checked]="isChecked(userSettings.resource)" - (valueChanged)="valueChanged.emit($event)"> - </ozgcloud-slide-toggle> - -</ng-container> \ No newline at end of file + <ozgcloud-slide-toggle + *ngIf="userSettings.resource | hasLink: userSettingsLinkRel.EDIT" + data-test-id="email-benachrichtigung" + label="Benachrichtigung per E-Mail" + toolTip="Benachrichtigung per E-Mail bei Eingang eines Antrags" + [checked]="isChecked(userSettings.resource)" + (valueChanged)="valueChanged.emit($event)" + > + </ozgcloud-slide-toggle> +</ng-container> diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.scss b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.scss index e1c6900b2cf0104008fbc6d294e0ba7e543335ed..2c61cd3d511af48df63135619118571600325fe0 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.scss +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.scss @@ -22,6 +22,6 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ ozgcloud-slide-toggle { - margin-bottom: 0.5rem; - display: block; -} \ No newline at end of file + margin-bottom: 0.5rem; + display: block; +} diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts index cab776bbf442e2b87197d37d53f67a8344c1b60e..fd32e05adb6c76b0efbb232c0e0206447f164340 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.spec.ts @@ -23,87 +23,115 @@ */ import { EventEmitter } from '@angular/core'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { createEmptyStateResource, createStateResource, HasLinkPipe } from '@alfa-client/tech-shared'; -import { dispatchEventFromFixture, getElementFromFixture, Mock, mock, useFromMock } from '@alfa-client/test-utils'; +import { + createEmptyStateResource, + createStateResource, + HasLinkPipe, +} from '@alfa-client/tech-shared'; +import { + dispatchEventFromFixture, + getElementFromFixture, + Mock, + mock, + useFromMock, +} from '@alfa-client/test-utils'; import { UserSettingsLinkRel } from '@alfa-client/user-settings-shared'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { SlideToggleComponent } from 'libs/ui/src/lib/ui/slide-toggle/slide-toggle.component'; -import { NotificationsSendFor, UserSettings } from 'libs/user-settings-shared/src/lib/user-settings.model'; -import { createUserSettings, createUserSettingsResource } from 'libs/user-settings-shared/test/user-settings'; +import { + NotificationsSendFor, + UserSettings, +} from 'libs/user-settings-shared/src/lib/user-settings.model'; +import { + createUserSettings, + createUserSettingsResource, +} from 'libs/user-settings-shared/test/user-settings'; import { MockComponent } from 'ng-mocks'; import { UserSettingsEmailBenachrichtigungComponent } from './user-settings-email-benachrichtigung.component'; describe('UserSettingsEmailBenachrichtigungComponent', () => { - let component: UserSettingsEmailBenachrichtigungComponent; - let fixture: ComponentFixture<UserSettingsEmailBenachrichtigungComponent>; - - const notificationSensForToggle: string = getDataTestIdOf('email-benachrichtigung'); - - const valueChangedEmitter: Mock<EventEmitter<boolean>> = { ...mock(EventEmitter), emit: jest.fn() }; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HasLinkPipe, - UserSettingsEmailBenachrichtigungComponent, - MockComponent(SlideToggleComponent) - ], - }).compileComponents(); - - fixture = TestBed.createComponent(UserSettingsEmailBenachrichtigungComponent); - component = fixture.componentInstance; - component.userSettings = createEmptyStateResource(); - component.valueChanged = useFromMock(valueChangedEmitter); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('toggle', () => { - - it('should be active if notificationsSendFor is ALL', () => { - const userSettings: UserSettings = { ...createUserSettings(), notificationsSendFor: NotificationsSendFor.ALL }; - - const result: boolean = component.isChecked(userSettings); - - expect(result).toBeTruthy(); - }) - - it('should be not active if notificationsSendFor is NONE', () => { - const userSettings: UserSettings = { ...createUserSettings(), notificationsSendFor: NotificationsSendFor.NONE }; - - const result: boolean = component.isChecked(userSettings); - - expect(result).toBeFalsy(); - }) - - it('should emit value if toggled', () => { - component.userSettings = createStateResource(createUserSettingsResource([UserSettingsLinkRel.EDIT])); - fixture.detectChanges(); - - dispatchEventFromFixture(fixture, notificationSensForToggle, 'valueChanged'); - - expect(component.valueChanged.emit).toHaveBeenCalled(); - }) - - it('should hide if edit link is missing', () => { - component.userSettings = createStateResource(createUserSettingsResource()); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, notificationSensForToggle); - - expect(element).not.toBeInTheDocument(); - }) - - it('should show if edit link exist', () => { - component.userSettings = createStateResource(createUserSettingsResource([UserSettingsLinkRel.EDIT])); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, notificationSensForToggle); - - expect(element).toBeInTheDocument(); - }) - }) + let component: UserSettingsEmailBenachrichtigungComponent; + let fixture: ComponentFixture<UserSettingsEmailBenachrichtigungComponent>; + + const notificationSensForToggle: string = getDataTestIdOf('email-benachrichtigung'); + + const valueChangedEmitter: Mock<EventEmitter<boolean>> = { + ...mock(EventEmitter), + emit: jest.fn(), + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HasLinkPipe, + UserSettingsEmailBenachrichtigungComponent, + MockComponent(SlideToggleComponent), + ], + }).compileComponents(); + + fixture = TestBed.createComponent(UserSettingsEmailBenachrichtigungComponent); + component = fixture.componentInstance; + component.userSettings = createEmptyStateResource(); + component.valueChanged = useFromMock(valueChangedEmitter); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('toggle', () => { + it('should be active if notificationsSendFor is ALL', () => { + const userSettings: UserSettings = { + ...createUserSettings(), + notificationsSendFor: NotificationsSendFor.ALL, + }; + + const result: boolean = component.isChecked(userSettings); + + expect(result).toBeTruthy(); + }); + + it('should be not active if notificationsSendFor is NONE', () => { + const userSettings: UserSettings = { + ...createUserSettings(), + notificationsSendFor: NotificationsSendFor.NONE, + }; + + const result: boolean = component.isChecked(userSettings); + + expect(result).toBeFalsy(); + }); + + it('should emit value if toggled', () => { + component.userSettings = createStateResource( + createUserSettingsResource([UserSettingsLinkRel.EDIT]), + ); + fixture.detectChanges(); + + dispatchEventFromFixture(fixture, notificationSensForToggle, 'valueChanged'); + + expect(component.valueChanged.emit).toHaveBeenCalled(); + }); + + it('should hide if edit link is missing', () => { + component.userSettings = createStateResource(createUserSettingsResource()); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, notificationSensForToggle); + + expect(element).not.toBeInTheDocument(); + }); + + it('should show if edit link exist', () => { + component.userSettings = createStateResource( + createUserSettingsResource([UserSettingsLinkRel.EDIT]), + ); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, notificationSensForToggle); + + expect(element).toBeInTheDocument(); + }); + }); }); diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts index be912b814c1b5424d6552384d29454db7124914d..7770c34f1ef8f4cdf2003b6f51803ac914598a21 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-email-benachrichtigung-container/user-settings-email-benachrichtigung/user-settings-email-benachrichtigung.component.ts @@ -23,22 +23,27 @@ */ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { createEmptyStateResource, StateResource } from '@alfa-client/tech-shared'; -import { NotificationsSendFor, UserSettings, UserSettingsLinkRel, UserSettingsResource } from '@alfa-client/user-settings-shared'; +import { + NotificationsSendFor, + UserSettings, + UserSettingsLinkRel, + UserSettingsResource, +} from '@alfa-client/user-settings-shared'; @Component({ - selector: 'alfa-user-settings-email-benachrichtigung', - templateUrl: './user-settings-email-benachrichtigung.component.html', - styleUrls: ['./user-settings-email-benachrichtigung.component.scss'], + selector: 'alfa-user-settings-email-benachrichtigung', + templateUrl: './user-settings-email-benachrichtigung.component.html', + styleUrls: ['./user-settings-email-benachrichtigung.component.scss'], }) export class UserSettingsEmailBenachrichtigungComponent { + @Input() userSettings: StateResource<UserSettingsResource> = + createEmptyStateResource<UserSettingsResource>(); - @Input() userSettings: StateResource<UserSettingsResource> = createEmptyStateResource<UserSettingsResource>(); + @Output() valueChanged: EventEmitter<boolean> = new EventEmitter(); - @Output() valueChanged: EventEmitter<boolean> = new EventEmitter(); + readonly userSettingsLinkRel = UserSettingsLinkRel; - readonly userSettingsLinkRel = UserSettingsLinkRel; - - public isChecked(userSettings: UserSettings): boolean { - return userSettings.notificationsSendFor === NotificationsSendFor.ALL; - } -} \ No newline at end of file + public isChecked(userSettings: UserSettings): boolean { + return userSettings.notificationsSendFor === NotificationsSendFor.ALL; + } +} diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.html b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.html index b4374737442171eb74247356447008f83ce70748..b5c75e65e763c68cd0300190f8c1ff422738c3fc 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.html +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.html @@ -23,4 +23,8 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ozgcloud-icon-button-with-spinner icon="settings" toolTip="Einstellungen" data-test-id="menu-button"></ozgcloud-icon-button-with-spinner> \ No newline at end of file +<ozgcloud-icon-button-with-spinner + icon="settings" + toolTip="Einstellungen" + data-test-id="menu-button" +></ozgcloud-icon-button-with-spinner> diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.scss b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.scss index cfb01d230ea12e3143d5b085e3a441b7ff3b5877..b72d7213d6993a8f359da154e01d6f0154db6a54 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.scss +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.scss @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ ozgcloud-icon-button-with-spinner { - display: block; -} \ No newline at end of file + display: block; +} diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.spec.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.spec.ts index 8e82149c068982b29e2a10f832c9317d98186f83..f8b7705dc59130dfb436934aed1b3a225b409845 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.spec.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.spec.ts @@ -27,23 +27,23 @@ import { MockComponent } from 'ng-mocks'; import { UserSettingsMenuButtonComponent } from './user-settings-menu-button.component'; describe('UserSettingsMenuButtonComponent', () => { - let component: UserSettingsMenuButtonComponent; - let fixture: ComponentFixture<UserSettingsMenuButtonComponent>; + let component: UserSettingsMenuButtonComponent; + let fixture: ComponentFixture<UserSettingsMenuButtonComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - UserSettingsMenuButtonComponent, - MockComponent(IconButtonWithSpinnerComponent) - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + UserSettingsMenuButtonComponent, + MockComponent(IconButtonWithSpinnerComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(UserSettingsMenuButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(UserSettingsMenuButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.ts index 65bb80c7e0f4776b470bbcc315eddfd9c3b1fb8d..5151de3ca312af3db73cc04385d649a4d3c7ee92 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings-menu-button/user-settings-menu-button.component.ts @@ -24,10 +24,8 @@ import { Component } from '@angular/core'; @Component({ - selector: 'alfa-user-settings-menu-button', - templateUrl: './user-settings-menu-button.component.html', - styleUrls: ['./user-settings-menu-button.component.scss'], + selector: 'alfa-user-settings-menu-button', + templateUrl: './user-settings-menu-button.component.html', + styleUrls: ['./user-settings-menu-button.component.scss'], }) -export class UserSettingsMenuButtonComponent { - -} +export class UserSettingsMenuButtonComponent {} diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.html b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.html index f2d51621473931cb3b20852311943f8396aade9c..23880a22fb1b6ebb371a9923d4631b2ae87a4e0c 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.html +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.html @@ -23,12 +23,18 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-user-settings-menu-button [matMenuTriggerFor]="settingsMenu.matMenu" data-test-id="menu-button"></alfa-user-settings-menu-button> +<alfa-user-settings-menu-button + [matMenuTriggerFor]="settingsMenu.matMenu" + data-test-id="menu-button" +></alfa-user-settings-menu-button> <!-- TODO Das Menu in eine eigene Componente auslagern um die Technik zu kapseln --> <ozgcloud-menu #settingsMenu> - <div class="menu-container" (click)="$event.stopPropagation()"> - <alfa-user-settings-email-benachrichtigung-container *ngIf="apiRoot.resource | hasLink: apiRootLinkRel.CURRENT_USER" data-test-id="email-benachrichtigung-toggle"></alfa-user-settings-email-benachrichtigung-container> - <alfa-user-settings-darkmode-container></alfa-user-settings-darkmode-container> - </div> -</ozgcloud-menu> \ No newline at end of file + <div class="menu-container" (click)="$event.stopPropagation()"> + <alfa-user-settings-email-benachrichtigung-container + *ngIf="apiRoot.resource | hasLink: apiRootLinkRel.CURRENT_USER" + data-test-id="email-benachrichtigung-toggle" + ></alfa-user-settings-email-benachrichtigung-container> + <alfa-user-settings-darkmode-container></alfa-user-settings-darkmode-container> + </div> +</ozgcloud-menu> diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.scss b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.scss index 9c92a38994f626abd2e86566fe3100d2a059594e..eb3c6391fbbf2c6947d43e324ef2bc8331550381 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.scss +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.scss @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .menu-container { - margin: 16px; -} \ No newline at end of file + margin: 16px; +} diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.spec.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.spec.ts index 99bf38d096240ae9e77525df00a1bb51719f5a01..532ef326b84d75b6f720d29c825442567847ece7 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.spec.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.spec.ts @@ -25,7 +25,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatButtonModule } from '@angular/material/button'; import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { ApiRootLinkRel } from '@alfa-client/api-root-shared'; -import { HasLinkPipe, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + HasLinkPipe, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { getElementFromDomRoot, getElementFromFixture } from '@alfa-client/test-utils'; import { UiModule } from '@alfa-client/ui'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; @@ -37,57 +41,52 @@ import { UserSettingsMenuButtonComponent } from './user-settings-menu-button/use import { UserSettingsComponent } from './user-settings.component'; describe('UserSettingsComponent', () => { - let component: UserSettingsComponent; - let fixture: ComponentFixture<UserSettingsComponent>; + let component: UserSettingsComponent; + let fixture: ComponentFixture<UserSettingsComponent>; - const menuButton: string = getDataTestIdOf('menu-button'); - const emailBenachrichtigung: string = getDataTestIdOf('email-benachrichtigung-toggle'); + const menuButton: string = getDataTestIdOf('menu-button'); + const emailBenachrichtigung: string = getDataTestIdOf('email-benachrichtigung-toggle'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - MatButtonModule, - UiModule - ], - declarations: [ - HasLinkPipe, - UserSettingsComponent, - MockComponent(UserSettingsMenuButtonComponent), - MockComponent(UserSettingsEmailBenachrichtigungContainerComponent), - MockComponent(UserSettingsDarkmodeContainerComponent), - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [NoopAnimationsModule, MatButtonModule, UiModule], + declarations: [ + HasLinkPipe, + UserSettingsComponent, + MockComponent(UserSettingsMenuButtonComponent), + MockComponent(UserSettingsEmailBenachrichtigungContainerComponent), + MockComponent(UserSettingsDarkmodeContainerComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(UserSettingsComponent); - component = fixture.componentInstance; - component.apiRoot = createEmptyStateResource() - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(UserSettingsComponent); + component = fixture.componentInstance; + component.apiRoot = createEmptyStateResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('Toggle for "email benachrichtigung"', () => { + describe('Toggle for "email benachrichtigung"', () => { + it('should show if link exists', () => { + component.apiRoot = createStateResource(createApiRootResource([ApiRootLinkRel.CURRENT_USER])); + fixture.detectChanges(); - it('should show if link exists', () => { - component.apiRoot = createStateResource(createApiRootResource([ApiRootLinkRel.CURRENT_USER])); - fixture.detectChanges(); + getElementFromFixture(fixture, menuButton).click(); + const element = getElementFromDomRoot(fixture, emailBenachrichtigung); - getElementFromFixture(fixture, menuButton).click(); - const element = getElementFromDomRoot(fixture, emailBenachrichtigung); + expect(element).toBeInTheDocument(); + }); - expect(element).toBeInTheDocument(); - }) + it('should hide if link not exists', () => { + component.apiRoot = createStateResource(createApiRootResource()); - it('should hide if link not exists', () => { - component.apiRoot = createStateResource(createApiRootResource()); + getElementFromFixture(fixture, menuButton).click(); + const element = getElementFromDomRoot(fixture, emailBenachrichtigung); - getElementFromFixture(fixture, menuButton).click(); - const element = getElementFromDomRoot(fixture, emailBenachrichtigung); - - expect(element).not.toBeInTheDocument(); - }) - }) -}); \ No newline at end of file + expect(element).not.toBeInTheDocument(); + }); + }); +}); diff --git a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.ts b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.ts index b1ef358b4760642d6d568e9a4becfd2d3342d439..4ab02e278fe7338668f91f93a4c5d7ccf2babe8f 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings-container/user-settings/user-settings.component.ts @@ -26,13 +26,12 @@ import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; import { StateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-user-settings', - templateUrl: './user-settings.component.html', - styleUrls: ['./user-settings.component.scss'], + selector: 'alfa-user-settings', + templateUrl: './user-settings.component.html', + styleUrls: ['./user-settings.component.scss'], }) export class UserSettingsComponent { + @Input() apiRoot: StateResource<ApiRootResource>; - @Input() apiRoot: StateResource<ApiRootResource>; - - readonly apiRootLinkRel = ApiRootLinkRel; -} \ No newline at end of file + readonly apiRootLinkRel = ApiRootLinkRel; +} diff --git a/alfa-client/libs/user-settings/src/lib/user-settings.module.ts b/alfa-client/libs/user-settings/src/lib/user-settings.module.ts index 3c1f77c040b99ec0ccd6bf47afd398db44d247c1..ad98409aa31cae49637c31ef41cc4726ba9a39dc 100644 --- a/alfa-client/libs/user-settings/src/lib/user-settings.module.ts +++ b/alfa-client/libs/user-settings/src/lib/user-settings.module.ts @@ -34,23 +34,16 @@ import { UserSettingsMenuButtonComponent } from './user-settings-container/user- import { UserSettingsComponent } from './user-settings-container/user-settings/user-settings.component'; @NgModule({ - imports: [ - CommonModule, - UiModule, - UserSettingsSharedModule - ], - declarations: [ - UserSettingsContainerComponent, - UserSettingsEmailBenachrichtigungComponent, - UserSettingsDarkmodeComponent, - UserSettingsComponent, - UserSettingsDarkmodeContainerComponent, - UserSettingsEmailBenachrichtigungContainerComponent, - UserSettingsMenuButtonComponent, - ], - exports: [ - UserSettingsContainerComponent, - UserSettingsEmailBenachrichtigungComponent, - ], + imports: [CommonModule, UiModule, UserSettingsSharedModule], + declarations: [ + UserSettingsContainerComponent, + UserSettingsEmailBenachrichtigungComponent, + UserSettingsDarkmodeComponent, + UserSettingsComponent, + UserSettingsDarkmodeContainerComponent, + UserSettingsEmailBenachrichtigungContainerComponent, + UserSettingsMenuButtonComponent, + ], + exports: [UserSettingsContainerComponent, UserSettingsEmailBenachrichtigungComponent], }) -export class UserSettingsModule { } +export class UserSettingsModule {} diff --git a/alfa-client/libs/user-settings/src/test-setup.ts b/alfa-client/libs/user-settings/src/test-setup.ts index 5870fdabb6470fd0f6f3f63be3d4f6b8041b4dd2..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/user-settings/src/test-setup.ts +++ b/alfa-client/libs/user-settings/src/test-setup.ts @@ -26,17 +26,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/user-settings/tsconfig.json b/alfa-client/libs/user-settings/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/user-settings/tsconfig.json +++ b/alfa-client/libs/user-settings/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/user-settings/tsconfig.lib.json b/alfa-client/libs/user-settings/tsconfig.lib.json index ead8f8bdba5aca4d713f65c9003b06695a69c2f4..2e762bd23944def694724f2ce7c0ea2d922ae1e5 100644 --- a/alfa-client/libs/user-settings/tsconfig.lib.json +++ b/alfa-client/libs/user-settings/tsconfig.lib.json @@ -1,17 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [] - }, - "exclude": [ - "src/test-setup.ts", - "**/*.spec.ts", - "**/*.test.ts", - "jest.config.ts" - ], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "**/*.test.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/user-settings/tsconfig.spec.json b/alfa-client/libs/user-settings/tsconfig.spec.json index 8aebb990f5ab78e0220092403b1217ead2e8fa94..a6ea32cf1965d401df75804a35fdcab4ad04ef0e 100644 --- a/alfa-client/libs/user-settings/tsconfig.spec.json +++ b/alfa-client/libs/user-settings/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["jest.config.ts", "**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] } diff --git a/alfa-client/libs/vorgang-detail/.eslintrc.json b/alfa-client/libs/vorgang-detail/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/vorgang-detail/.eslintrc.json +++ b/alfa-client/libs/vorgang-detail/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/vorgang-detail/jest.config.ts b/alfa-client/libs/vorgang-detail/jest.config.ts index bf8b4cd34cfd758ced06747aa02414d6882e2421..b8c2c95d34a248cb0ac80c68a59c52b314f4c869 100644 --- a/alfa-client/libs/vorgang-detail/jest.config.ts +++ b/alfa-client/libs/vorgang-detail/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'vorgang-detail', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/vorgang-detail', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'vorgang-detail', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/vorgang-detail', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/vorgang-detail/project.json b/alfa-client/libs/vorgang-detail/project.json index 0efb232b2bc35fac1ea5bf8ea16efa0e711bfa10..9e095eeb9bb787c94515fe056937d5e7c18e1a27 100644 --- a/alfa-client/libs/vorgang-detail/project.json +++ b/alfa-client/libs/vorgang-detail/project.json @@ -1,34 +1,31 @@ { - "name": "vorgang-detail", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/vorgang-detail/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/vorgang-detail/src/**/*.ts", - "libs/vorgang-detail/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/vorgang-detail/tsconfig.spec.json", - "jestConfig": "libs/vorgang-detail/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/vorgang-detail"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "vorgang-detail", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/vorgang-detail/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/vorgang-detail/src/**/*.ts", "libs/vorgang-detail/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/vorgang-detail/tsconfig.spec.json", + "jestConfig": "libs/vorgang-detail/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/vorgang-detail"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.html b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.html index 7b4d7ee0b95c53eda80ee0857dbee378a3496067..fe70c506296b595571471270225b09b6cef35e44 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.html @@ -1,42 +1,51 @@ <h1 mat-dialog-title data-test-id="aktenzeichen-edit-dialog-header">Aktenzeichen bearbeiten</h1> <form class="form" [formGroup]="formService.form" (ngSubmit)="onSubmit()"> - <mat-dialog-content> - <div class="content"> - <mat-icon svgIcon="az" class="az_icon" [class.az_icon--active]="hasAktenzeichen$ | async"></mat-icon> - <ozgcloud-text-editor - class="az_text" - data-test-id="aktenzeichen-edit-dialog-text-editor" - label="Aktenzeichen" - placeholder="kein Aktenzeichen" - [autoFocus]="true" - [clearable]="true" - appearance="outline" - subscriptSizing="dynamic" - [formControlName]="AktenzeichenEditDialogFormservice.AKTENZEICHEN_FIELD"> - </ozgcloud-text-editor> - <ozgcloud-paste-text-button - class="paste_icon" - tooltip="Text aus Zwischenablage einfügen" - (pasteEmitter)="paste($event)"> - </ozgcloud-paste-text-button> - <p class="hinweis">Bitte geben Sie ein Aktenzeichen ein. (max. 256 Zeichen)</p> - </div> - </mat-dialog-content> - <mat-dialog-actions> - <ozgcloud-stroked-button-with-spinner - data-test-id="aktenzeichen-edit-dialog-confirmation-button" - text="Änderungen speichern" - type="submit" - icon="save_alt" - [stateResource]="setAktenzeichenPending$ | async"> - </ozgcloud-stroked-button-with-spinner> + <mat-dialog-content> + <div class="content"> + <mat-icon + svgIcon="az" + class="az_icon" + [class.az_icon--active]="hasAktenzeichen$ | async" + ></mat-icon> + <ozgcloud-text-editor + class="az_text" + data-test-id="aktenzeichen-edit-dialog-text-editor" + label="Aktenzeichen" + placeholder="kein Aktenzeichen" + [autoFocus]="true" + [clearable]="true" + appearance="outline" + subscriptSizing="dynamic" + [formControlName]="AktenzeichenEditDialogFormservice.AKTENZEICHEN_FIELD" + > + </ozgcloud-text-editor> + <ozgcloud-paste-text-button + class="paste_icon" + tooltip="Text aus Zwischenablage einfügen" + data-test-id="aktenzeichen-paste-clipboard" + (pasteEmitter)="paste($event)" + > + </ozgcloud-paste-text-button> + <p class="hinweis">Bitte geben Sie ein Aktenzeichen ein. (max. 256 Zeichen)</p> + </div> + </mat-dialog-content> + <mat-dialog-actions> + <ozgcloud-stroked-button-with-spinner + data-test-id="aktenzeichen-edit-dialog-confirmation-button" + text="Änderungen speichern" + type="submit" + icon="save_alt" + [stateResource]="setAktenzeichenPending$ | async" + > + </ozgcloud-stroked-button-with-spinner> - <ozgcloud-stroked-button-with-spinner - data-test-id="aktenzeichen-edit-dialog-cancel-button" - text="Abbrechen" - color="" - icon="clear" - (clickEmitter)="onCancel()"> - </ozgcloud-stroked-button-with-spinner> - </mat-dialog-actions> -</form> \ No newline at end of file + <ozgcloud-stroked-button-with-spinner + data-test-id="aktenzeichen-edit-dialog-cancel-button" + text="Abbrechen" + color="" + icon="clear" + (clickEmitter)="onCancel()" + > + </ozgcloud-stroked-button-with-spinner> + </mat-dialog-actions> +</form> diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.scss b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.scss index b7b2aa656dafbd136d784835f7dc0e12fdeaf81c..b61ea6c2be7bb5ea25305e910e0a68287228372b 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.scss @@ -1,69 +1,69 @@ @import 'variables'; .form { - width: 100%; + width: 100%; - ::ng-deep mat-form-field { - width: 100%; - } + ::ng-deep mat-form-field { + width: 100%; + } } .content { - display: grid; - grid-template-columns: min-content auto min-content; - grid-column-gap: 0.5rem; - grid-row-gap: 0.25rem; - align-items: flex-start; - grid-template-areas: - 'az_icon az_text paste_icon' - '. hinweis .'; + display: grid; + grid-template-columns: min-content auto min-content; + grid-column-gap: 0.5rem; + grid-row-gap: 0.25rem; + align-items: flex-start; + grid-template-areas: + 'az_icon az_text paste_icon' + '. hinweis .'; } .az_icon { - grid-area: az_icon; - color: $darkModeGreyLight; - margin-top: 12px; + grid-area: az_icon; + color: $darkModeGreyLight; + margin-top: 12px; - &--active { - color: black; - } + &--active { + color: black; + } } :host-context(.dark) { - .az_icon { - color: $darkModeGreyLight; + .az_icon { + color: $darkModeGreyLight; - &--active { - color: white; - } - } + &--active { + color: white; + } + } } .az_text { - grid-area: az_text; + grid-area: az_text; } .paste_icon { - grid-area: paste_icon; + grid-area: paste_icon; } .hinweis { - grid-area: hinweis; - padding-left: 16px; - font-size: 14px; + grid-area: hinweis; + padding-left: 16px; + font-size: 14px; } ozgcloud-stroked-button-with-spinner { - margin-right: 1rem; + margin-right: 1rem; } mat-icon { - height: 1.875rem; - min-height: 1.875rem; - width: 1.875rem; - min-width: 1.875rem; + height: 1.875rem; + min-height: 1.875rem; + width: 1.875rem; + min-width: 1.875rem; } mat-dialog-content { - padding-top: 0.5rem !important; + padding-top: 0.5rem !important; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.ts index a4a889ba613ac86b99ed4bdfedcce4606707a958..365d49838c5da700f325bc3ff4d0917f4ab8f5d1 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component.ts @@ -1,5 +1,15 @@ -import { COMMAND_ERROR_MESSAGES, CommandResource, hasError, isSuccessfulDone } from '@alfa-client/command-shared'; -import { StateResource, createEmptyStateResource, hasContent, isClipboardReadSupported } from '@alfa-client/tech-shared'; +import { + COMMAND_ERROR_MESSAGES, + CommandResource, + hasError, + isSuccessfulDone, +} from '@alfa-client/command-shared'; +import { + StateResource, + createEmptyStateResource, + hasContent, + isClipboardReadSupported, +} from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { Component, Inject, OnInit } from '@angular/core'; @@ -10,70 +20,80 @@ import { AktenzeichenEditDialogFormservice } from './aktenzeichen-edit-dialog.fo import { AktenzeichenEditDialogMessages } from './aktenzeichen-edit-dialog.message'; @Component({ - selector: 'alfa-aktenzeichen-edit-dialog', - templateUrl: './aktenzeichen-edit-dialog.component.html', - styleUrls: ['./aktenzeichen-edit-dialog.component.scss'], - providers: [AktenzeichenEditDialogFormservice] + selector: 'alfa-aktenzeichen-edit-dialog', + templateUrl: './aktenzeichen-edit-dialog.component.html', + styleUrls: ['./aktenzeichen-edit-dialog.component.scss'], + providers: [AktenzeichenEditDialogFormservice], }) export class AktenzeichenEditDialogComponent implements OnInit { + vorgang: VorgangWithEingangResource; - vorgang: VorgangWithEingangResource; + setAktenzeichenPending$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); + hasAktenzeichen$: Observable<boolean>; + isPasteSupported = false; - setAktenzeichenPending$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); - hasAktenzeichen$: Observable<boolean>; - isPasteSupported = false; + protected readonly AktenzeichenEditDialogFormservice = AktenzeichenEditDialogFormservice; - protected readonly AktenzeichenEditDialogFormservice = AktenzeichenEditDialogFormservice; + constructor( + public formService: AktenzeichenEditDialogFormservice, + private readonly snackbarService: SnackBarService, + private readonly vorgangService: VorgangService, + public dialogRef: MatDialogRef<AktenzeichenEditDialogComponent>, + @Inject(MAT_DIALOG_DATA) public data: AktenzeichenEditDialogData, + ) { + this.vorgang = data.vorgang; + } - constructor( - public formService: AktenzeichenEditDialogFormservice, - private readonly snackbarService: SnackBarService, - private readonly vorgangService: VorgangService, - public dialogRef: MatDialogRef<AktenzeichenEditDialogComponent>, - @Inject(MAT_DIALOG_DATA) public data: AktenzeichenEditDialogData, - ) { - this.vorgang = data.vorgang; - } + ngOnInit(): void { + this.isPasteSupported = isClipboardReadSupported(); + this.formService.setAktenzeichen(this.vorgang.aktenzeichen); + this.hasAktenzeichen$ = this.formService + .valueChanges() + .pipe(startWith(this.vorgang.aktenzeichen)) + .pipe(map(hasContent)); + } - ngOnInit(): void { - this.isPasteSupported = isClipboardReadSupported(); - this.formService.setAktenzeichen(this.vorgang.aktenzeichen); - this.hasAktenzeichen$ = this.formService.valueChanges() - .pipe(startWith(this.vorgang.aktenzeichen)) - .pipe(map(hasContent)); - } + public onCancel(): void { + this.dialogRef.close(); + } - public onCancel(): void { - this.dialogRef.close(); - } + public onSubmit(): void { + this.formService.setVorgangWithEingangResource(this.vorgang); + this.setAktenzeichenPending$ = this.formService + .submit() + .pipe(startWith(createEmptyStateResource<CommandResource>(true))) + .pipe( + tap((commandStateResource: StateResource<CommandResource>) => + this.onResponse(commandStateResource.resource), + ), + ); + } - public onSubmit(): void { - this.formService.setVorgangWithEingangResource(this.vorgang); - this.setAktenzeichenPending$ = this.formService.submit() - .pipe(startWith(createEmptyStateResource<CommandResource>(true))) - .pipe(tap((commandStateResource: StateResource<CommandResource>) => this.onResponse(commandStateResource.resource))); - } + onResponse(commandResource: CommandResource) { + if (commandResource && hasError(commandResource)) { + this.showSnackbar(commandResource); + } else if (isSuccessfulDone(commandResource)) { + this.vorgangService.reloadCurrentVorgang(); + this.dialogRef.close(); + } + } - onResponse(commandResource: CommandResource) { - if (commandResource && hasError(commandResource)) { - this.showSnackbar(commandResource); - } else if (isSuccessfulDone(commandResource)) { - this.vorgangService.reloadCurrentVorgang(); - this.dialogRef.close(); - } - } + private showSnackbar(commandResource: CommandResource): void { + if (hasError(commandResource)) { + this.snackbarService.showError(this.getErrorMessage(commandResource)); + } + } - private showSnackbar(commandResource: CommandResource): void { - if (hasError(commandResource)) { - this.snackbarService.showError(this.getErrorMessage(commandResource)); - } - } + private getErrorMessage(commandResource: CommandResource): string { + return ( + COMMAND_ERROR_MESSAGES[commandResource.errorMessage] || + AktenzeichenEditDialogMessages.SET_FAILED + ); + } - private getErrorMessage(commandResource: CommandResource): string { - return COMMAND_ERROR_MESSAGES[commandResource.errorMessage] || AktenzeichenEditDialogMessages.SET_FAILED; - } - - paste(clipboardContent: string) { - this.formService.setAktenzeichen(clipboardContent); - } + paste(clipboardContent: string) { + this.formService.setAktenzeichen(clipboardContent); + } } diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.data.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.data.ts index 166b7135c79c1f3972f154bdc54b27de59f8a515..9f9d7686f38bce5a70cabf8ebcb5c1305d3c965e 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.data.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.data.ts @@ -1,5 +1,5 @@ import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; export interface AktenzeichenEditDialogData { - vorgang: VorgangWithEingangResource; -} \ No newline at end of file + vorgang: VorgangWithEingangResource; +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.ts index 93e52ab0ca389df5eafc337d2cfe32fa969061ac..93b14879d0612c67adad7af5ceec947e4df552c3 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.formservice.ts @@ -8,52 +8,55 @@ import { Resource } from '@ngxp/rest'; @Injectable() export class AktenzeichenEditDialogFormservice extends AbstractFormService { - - static readonly AKTENZEICHEN_FIELD = 'aktenzeichen'; - - private vorgang: VorgangWithEingangResource; - - constructor(formBuilder: UntypedFormBuilder, private readonly vorgangService: VorgangService) { - super(formBuilder); - } - - protected initForm(): UntypedFormGroup { - return this.formBuilder.group({ - [AktenzeichenEditDialogFormservice.AKTENZEICHEN_FIELD]: new UntypedFormControl(null) - }); - } - - protected doSubmit(): Observable<StateResource<Resource>> { - return this.vorgangService.setAktenzeichen(this.vorgang, this.getValue()); - } - - protected getPathPrefix(): string { - return AktenzeichenEditDialogFormservice.AKTENZEICHEN_FIELD; - } - - private getAktenzeichenFormControl(): UntypedFormControl { - return this.getFormControl(); - } - - public getValue(): string { - const value: string = this.getAktenzeichenFormControl().value; - return isEmpty(value) ? null : value.trim(); - } - - public setVorgangWithEingangResource(vorgang: VorgangWithEingangResource): void { - this.vorgang = vorgang; - } - - public setAktenzeichen(aktenzeichen: string): void { - this.getFormControl().setValue(aktenzeichen); - } - - public valueChanges():Observable<any> { - return this.getFormControl().valueChanges; - } - - private getFormControl(): UntypedFormControl { - return <UntypedFormControl>this.form.controls[AktenzeichenEditDialogFormservice.AKTENZEICHEN_FIELD]; - } - -} \ No newline at end of file + static readonly AKTENZEICHEN_FIELD = 'aktenzeichen'; + + private vorgang: VorgangWithEingangResource; + + constructor( + formBuilder: UntypedFormBuilder, + private readonly vorgangService: VorgangService, + ) { + super(formBuilder); + } + + protected initForm(): UntypedFormGroup { + return this.formBuilder.group({ + [AktenzeichenEditDialogFormservice.AKTENZEICHEN_FIELD]: new UntypedFormControl(null), + }); + } + + protected doSubmit(): Observable<StateResource<Resource>> { + return this.vorgangService.setAktenzeichen(this.vorgang, this.getValue()); + } + + protected getPathPrefix(): string { + return AktenzeichenEditDialogFormservice.AKTENZEICHEN_FIELD; + } + + private getAktenzeichenFormControl(): UntypedFormControl { + return this.getFormControl(); + } + + public getValue(): string { + const value: string = this.getAktenzeichenFormControl().value; + return isEmpty(value) ? null : value.trim(); + } + + public setVorgangWithEingangResource(vorgang: VorgangWithEingangResource): void { + this.vorgang = vorgang; + } + + public setAktenzeichen(aktenzeichen: string): void { + this.getFormControl().setValue(aktenzeichen); + } + + public valueChanges(): Observable<any> { + return this.getFormControl().valueChanges; + } + + private getFormControl(): UntypedFormControl { + return <UntypedFormControl>( + this.form.controls[AktenzeichenEditDialogFormservice.AKTENZEICHEN_FIELD] + ); + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.message.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.message.ts index 86eaec13c2792bef36834189a9f698d27ba8af6c..be162cfb14775b8e8f1f7a5aea55aa141a628394 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.message.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.message.ts @@ -1,3 +1,3 @@ export enum AktenzeichenEditDialogMessages { - SET_FAILED = 'Aktenzeichen konnte nicht gespeichert werden.' -} \ No newline at end of file + SET_FAILED = 'Aktenzeichen konnte nicht gespeichert werden.', +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.html b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.html index 1d078b33608b5decfc4b631d2db21be15734737c..12e280dd9853ea90cd3db02843929d801bf39301 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.html @@ -24,8 +24,13 @@ --> <div class="horizontal"> - <div alfa-aktenzeichen class="ellipsis" [vorgang]="vorgang" data-test-id="aktenzeichen"></div> - <ng-container *ngIf="vorgang | hasLink: linkRel.SET_AKTENZEICHEN"> - <ozgcloud-icon-button-primary svgIcon="edit" tooltip="Aktenzeichen bearbeiten" (clickEmitter)="onEdit()"></ozgcloud-icon-button-primary> - </ng-container> -</div> \ No newline at end of file + <div alfa-aktenzeichen class="ellipsis" [vorgang]="vorgang"></div> + <ng-container *ngIf="vorgang | hasLink: linkRel.SET_AKTENZEICHEN"> + <ozgcloud-icon-button-primary + svgIcon="edit" + tooltip="Aktenzeichen bearbeiten" + data-test-id="aktenzeichen-editieren" + (clickEmitter)="onEdit()" + ></ozgcloud-icon-button-primary> + </ng-container> +</div> diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.scss b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.scss index bca48d71779df609342d15745d82b1fd453d7eb5..be66b5c81cdb771090d274585ae82dfe028a4b6d 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.scss @@ -23,20 +23,20 @@ */ .horizontal { - display: flex; - align-items: center; - font-size: 16px; - font-weight: 300; + display: flex; + align-items: center; + font-size: 16px; + font-weight: 300; } .ellipsis { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } // Workaround Material's fixed 48px height :host ::ng-deep ozgcloud-icon-button-primary button { - position: absolute; - top: -24px; -} \ No newline at end of file + position: absolute; + top: -24px; +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.spec.ts index 8e42bfaa46182b1c7eb5170ebc8d28061b8c8243..0c89af4e82cab281dd3dcd6afe2c8cab28a6574c 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.spec.ts @@ -34,69 +34,69 @@ import { createEmptyStateResource, HasLinkPipe } from '@alfa-client/tech-shared' import { VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; describe('AktenzeichenComponent', () => { - let component: AktenzeichenEditableComponent; - let fixture: ComponentFixture<AktenzeichenEditableComponent>; - - const dialogService = mock(DialogService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HasLinkPipe, - AktenzeichenEditableComponent, - MockComponent(OzgcloudIconButtonPrimaryComponent), - MockComponent(AktenzeichenComponent), - ], - providers: [ - { - provide: DialogService, - useValue: dialogService - } - ] - }).compileComponents(); - }) - - beforeEach(() => { - fixture = TestBed.createComponent(AktenzeichenEditableComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }) - - it('should create', () => { - expect(component).toBeTruthy(); - }) - - describe('onEdit', () => { - - it('should open dialog', () => { - const vorgang = createVorgangWithEingangResource(); - component.vorgang = vorgang; - - component.onEdit(); - - expect(dialogService.openWidely).toHaveBeenCalledWith(AktenzeichenEditDialogComponent, { data: { vorgang: vorgang, } }); - - }) - }) - - describe('after render', () => { - it('should render edit button', () => { - const editIcon = fixture.nativeElement.querySelector('ozgcloud-icon-button-primary'); - - fixture.detectChanges(); - - expect(editIcon).not.toBeInstanceOf(HTMLElement); - }) - - it('should render edit button', () => { - const vorgang = createVorgangWithEingangResource(); - vorgang._links[VorgangWithEingangLinkRel.SET_AKTENZEICHEN] = { href: 'http' } - component.vorgang = vorgang; - - fixture.detectChanges(); - - const editIcon = fixture.nativeElement.querySelector('ozgcloud-icon-button-primary'); - expect(editIcon).toBeInstanceOf(HTMLElement); - }) - }) -}) + let component: AktenzeichenEditableComponent; + let fixture: ComponentFixture<AktenzeichenEditableComponent>; + + const dialogService = mock(DialogService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HasLinkPipe, + AktenzeichenEditableComponent, + MockComponent(OzgcloudIconButtonPrimaryComponent), + MockComponent(AktenzeichenComponent), + ], + providers: [ + { + provide: DialogService, + useValue: dialogService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AktenzeichenEditableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('onEdit', () => { + it('should open dialog', () => { + const vorgang = createVorgangWithEingangResource(); + component.vorgang = vorgang; + + component.onEdit(); + + expect(dialogService.openWidely).toHaveBeenCalledWith(AktenzeichenEditDialogComponent, { + data: { vorgang: vorgang }, + }); + }); + }); + + describe('after render', () => { + it('should render edit button', () => { + const editIcon = fixture.nativeElement.querySelector('ozgcloud-icon-button-primary'); + + fixture.detectChanges(); + + expect(editIcon).not.toBeInstanceOf(HTMLElement); + }); + + it('should render edit button', () => { + const vorgang = createVorgangWithEingangResource(); + vorgang._links[VorgangWithEingangLinkRel.SET_AKTENZEICHEN] = { href: 'http' }; + component.vorgang = vorgang; + + fixture.detectChanges(); + + const editIcon = fixture.nativeElement.querySelector('ozgcloud-icon-button-primary'); + expect(editIcon).toBeInstanceOf(HTMLElement); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.ts b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.ts index 5a13bd21d496a3a346eb84f19a4020fa55068be1..0b7c225ce89af017ffe0f15b00511cd859deb0e8 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/aktenzeichen-editable/aktenzeichen-editable.component.ts @@ -27,20 +27,20 @@ import { DialogService } from '@alfa-client/ui'; import { AktenzeichenEditDialogComponent } from '../aktenzeichen-edit-dialog/aktenzeichen-edit-dialog.component'; @Component({ - selector: 'alfa-aktenzeichen-editable', - templateUrl: './aktenzeichen-editable.component.html', - styleUrls: ['./aktenzeichen-editable.component.scss'] + selector: 'alfa-aktenzeichen-editable', + templateUrl: './aktenzeichen-editable.component.html', + styleUrls: ['./aktenzeichen-editable.component.scss'], }) export class AktenzeichenEditableComponent { + @Input() vorgang: VorgangWithEingangResource; - @Input() vorgang: VorgangWithEingangResource; + constructor(private readonly dialogService: DialogService) {} - constructor(private readonly dialogService: DialogService) { - } + public onEdit(): void { + this.dialogService.openWidely(AktenzeichenEditDialogComponent, { + data: { vorgang: this.vorgang }, + }); + } - public onEdit(): void { - this.dialogService.openWidely(AktenzeichenEditDialogComponent, { data: { vorgang: this.vorgang, } }); - } - - protected readonly linkRel = VorgangWithEingangLinkRel; + protected readonly linkRel = VorgangWithEingangLinkRel; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.html index fe9fbd96d29589b825f65c8e0f374f557cce5bf3..be0c599a5b7e04df8b03cbe0c51568aed474e709 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.html @@ -24,19 +24,23 @@ --> <ng-container *ngIf="vorgang | hasLink: linkRel.ABSCHLIESSEN"> - - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="abschliessen-button" - text="Abschließen" - icon="done" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="abschliessen()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="abschliessen-icon-button" - icon="done" - toolTip="Vorgang abschließen" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="abschliessen()"> - </ozgcloud-icon-button-with-spinner> - -</ng-container> \ No newline at end of file + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="abschliessen-button" + text="Abschließen" + icon="done" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="abschliessen()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="abschliessen-icon-button" + icon="done" + toolTip="Vorgang abschließen" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="abschliessen()" + > + </ozgcloud-icon-button-with-spinner> +</ng-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.spec.ts index 5ed268acf1c2f63fc73a1514e52663addc3b26e0..1dd2e6701baba2c50028dbfdfa9c215359e7ef06 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.spec.ts @@ -24,7 +24,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; import { createCommandResource } from 'libs/command-shared/test/command'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -34,108 +37,111 @@ import { of } from 'rxjs'; import { AbschliessenButtonComponent } from './abschliessen-button.component'; describe('AbschliessenButtonComponent', () => { - let component: AbschliessenButtonComponent; - let fixture: ComponentFixture<AbschliessenButtonComponent>; - - const abschliessenButton: string = getDataTestIdOf('abschliessen-button'); - const abschliessenIconButton: string = getDataTestIdOf('abschliessen-icon-button'); - - const vorgangCommandService = { ...mock(VorgangCommandService), getCommandStateResources: () => of(createStateResource(createCommandResource())) }; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - AbschliessenButtonComponent, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent), - HasLinkPipe - ], - providers: [ - { - provide: VorgangCommandService, - useValue: vorgangCommandService - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(AbschliessenButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call service', () => { - component.ngOnInit(); - - expect(vorgangCommandService.getAbschliessenCommand).toHaveBeenCalled(); - }) - }) - - describe('abschliessen', () => { - - it('should call vorgang service', () => { - component.abschliessen(); - - expect(vorgangCommandService.abschliessen).toHaveBeenCalled(); - }) - }) - - describe('abschliessen button', () => { - - beforeEach(() => { - component.showAsIconButton = false; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(abschliessenButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ABSCHLIESSEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(abschliessenButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) - - describe('abschliessen icon button', () => { - - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(abschliessenIconButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ABSCHLIESSEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(abschliessenIconButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) + let component: AbschliessenButtonComponent; + let fixture: ComponentFixture<AbschliessenButtonComponent>; + + const abschliessenButton: string = getDataTestIdOf('abschliessen-button'); + const abschliessenIconButton: string = getDataTestIdOf('abschliessen-icon-button'); + + const vorgangCommandService = { + ...mock(VorgangCommandService), + getCommandStateResources: () => of(createStateResource(createCommandResource())), + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + AbschliessenButtonComponent, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + HasLinkPipe, + ], + providers: [ + { + provide: VorgangCommandService, + useValue: vorgangCommandService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AbschliessenButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call service', () => { + component.ngOnInit(); + + expect(vorgangCommandService.getAbschliessenCommand).toHaveBeenCalled(); + }); + }); + + describe('abschliessen', () => { + it('should call vorgang service', () => { + component.abschliessen(); + + expect(vorgangCommandService.abschliessen).toHaveBeenCalled(); + }); + }); + + describe('abschliessen button', () => { + beforeEach(() => { + component.showAsIconButton = false; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(abschliessenButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.ABSCHLIESSEN, + ]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(abschliessenButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); + + describe('abschliessen icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(abschliessenIconButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.ABSCHLIESSEN, + ]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(abschliessenIconButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.ts index 3790f6c89a95002bf0eaf46ba46a48ba71e8e42f..f4dafed5cdc6da7afcec0f200722405e281d1e17 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/abschliessen-button/abschliessen-button.component.ts @@ -24,30 +24,35 @@ import { Component, Input, OnInit } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; -import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangCommandService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-abschliessen-button', - templateUrl: './abschliessen-button.component.html', - styleUrls: ['./abschliessen-button.component.scss'] + selector: 'alfa-abschliessen-button', + templateUrl: './abschliessen-button.component.html', + styleUrls: ['./abschliessen-button.component.scss'], }) export class AbschliessenButtonComponent implements OnInit { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean = false; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean = false; + commandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = VorgangWithEingangLinkRel; - readonly linkRel = VorgangWithEingangLinkRel; + constructor(private vorgangCommandService: VorgangCommandService) {} - constructor(private vorgangCommandService: VorgangCommandService) { } + ngOnInit(): void { + this.commandStateResource$ = this.vorgangCommandService.getAbschliessenCommand(); + } - ngOnInit(): void { - this.commandStateResource$ = this.vorgangCommandService.getAbschliessenCommand(); - } - - public abschliessen(): void { - this.vorgangCommandService.abschliessen(this.vorgang); - } -} \ No newline at end of file + public abschliessen(): void { + this.vorgangCommandService.abschliessen(this.vorgang); + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.html index b3dab7af2dec209398318dd66829f56f05b4628e..4f630870be2e40cf4feac339d162649f63c62e86 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.html @@ -24,19 +24,23 @@ --> <ng-container *ngIf="vorgang | hasLink: linkRel.ANNEHMEN"> - - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="annehmen-button" - text="Annehmen" - icon="check_circle_outline" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="annehmen()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="annehmen-icon-button" - icon="check_circle_outline" - toolTip="Vorgang annehmen" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="annehmen()"> - </ozgcloud-icon-button-with-spinner> - -</ng-container> \ No newline at end of file + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="annehmen-button" + text="Annehmen" + icon="check_circle_outline" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="annehmen()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="annehmen-icon-button" + icon="check_circle_outline" + toolTip="Vorgang annehmen" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="annehmen()" + > + </ozgcloud-icon-button-with-spinner> +</ng-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.spec.ts index 3da6c72b07927a67aefdde25a89537c4868c98a0..aeb1fc630c885ad740a6be565293c97f69f4be19 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.spec.ts @@ -24,7 +24,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; import { createCommandResource } from 'libs/command-shared/test/command'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -34,108 +37,107 @@ import { of } from 'rxjs'; import { AnnehmenButtonComponent } from './annehmen-button.component'; describe('AnnehmenButtonComponent', () => { - let component: AnnehmenButtonComponent; - let fixture: ComponentFixture<AnnehmenButtonComponent>; - - const annehmenButton: string = getDataTestIdOf('annehmen-button'); - const annehmenIconButton: string = getDataTestIdOf('annehmen-icon-button'); - - const vorgangCommandService = { ...mock(VorgangCommandService), getCommandStateResources: () => of(createStateResource(createCommandResource())) }; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - AnnehmenButtonComponent, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent), - HasLinkPipe - ], - providers: [ - { - provide: VorgangCommandService, - useValue: vorgangCommandService - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(AnnehmenButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call service', () => { - component.ngOnInit(); - - expect(vorgangCommandService.getAnnehmenCommand).toHaveBeenCalled(); - }) - }) - - describe('annehmen', () => { - - it('should call vorgang service', () => { - component.annehmen(); - - expect(vorgangCommandService.annehmen).toHaveBeenCalled(); - }) - }) - - describe('annehmen button', () => { - - beforeEach(() => { - component.showAsIconButton = false; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(annehmenButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ANNEHMEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(annehmenButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) - - describe('annehmen icon button', () => { - - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(annehmenIconButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ANNEHMEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(annehmenIconButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) + let component: AnnehmenButtonComponent; + let fixture: ComponentFixture<AnnehmenButtonComponent>; + + const annehmenButton: string = getDataTestIdOf('annehmen-button'); + const annehmenIconButton: string = getDataTestIdOf('annehmen-icon-button'); + + const vorgangCommandService = { + ...mock(VorgangCommandService), + getCommandStateResources: () => of(createStateResource(createCommandResource())), + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + AnnehmenButtonComponent, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + HasLinkPipe, + ], + providers: [ + { + provide: VorgangCommandService, + useValue: vorgangCommandService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AnnehmenButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call service', () => { + component.ngOnInit(); + + expect(vorgangCommandService.getAnnehmenCommand).toHaveBeenCalled(); + }); + }); + + describe('annehmen', () => { + it('should call vorgang service', () => { + component.annehmen(); + + expect(vorgangCommandService.annehmen).toHaveBeenCalled(); + }); + }); + + describe('annehmen button', () => { + beforeEach(() => { + component.showAsIconButton = false; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(annehmenButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ANNEHMEN]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(annehmenButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); + + describe('annehmen icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(annehmenIconButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ANNEHMEN]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(annehmenIconButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.ts index 0daf3c9d9061a6b4f15ebcd4f094d2a9bb004a13..1cd16a4371e1a5efbe7f11d5ddc288631e1b0924 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/annehmen-button/annehmen-button.component.ts @@ -24,30 +24,35 @@ import { Component, Input, OnInit } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; -import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangCommandService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-annehmen-button', - templateUrl: './annehmen-button.component.html', - styleUrls: ['./annehmen-button.component.scss'] + selector: 'alfa-annehmen-button', + templateUrl: './annehmen-button.component.html', + styleUrls: ['./annehmen-button.component.scss'], }) export class AnnehmenButtonComponent implements OnInit { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean = false; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean = false; + commandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = VorgangWithEingangLinkRel; - readonly linkRel = VorgangWithEingangLinkRel; + constructor(private vorgangCommandService: VorgangCommandService) {} - constructor(private vorgangCommandService: VorgangCommandService) { } + ngOnInit(): void { + this.commandStateResource$ = this.vorgangCommandService.getAnnehmenCommand(); + } - ngOnInit(): void { - this.commandStateResource$ = this.vorgangCommandService.getAnnehmenCommand(); - } - - public annehmen(): void { - this.vorgangCommandService.annehmen(this.vorgang); - } -} \ No newline at end of file + public annehmen(): void { + this.vorgangCommandService.annehmen(this.vorgang); + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.html index bf082a9ac7f17d15b30dd6f85e86de054084fc55..d0c54c8ed13309f1bcd67227a65f13570947b14f 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.html @@ -24,19 +24,23 @@ --> <ng-container *ngIf="vorgang | hasLink: linkRel.BEARBEITEN"> - - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="bearbeiten-button" - text="Bearbeiten" - icon="edit_icon" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="bearbeiten()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="bearbeiten-icon-button" - svgIcon="edit" - toolTip="Vorgang bearbeiten" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="bearbeiten()"> - </ozgcloud-icon-button-with-spinner> - -</ng-container> \ No newline at end of file + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="bearbeiten-button" + text="Bearbeiten" + icon="edit_icon" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="bearbeiten()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="bearbeiten-icon-button" + svgIcon="edit" + toolTip="Vorgang bearbeiten" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="bearbeiten()" + > + </ozgcloud-icon-button-with-spinner> +</ng-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.spec.ts index c38c1a9b6c2366e86c276bdec9988533bbb58f50..6eaeacf49623c74ca8134fc499ac0beb23283502 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.spec.ts @@ -24,7 +24,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; import { createCommandResource } from 'libs/command-shared/test/command'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; @@ -33,99 +36,99 @@ import { of } from 'rxjs'; import { BearbeitenButtonComponent } from './bearbeiten-button.component'; describe('BearbeitenButtonComponent', () => { - let component: BearbeitenButtonComponent; - let fixture: ComponentFixture<BearbeitenButtonComponent>; - - const bearbeitenButton: string = '[data-test-id="bearbeiten-button"]'; - const bearbeitenIconButton: string = '[data-test-id="bearbeiten-icon-button"]'; - - const vorgangCommandService = { ...mock(VorgangCommandService), getCommandStateResources: () => of(createStateResource(createCommandResource())) }; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - BearbeitenButtonComponent, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent), - HasLinkPipe - ], - providers: [ - { - provide: VorgangCommandService, - useValue: vorgangCommandService - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(BearbeitenButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('bearbeiten', () => { - - it('should call vorgang service', () => { - component.bearbeiten(); - - expect(vorgangCommandService.bearbeiten).toHaveBeenCalled(); - }) - }) - - describe('bearbeiten button', () => { - - beforeEach(() => { - component.showAsIconButton = false; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(bearbeitenButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BEARBEITEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(bearbeitenButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) - - describe('bearbeiten icon button', () => { - - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(bearbeitenIconButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BEARBEITEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(bearbeitenIconButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) + let component: BearbeitenButtonComponent; + let fixture: ComponentFixture<BearbeitenButtonComponent>; + + const bearbeitenButton: string = '[data-test-id="bearbeiten-button"]'; + const bearbeitenIconButton: string = '[data-test-id="bearbeiten-icon-button"]'; + + const vorgangCommandService = { + ...mock(VorgangCommandService), + getCommandStateResources: () => of(createStateResource(createCommandResource())), + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + BearbeitenButtonComponent, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + HasLinkPipe, + ], + providers: [ + { + provide: VorgangCommandService, + useValue: vorgangCommandService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BearbeitenButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('bearbeiten', () => { + it('should call vorgang service', () => { + component.bearbeiten(); + + expect(vorgangCommandService.bearbeiten).toHaveBeenCalled(); + }); + }); + + describe('bearbeiten button', () => { + beforeEach(() => { + component.showAsIconButton = false; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(bearbeitenButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BEARBEITEN]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(bearbeitenButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); + + describe('bearbeiten icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(bearbeitenIconButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BEARBEITEN]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(bearbeitenIconButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.ts index 3d0cf26db35c704caab731569dbda42757ab6011..4e73fe51b2db178fcc83fd0e1f7a1e5472001606 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bearbeiten-button/bearbeiten-button.component.ts @@ -24,30 +24,35 @@ import { Component, Input, OnInit } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; -import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangCommandService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-bearbeiten-button', - templateUrl: './bearbeiten-button.component.html', - styleUrls: ['./bearbeiten-button.component.scss'] + selector: 'alfa-bearbeiten-button', + templateUrl: './bearbeiten-button.component.html', + styleUrls: ['./bearbeiten-button.component.scss'], }) export class BearbeitenButtonComponent implements OnInit { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean = false; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean = false; + commandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = VorgangWithEingangLinkRel; - readonly linkRel = VorgangWithEingangLinkRel; + constructor(private vorgangCommandService: VorgangCommandService) {} - constructor(private vorgangCommandService: VorgangCommandService) { } + ngOnInit(): void { + this.commandStateResource$ = this.vorgangCommandService.getBearbeitenCommand(); + } - ngOnInit(): void { - this.commandStateResource$ = this.vorgangCommandService.getBearbeitenCommand(); - } - - public bearbeiten(): void { - this.vorgangCommandService.bearbeiten(this.vorgang); - } + public bearbeiten(): void { + this.vorgangCommandService.bearbeiten(this.vorgang); + } } diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.html index aad567ea69a91f0f79309c9d0e4d8a6f4fe7c106..629a451eacc28bba3ccdc1bc669f717e65277998 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.html @@ -24,19 +24,23 @@ --> <ng-container *ngIf="vorgang | hasLink: linkRel.BESCHEIDEN"> - - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="bescheiden-button" - text="Bescheiden" - svgIcon="stamp" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="bescheiden()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="bescheiden-icon-button" - svgIcon="stamp" - toolTip="Vorgang bescheiden" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="bescheiden()"> - </ozgcloud-icon-button-with-spinner> - -</ng-container> \ No newline at end of file + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="bescheiden-button" + text="Bescheiden" + svgIcon="stamp" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="bescheiden()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="bescheiden-icon-button" + svgIcon="stamp" + toolTip="Vorgang bescheiden" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="bescheiden()" + > + </ozgcloud-icon-button-with-spinner> +</ng-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts index 76f1bd5b46306d7609d79c8b9318cb3304cca845..38773f6f20de06b2b95dd162e10569240f01d7ee 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.spec.ts @@ -24,7 +24,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; import { createCommandResource } from 'libs/command-shared/test/command'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -34,108 +37,107 @@ import { of } from 'rxjs'; import { BescheidenButtonComponent } from './bescheiden-button.component'; describe('BescheidenButtonComponent', () => { - let component: BescheidenButtonComponent; - let fixture: ComponentFixture<BescheidenButtonComponent>; - - const bescheidenButton: string = getDataTestIdOf('bescheiden-button'); - const bescheidenIconButton: string = getDataTestIdOf('bescheiden-icon-button'); - - const vorgangCommandService = { ...mock(VorgangCommandService), getCommandStateResources: () => of(createStateResource(createCommandResource())) }; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - BescheidenButtonComponent, - HasLinkPipe, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent) - ], - providers: [ - { - provide: VorgangCommandService, - useValue: vorgangCommandService - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(BescheidenButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call service', () => { - component.ngOnInit(); - - expect(vorgangCommandService.getBeschiedenCommand).toHaveBeenCalled(); - }) - }) - - describe('bescheiden', () => { - - it('should call vorgang service', () => { - component.bescheiden(); - - expect(vorgangCommandService.bescheiden).toHaveBeenCalled(); - }) - }) - - describe('bescheiden button', () => { - - beforeEach(() => { - component.showAsIconButton = false; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(bescheidenButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEIDEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(bescheidenButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) - - describe('bescheiden icon button', () => { - - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(bescheidenIconButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEIDEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(bescheidenIconButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) + let component: BescheidenButtonComponent; + let fixture: ComponentFixture<BescheidenButtonComponent>; + + const bescheidenButton: string = getDataTestIdOf('bescheiden-button'); + const bescheidenIconButton: string = getDataTestIdOf('bescheiden-icon-button'); + + const vorgangCommandService = { + ...mock(VorgangCommandService), + getCommandStateResources: () => of(createStateResource(createCommandResource())), + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + BescheidenButtonComponent, + HasLinkPipe, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + providers: [ + { + provide: VorgangCommandService, + useValue: vorgangCommandService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(BescheidenButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call service', () => { + component.ngOnInit(); + + expect(vorgangCommandService.getBeschiedenCommand).toHaveBeenCalled(); + }); + }); + + describe('bescheiden', () => { + it('should call vorgang service', () => { + component.bescheiden(); + + expect(vorgangCommandService.bescheiden).toHaveBeenCalled(); + }); + }); + + describe('bescheiden button', () => { + beforeEach(() => { + component.showAsIconButton = false; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(bescheidenButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEIDEN]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(bescheidenButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); + + describe('bescheiden icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(bescheidenIconButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.BESCHEIDEN]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(bescheidenIconButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts index 7b5c05b97d866c2d635d39316faa7eb6f3966887..f14774ee1578ae70da1c2d7ac87ec2d15bcc26ca 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/bescheiden-button/bescheiden-button.component.ts @@ -24,30 +24,35 @@ import { Component, Input, OnInit } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; -import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangCommandService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-bescheiden-button', - templateUrl: './bescheiden-button.component.html', - styleUrls: ['./bescheiden-button.component.scss'] + selector: 'alfa-bescheiden-button', + templateUrl: './bescheiden-button.component.html', + styleUrls: ['./bescheiden-button.component.scss'], }) export class BescheidenButtonComponent implements OnInit { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean = false; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean = false; + commandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = VorgangWithEingangLinkRel; - readonly linkRel = VorgangWithEingangLinkRel; + constructor(private vorgangCommandService: VorgangCommandService) {} - constructor(private vorgangCommandService: VorgangCommandService) { } + ngOnInit(): void { + this.commandStateResource$ = this.vorgangCommandService.getBeschiedenCommand(); + } - ngOnInit(): void { - this.commandStateResource$ = this.vorgangCommandService.getBeschiedenCommand(); - } - - public bescheiden(): void { - this.vorgangCommandService.bescheiden(this.vorgang); - } -} \ No newline at end of file + public bescheiden(): void { + this.vorgangCommandService.bescheiden(this.vorgang); + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.html index cc4bae76031bc1c156c7fb64610bb25004add05a..85d20ebee72eb0bd0325b0a3d6af06be30c3808b 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.html @@ -24,19 +24,23 @@ --> <ng-container *ngIf="vorgang | hasLink: linkRel.VERWERFEN"> - - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="verwerfen-button" - text="Verwerfen" - svgIcon="discard_document" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="verwerfen()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="verwerfen-icon-button" - svgIcon="discard_document" - toolTip="Vorgang verwerfen" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="verwerfen()"> - </ozgcloud-icon-button-with-spinner> - -</ng-container> \ No newline at end of file + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="verwerfen-button" + text="Verwerfen" + svgIcon="discard_document" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="verwerfen()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="verwerfen-icon-button" + svgIcon="discard_document" + toolTip="Vorgang verwerfen" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="verwerfen()" + > + </ozgcloud-icon-button-with-spinner> +</ng-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.spec.ts index a9ec2f14fff817c998057e991262140bbbf15771..0151773895fffd56313b6b099daadb5abaead395 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.spec.ts @@ -24,7 +24,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; import { createCommandResource } from 'libs/command-shared/test/command'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -34,108 +37,107 @@ import { of } from 'rxjs'; import { VerwerfenButtonComponent } from './verwerfen-button.component'; describe('VerwerfenButtonComponent', () => { - let component: VerwerfenButtonComponent; - let fixture: ComponentFixture<VerwerfenButtonComponent>; - - const verwerfenButton: string = getDataTestIdOf('verwerfen-button'); - const verwerfenIconButton: string = getDataTestIdOf('verwerfen-icon-button'); - - const vorgangCommandService = { ...mock(VorgangCommandService), getCommandStateResources: () => of(createStateResource(createCommandResource())) }; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VerwerfenButtonComponent, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent), - HasLinkPipe - ], - providers: [ - { - provide: VorgangCommandService, - useValue: vorgangCommandService - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(VerwerfenButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call service', () => { - component.ngOnInit(); - - expect(vorgangCommandService.getVerwerfenCommand).toHaveBeenCalled(); - }) - }) - - describe('verwerfen', () => { - - it('should call vorgang service', () => { - component.verwerfen(); - - expect(vorgangCommandService.verwerfen).toHaveBeenCalled(); - }) - }) - - describe('verwerfen button', () => { - - beforeEach(() => { - component.showAsIconButton = false; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(verwerfenButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.VERWERFEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(verwerfenButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) - - describe('verwerfen icon button', () => { - - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(verwerfenIconButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.VERWERFEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(verwerfenIconButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) + let component: VerwerfenButtonComponent; + let fixture: ComponentFixture<VerwerfenButtonComponent>; + + const verwerfenButton: string = getDataTestIdOf('verwerfen-button'); + const verwerfenIconButton: string = getDataTestIdOf('verwerfen-icon-button'); + + const vorgangCommandService = { + ...mock(VorgangCommandService), + getCommandStateResources: () => of(createStateResource(createCommandResource())), + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VerwerfenButtonComponent, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + HasLinkPipe, + ], + providers: [ + { + provide: VorgangCommandService, + useValue: vorgangCommandService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VerwerfenButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call service', () => { + component.ngOnInit(); + + expect(vorgangCommandService.getVerwerfenCommand).toHaveBeenCalled(); + }); + }); + + describe('verwerfen', () => { + it('should call vorgang service', () => { + component.verwerfen(); + + expect(vorgangCommandService.verwerfen).toHaveBeenCalled(); + }); + }); + + describe('verwerfen button', () => { + beforeEach(() => { + component.showAsIconButton = false; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(verwerfenButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.VERWERFEN]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(verwerfenButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); + + describe('verwerfen icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(verwerfenIconButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.VERWERFEN]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(verwerfenIconButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.ts index 7a305f692b1bd7b41a07eab37520767c879632bc..d34d11c9de7684c9bd85ab602e484bab59891189 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/verwerfen-button/verwerfen-button.component.ts @@ -24,30 +24,35 @@ import { Component, Input, OnInit } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; -import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangCommandService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-verwerfen-button', - templateUrl: './verwerfen-button.component.html', - styleUrls: ['./verwerfen-button.component.scss'] + selector: 'alfa-verwerfen-button', + templateUrl: './verwerfen-button.component.html', + styleUrls: ['./verwerfen-button.component.scss'], }) export class VerwerfenButtonComponent implements OnInit { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean = false; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean = false; + commandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = VorgangWithEingangLinkRel; - readonly linkRel = VorgangWithEingangLinkRel; + constructor(private vorgangCommandService: VorgangCommandService) {} - constructor(private vorgangCommandService: VorgangCommandService) { } + ngOnInit(): void { + this.commandStateResource$ = this.vorgangCommandService.getVerwerfenCommand(); + } - ngOnInit(): void { - this.commandStateResource$ = this.vorgangCommandService.getVerwerfenCommand(); - } - - public verwerfen(): void { - this.vorgangCommandService.verwerfen(this.vorgang); - } -} \ No newline at end of file + public verwerfen(): void { + this.vorgangCommandService.verwerfen(this.vorgang); + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.html index 0edf1379b7a5d691152c50ec7c225c2089386908..77cdd31ed2c21da99dc34ddfb91cf03b79060e62 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.html @@ -24,19 +24,23 @@ --> <ng-container *ngIf="vorgang | hasLink: linkRel.WIEDEREROEFFNEN"> - - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="wiedereroeffnen-button" - text="Wiedereröffnen" - icon="undo" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="wiedereroeffnen()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="wiedereroeffnen-icon-button" - icon="undo" - toolTip="Vorgang wiedereröffnen" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="wiedereroeffnen()"> - </ozgcloud-icon-button-with-spinner> - -</ng-container> \ No newline at end of file + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="wiedereroeffnen-button" + text="Wiedereröffnen" + icon="undo" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="wiedereroeffnen()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="wiedereroeffnen-icon-button" + icon="undo" + toolTip="Vorgang wiedereröffnen" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="wiedereroeffnen()" + > + </ozgcloud-icon-button-with-spinner> +</ng-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.spec.ts index 8e79d1f5db89699aba2b0b8fcca4b27742438dc6..84f3f31a082c7b415e34e449434dc86505491b6a 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.spec.ts @@ -24,7 +24,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; import { createCommandResource } from 'libs/command-shared/test/command'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -34,107 +37,110 @@ import { of } from 'rxjs'; import { WiedereroeffnenButtonComponent } from './wiedereroeffnen-button.component'; describe('WiedereroeffnenButtonComponent', () => { - let component: WiedereroeffnenButtonComponent; - let fixture: ComponentFixture<WiedereroeffnenButtonComponent>; - const wiedereroeffnenButton: string = getDataTestIdOf('wiedereroeffnen-button'); - const wiedereroeffnenIconButton: string = getDataTestIdOf('wiedereroeffnen-icon-button'); - - const vorgangCommandService = { ...mock(VorgangCommandService), getCommandStateResources: () => of(createStateResource(createCommandResource())) }; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedereroeffnenButtonComponent, - HasLinkPipe, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent) - ], - providers: [ - { - provide: VorgangCommandService, - useValue: vorgangCommandService - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(WiedereroeffnenButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call service', () => { - component.ngOnInit(); - - expect(vorgangCommandService.getWiedereroeffnenCommand).toHaveBeenCalled(); - }) - }) - - describe('wiedereroeffnen', () => { - - it('should call vorgang service', () => { - component.wiedereroeffnen(); - - expect(vorgangCommandService.wiedereroeffnen).toHaveBeenCalled(); - }) - }) - - describe('wiedereroeffnen button', () => { - - beforeEach(() => { - component.showAsIconButton = false; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(wiedereroeffnenButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.WIEDEREROEFFNEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(wiedereroeffnenButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) - - describe('wiedereroeffnen icon button', () => { - - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(wiedereroeffnenIconButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.WIEDEREROEFFNEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(wiedereroeffnenIconButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) + let component: WiedereroeffnenButtonComponent; + let fixture: ComponentFixture<WiedereroeffnenButtonComponent>; + const wiedereroeffnenButton: string = getDataTestIdOf('wiedereroeffnen-button'); + const wiedereroeffnenIconButton: string = getDataTestIdOf('wiedereroeffnen-icon-button'); + + const vorgangCommandService = { + ...mock(VorgangCommandService), + getCommandStateResources: () => of(createStateResource(createCommandResource())), + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedereroeffnenButtonComponent, + HasLinkPipe, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + providers: [ + { + provide: VorgangCommandService, + useValue: vorgangCommandService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(WiedereroeffnenButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call service', () => { + component.ngOnInit(); + + expect(vorgangCommandService.getWiedereroeffnenCommand).toHaveBeenCalled(); + }); + }); + + describe('wiedereroeffnen', () => { + it('should call vorgang service', () => { + component.wiedereroeffnen(); + + expect(vorgangCommandService.wiedereroeffnen).toHaveBeenCalled(); + }); + }); + + describe('wiedereroeffnen button', () => { + beforeEach(() => { + component.showAsIconButton = false; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(wiedereroeffnenButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.WIEDEREROEFFNEN, + ]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(wiedereroeffnenButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); + + describe('wiedereroeffnen icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(wiedereroeffnenIconButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.WIEDEREROEFFNEN, + ]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(wiedereroeffnenIconButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.ts index 427263087181832b92aefe72c4c516ab125e791a..daa0d0cb32beb86a76445f90f1f1c79fbea23b95 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/wiedereroeffnen-button/wiedereroeffnen-button.component.ts @@ -24,30 +24,35 @@ import { Component, Input, OnInit } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; -import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangCommandService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-wiedereroeffnen-button', - templateUrl: './wiedereroeffnen-button.component.html', - styleUrls: ['./wiedereroeffnen-button.component.scss'] + selector: 'alfa-wiedereroeffnen-button', + templateUrl: './wiedereroeffnen-button.component.html', + styleUrls: ['./wiedereroeffnen-button.component.scss'], }) export class WiedereroeffnenButtonComponent implements OnInit { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean = false; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean = false; + commandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = VorgangWithEingangLinkRel; - readonly linkRel = VorgangWithEingangLinkRel; + constructor(private vorgangCommandService: VorgangCommandService) {} - constructor(private vorgangCommandService: VorgangCommandService) { } + ngOnInit(): void { + this.commandStateResource$ = this.vorgangCommandService.getWiedereroeffnenCommand(); + } - ngOnInit(): void { - this.commandStateResource$ = this.vorgangCommandService.getWiedereroeffnenCommand(); - } - - public wiedereroeffnen(): void { - this.vorgangCommandService.wiedereroeffnen(this.vorgang); - } + public wiedereroeffnen(): void { + this.vorgangCommandService.wiedereroeffnen(this.vorgang); + } } diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.html index 2bd8e2e0734c54ac403032a5667554ecd0c7bc4c..70592b2f97d06dc58bc51a51f86ae4ab990798a2 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.html @@ -24,19 +24,23 @@ --> <ng-container *ngIf="vorgang | hasLink: linkRel.ZURUECKHOLEN"> - - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="zurueckholen-button" - text="Zurückholen" - icon="undo" - [stateResource]="commandStateResource$ | async" - (click)="zurueckholen()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="zurueckholen-icon-button" - icon="undo" - toolTip="Vorgang zurückholen" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="zurueckholen()"> - </ozgcloud-icon-button-with-spinner> - -</ng-container> \ No newline at end of file + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="zurueckholen-button" + text="Zurückholen" + icon="undo" + [stateResource]="commandStateResource$ | async" + (click)="zurueckholen()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="zurueckholen-icon-button" + icon="undo" + toolTip="Vorgang zurückholen" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="zurueckholen()" + > + </ozgcloud-icon-button-with-spinner> +</ng-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.spec.ts index 6d7396c233275aa712f1fccb561b48b33b2f83da..200796bce5d5c30ac8f4ed98c0a235f5558b9c50 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.spec.ts @@ -24,7 +24,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; import { createCommandResource } from 'libs/command-shared/test/command'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -34,108 +37,111 @@ import { of } from 'rxjs'; import { ZurueckholenButtonComponent } from './zurueckholen-button.component'; describe('ZurueckholenButtonComponent', () => { - let component: ZurueckholenButtonComponent; - let fixture: ComponentFixture<ZurueckholenButtonComponent>; - - const zurueckholenButton: string = getDataTestIdOf('zurueckholen-button'); - const zurueckholenIconButton: string = getDataTestIdOf('zurueckholen-icon-button'); - - const vorgangCommandService = { ...mock(VorgangCommandService), getCommandStateResources: () => of(createStateResource(createCommandResource())) }; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - ZurueckholenButtonComponent, - HasLinkPipe, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent) - ], - providers: [ - { - provide: VorgangCommandService, - useValue: vorgangCommandService - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(ZurueckholenButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call service', () => { - component.ngOnInit(); - - expect(vorgangCommandService.getZurueckholenCommand).toHaveBeenCalled(); - }) - }) - - describe('zurueckholen', () => { - - it('should call vorgang service', () => { - component.zurueckholen(); - - expect(vorgangCommandService.zurueckholen).toHaveBeenCalled(); - }) - }) - - describe('zurueckholen button', () => { - - beforeEach(() => { - component.showAsIconButton = false; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(zurueckholenButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ZURUECKHOLEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(zurueckholenButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) - - describe('zurueckholen icon button', () => { - - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(zurueckholenIconButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ZURUECKHOLEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(zurueckholenIconButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) + let component: ZurueckholenButtonComponent; + let fixture: ComponentFixture<ZurueckholenButtonComponent>; + + const zurueckholenButton: string = getDataTestIdOf('zurueckholen-button'); + const zurueckholenIconButton: string = getDataTestIdOf('zurueckholen-icon-button'); + + const vorgangCommandService = { + ...mock(VorgangCommandService), + getCommandStateResources: () => of(createStateResource(createCommandResource())), + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + ZurueckholenButtonComponent, + HasLinkPipe, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + providers: [ + { + provide: VorgangCommandService, + useValue: vorgangCommandService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ZurueckholenButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call service', () => { + component.ngOnInit(); + + expect(vorgangCommandService.getZurueckholenCommand).toHaveBeenCalled(); + }); + }); + + describe('zurueckholen', () => { + it('should call vorgang service', () => { + component.zurueckholen(); + + expect(vorgangCommandService.zurueckholen).toHaveBeenCalled(); + }); + }); + + describe('zurueckholen button', () => { + beforeEach(() => { + component.showAsIconButton = false; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(zurueckholenButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.ZURUECKHOLEN, + ]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(zurueckholenButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); + + describe('zurueckholen icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(zurueckholenIconButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.ZURUECKHOLEN, + ]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(zurueckholenIconButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.ts index f05fc27399834370a4066e80e7b525e0d768352e..7715a436d2f3c47d8be90075baefd171179118b8 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckholen-button/zurueckholen-button.component.ts @@ -24,30 +24,35 @@ import { Component, Input, OnInit } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; -import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangCommandService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-zurueckholen-button', - templateUrl: './zurueckholen-button.component.html', - styleUrls: ['./zurueckholen-button.component.scss'] + selector: 'alfa-zurueckholen-button', + templateUrl: './zurueckholen-button.component.html', + styleUrls: ['./zurueckholen-button.component.scss'], }) export class ZurueckholenButtonComponent implements OnInit { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean = false; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean = false; + commandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = VorgangWithEingangLinkRel; - readonly linkRel = VorgangWithEingangLinkRel; + constructor(private vorgangCommandService: VorgangCommandService) {} - constructor(private vorgangCommandService: VorgangCommandService) { } + ngOnInit(): void { + this.commandStateResource$ = this.vorgangCommandService.getZurueckholenCommand(); + } - ngOnInit(): void { - this.commandStateResource$ = this.vorgangCommandService.getZurueckholenCommand(); - } - - public zurueckholen(): void { - this.vorgangCommandService.zurueckholen(this.vorgang); - } -} \ No newline at end of file + public zurueckholen(): void { + this.vorgangCommandService.zurueckholen(this.vorgang); + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.html index f93ef1a91c6d7232d98f9f0275e85b1bc842fd96..ecfedac4b0a0bf544ffbd730234ae29c1653aa22 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.html @@ -24,19 +24,23 @@ --> <ng-container *ngIf="vorgang | hasLink: linkRel.ZURUECKSTELLEN"> - - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="zurueckstellen-button" - text="Zurückstellen" - icon="undo" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="zurueckstellen()"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="zurueckstellen-icon-button" - icon="undo" - toolTip="Vorgang zurückstellen" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="zurueckstellen()"> - </ozgcloud-icon-button-with-spinner> - -</ng-container> \ No newline at end of file + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="zurueckstellen-button" + text="Zurückstellen" + icon="undo" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="zurueckstellen()" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="zurueckstellen-icon-button" + icon="undo" + toolTip="Vorgang zurückstellen" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="zurueckstellen()" + > + </ozgcloud-icon-button-with-spinner> +</ng-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.spec.ts index 22fb1872012724c05c95ce246410b216092f772f..da17a1d15e485d5234b0272be78d4bb8fd9c26eb 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.spec.ts @@ -24,7 +24,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { VorgangCommandService, VorgangWithEingangLinkRel } from '@alfa-client/vorgang-shared'; import { createCommandResource } from 'libs/command-shared/test/command'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -34,108 +37,111 @@ import { of } from 'rxjs'; import { ZurueckstellenButtonComponent } from './zurueckstellen-button.component'; describe('ZurueckstellenButtonComponent', () => { - let component: ZurueckstellenButtonComponent; - let fixture: ComponentFixture<ZurueckstellenButtonComponent>; - - const zurueckstellenButton: string = getDataTestIdOf('zurueckstellen-button'); - const zurueckstellenIconButton: string = getDataTestIdOf('zurueckstellen-icon-button'); - - const vorgangCommandService = { ...mock(VorgangCommandService), getCommandStateResources: () => of(createStateResource(createCommandResource())) }; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - ZurueckstellenButtonComponent, - HasLinkPipe, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent) - ], - providers: [ - { - provide: VorgangCommandService, - useValue: vorgangCommandService - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(ZurueckstellenButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call service', () => { - component.ngOnInit(); - - expect(vorgangCommandService.getZurueckstellenCommand).toHaveBeenCalled(); - }) - }) - - describe('zurueckstellen', () => { - - it('should call vorgang service', () => { - component.zurueckstellen(); - - expect(vorgangCommandService.zurueckstellen).toHaveBeenCalled(); - }) - }) - - describe('zurueckstellen button', () => { - - beforeEach(() => { - component.showAsIconButton = false; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(zurueckstellenButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ZURUECKSTELLEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(zurueckstellenButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) - - describe('zurueckstellen icon button', () => { - - beforeEach(() => { - component.showAsIconButton = true; - fixture.detectChanges(); - }) - - it('should be hidden', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(zurueckstellenIconButton); - - expect(buttonElement).not.toBeInstanceOf(HTMLElement); - }); - - it('should be visible', () => { - component.vorgang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ZURUECKSTELLEN]); - - fixture.detectChanges(); - const buttonElement = fixture.nativeElement.querySelector(zurueckstellenIconButton); - - expect(buttonElement).toBeInstanceOf(HTMLElement); - }); - }) + let component: ZurueckstellenButtonComponent; + let fixture: ComponentFixture<ZurueckstellenButtonComponent>; + + const zurueckstellenButton: string = getDataTestIdOf('zurueckstellen-button'); + const zurueckstellenIconButton: string = getDataTestIdOf('zurueckstellen-icon-button'); + + const vorgangCommandService = { + ...mock(VorgangCommandService), + getCommandStateResources: () => of(createStateResource(createCommandResource())), + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + ZurueckstellenButtonComponent, + HasLinkPipe, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + providers: [ + { + provide: VorgangCommandService, + useValue: vorgangCommandService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(ZurueckstellenButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call service', () => { + component.ngOnInit(); + + expect(vorgangCommandService.getZurueckstellenCommand).toHaveBeenCalled(); + }); + }); + + describe('zurueckstellen', () => { + it('should call vorgang service', () => { + component.zurueckstellen(); + + expect(vorgangCommandService.zurueckstellen).toHaveBeenCalled(); + }); + }); + + describe('zurueckstellen button', () => { + beforeEach(() => { + component.showAsIconButton = false; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(zurueckstellenButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.ZURUECKSTELLEN, + ]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(zurueckstellenButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); + + describe('zurueckstellen icon button', () => { + beforeEach(() => { + component.showAsIconButton = true; + fixture.detectChanges(); + }); + + it('should be hidden', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(zurueckstellenIconButton); + + expect(buttonElement).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible', () => { + component.vorgang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.ZURUECKSTELLEN, + ]); + + fixture.detectChanges(); + const buttonElement = fixture.nativeElement.querySelector(zurueckstellenIconButton); + + expect(buttonElement).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.ts index 81efdbb8be7a4b1d094244e9a05ecb8d1e416528..4bad6d7aa7f7c3c3ec4443af8b60e13f945deed2 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/buttons/zurueckstellen-button/zurueckstellen-button.component.ts @@ -24,30 +24,35 @@ import { Component, Input, OnInit } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; -import { VorgangCommandService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangCommandService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-zurueckstellen-button', - templateUrl: './zurueckstellen-button.component.html', - styleUrls: ['./zurueckstellen-button.component.scss'] + selector: 'alfa-zurueckstellen-button', + templateUrl: './zurueckstellen-button.component.html', + styleUrls: ['./zurueckstellen-button.component.scss'], }) export class ZurueckstellenButtonComponent implements OnInit { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean = false; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean = false; + commandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + readonly linkRel = VorgangWithEingangLinkRel; - readonly linkRel = VorgangWithEingangLinkRel; + constructor(private vorgangCommandService: VorgangCommandService) {} - constructor(private vorgangCommandService: VorgangCommandService) { } + ngOnInit(): void { + this.commandStateResource$ = this.vorgangCommandService.getZurueckstellenCommand(); + } - ngOnInit(): void { - this.commandStateResource$ = this.vorgangCommandService.getZurueckstellenCommand(); - } - - public zurueckstellen(): void { - this.vorgangCommandService.zurueckstellen(this.vorgang); - } -} \ No newline at end of file + public zurueckstellen(): void { + this.vorgangCommandService.zurueckstellen(this.vorgang); + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.html index ee2d0598cc9d6d2556a6dbfe5ebb19534bf709ea..85de971a72be9d72870985a6c9c32c35939b0079 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.html @@ -23,23 +23,68 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-annehmen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-annehmen-button> -<alfa-zurueckholen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-zurueckholen-button> -<alfa-bearbeiten-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-bearbeiten-button> -<alfa-bescheiden-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-bescheiden-button> -<alfa-zurueckstellen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-zurueckstellen-button> -<alfa-abschliessen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-abschliessen-button> -<alfa-verwerfen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-verwerfen-button> -<alfa-wiedereroeffnen-button [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-wiedereroeffnen-button> +<alfa-annehmen-button + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-annehmen-button> +<alfa-zurueckholen-button + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-zurueckholen-button> +<alfa-bearbeiten-button + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-bearbeiten-button> +<alfa-bescheiden-button + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-bescheiden-button> +<alfa-zurueckstellen-button + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-zurueckstellen-button> +<alfa-abschliessen-button + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-abschliessen-button> +<alfa-verwerfen-button + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-verwerfen-button> +<alfa-wiedereroeffnen-button + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-wiedereroeffnen-button> <!-- TODO Anhand des Links Library dynamisch laden --> -<alfa-loeschen-anfordern-button-container *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.LOESCHEN_ANFORDERN" data-test-id="loeschen-anfordern-icon-button-container" - [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"> +<alfa-loeschen-anfordern-button-container + *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.LOESCHEN_ANFORDERN" + data-test-id="loeschen-anfordern-icon-button-container" + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +> </alfa-loeschen-anfordern-button-container> -<alfa-endgueltig-loeschen-button-container [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-endgueltig-loeschen-button-container> -<alfa-loesch-anforderung-zuruecknehmen-button-container [showAsIconButton]="showAsIconButton"></alfa-loesch-anforderung-zuruecknehmen-button-container> +<alfa-endgueltig-loeschen-button-container + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-endgueltig-loeschen-button-container> +<alfa-loesch-anforderung-zuruecknehmen-button-container + [showAsIconButton]="showAsIconButton" +></alfa-loesch-anforderung-zuruecknehmen-button-container> <!-- --> -<alfa-create-wiedervorlage-button-container [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-create-wiedervorlage-button-container> -<alfa-assign-user-profile-button-container [vorgang]="vorgangWithEingang"></alfa-assign-user-profile-button-container> -<alfa-postfach-mail-button-container [showAsIconButton]="showAsIconButton" [vorgang]="vorgangWithEingang"></alfa-postfach-mail-button-container> +<alfa-create-wiedervorlage-button-container + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-create-wiedervorlage-button-container> +<alfa-assign-user-profile-button-container + [vorgang]="vorgangWithEingang" +></alfa-assign-user-profile-button-container> +<alfa-postfach-mail-button-container + [showAsIconButton]="showAsIconButton" + [vorgang]="vorgangWithEingang" +></alfa-postfach-mail-button-container> -<alfa-create-bescheid-button-container *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.CREATE_BESCHEID" [vorgangWithEingang]="vorgangWithEingang" data-test-id="create-bescheid-button-container"></alfa-create-bescheid-button-container> \ No newline at end of file +<alfa-create-bescheid-button-container + *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.CREATE_BESCHEID" + [vorgangWithEingang]="vorgangWithEingang" + data-test-id="create-bescheid-button-container" +></alfa-create-bescheid-button-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.scss index 7213e3ae301b500112ccc6434100bbda08f76d9d..bde392292fd2461a28b488ae3fb3fe77a796e081 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.scss @@ -22,12 +22,12 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - flex-grow: 1; + display: flex; + flex-grow: 1; - ::ng-deep { - a { - color: inherit; - } - } + ::ng-deep { + a { + color: inherit; + } + } } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.spec.ts index 05a2917c4c1101c1489ab07df74a2f5fc63cd20f..d62f61ebe56e9a706ee873724f56e4524b8c7d91 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.spec.ts @@ -23,7 +23,11 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CreateBescheidButtonContainerComponent } from '@alfa-client/bescheid'; -import { EndgueltigLoeschenButtonContainerComponent, LoeschAnforderungZuruecknehmenButtonContainerComponent, LoeschenAnfordernButtonContainerComponent } from '@alfa-client/loesch-anforderung'; +import { + EndgueltigLoeschenButtonContainerComponent, + LoeschAnforderungZuruecknehmenButtonContainerComponent, + LoeschenAnfordernButtonContainerComponent, +} from '@alfa-client/loesch-anforderung'; import { PostfachMailButtonContainerComponent } from '@alfa-client/postfach'; import { HasLinkPipe } from '@alfa-client/tech-shared'; import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils'; @@ -45,72 +49,74 @@ import { ZurueckstellenButtonComponent } from '../../../buttons/zurueckstellen-b import { VorgangDetailActionButtonsComponent } from './vorgang-detail-action-buttons.component'; describe('VorgangDetailActionButtonsComponent', () => { - let component: VorgangDetailActionButtonsComponent; - let fixture: ComponentFixture<VorgangDetailActionButtonsComponent>; + let component: VorgangDetailActionButtonsComponent; + let fixture: ComponentFixture<VorgangDetailActionButtonsComponent>; - const loeschenAnfordernIconButtonContainer: string = getDataTestIdOf('loeschen-anfordern-icon-button-container'); - const createBescheidButtonContainer: string = getDataTestIdOf('create-bescheid-button-container'); + const loeschenAnfordernIconButtonContainer: string = getDataTestIdOf( + 'loeschen-anfordern-icon-button-container', + ); + const createBescheidButtonContainer: string = getDataTestIdOf('create-bescheid-button-container'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailActionButtonsComponent, - HasLinkPipe, - MockComponent(IconButtonWithSpinnerComponent), - MockComponent(AnnehmenButtonComponent), - MockComponent(BearbeitenButtonComponent), - MockComponent(VerwerfenButtonComponent), - MockComponent(ZurueckholenButtonComponent), - MockComponent(BescheidenButtonComponent), - MockComponent(AbschliessenButtonComponent), - MockComponent(ZurueckstellenButtonComponent), - MockComponent(WiedereroeffnenButtonComponent), - MockComponent(AssignUserProfileButtonContainerComponent), - MockComponent(CreateWiedervorlageButtonContainerComponent), - MockComponent(PostfachMailButtonContainerComponent), - MockComponent(LoeschenAnfordernButtonContainerComponent), - MockComponent(EndgueltigLoeschenButtonContainerComponent), - MockComponent(LoeschAnforderungZuruecknehmenButtonContainerComponent), - MockComponent(CreateBescheidButtonContainerComponent) - ] - }) - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangDetailActionButtonsComponent, + HasLinkPipe, + MockComponent(IconButtonWithSpinnerComponent), + MockComponent(AnnehmenButtonComponent), + MockComponent(BearbeitenButtonComponent), + MockComponent(VerwerfenButtonComponent), + MockComponent(ZurueckholenButtonComponent), + MockComponent(BescheidenButtonComponent), + MockComponent(AbschliessenButtonComponent), + MockComponent(ZurueckstellenButtonComponent), + MockComponent(WiedereroeffnenButtonComponent), + MockComponent(AssignUserProfileButtonContainerComponent), + MockComponent(CreateWiedervorlageButtonContainerComponent), + MockComponent(PostfachMailButtonContainerComponent), + MockComponent(LoeschenAnfordernButtonContainerComponent), + MockComponent(EndgueltigLoeschenButtonContainerComponent), + MockComponent(LoeschAnforderungZuruecknehmenButtonContainerComponent), + MockComponent(CreateBescheidButtonContainerComponent), + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailActionButtonsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailActionButtonsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('loeschenAnfordernIconButtonContainer', () => { + describe('loeschenAnfordernIconButtonContainer', () => { + it('should show if link is present', () => { + component.vorgangWithEingang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN, + ]); + fixture.detectChanges(); - it('should show if link is present', () => { - component.vorgangWithEingang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN]); - fixture.detectChanges(); + existsAsHtmlElement(fixture, loeschenAnfordernIconButtonContainer); + }); - existsAsHtmlElement(fixture, loeschenAnfordernIconButtonContainer); - }) + it('should hide if link is not present', () => { + component.vorgangWithEingang = createVorgangWithEingangResource(); + fixture.detectChanges(); - it('should hide if link is not present', () => { - component.vorgangWithEingang = createVorgangWithEingangResource(); - fixture.detectChanges(); + notExistsAsHtmlElement(fixture, loeschenAnfordernIconButtonContainer); + }); + }); - notExistsAsHtmlElement(fixture, loeschenAnfordernIconButtonContainer); - }) - }) + describe('create bescheid button', () => { + it('should hide if link not exists', () => { + component.vorgangWithEingang = createVorgangWithEingangResource(); - describe('create bescheid button', () => { + fixture.detectChanges(); - it('should hide if link not exists', () => { - component.vorgangWithEingang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, createBescheidButtonContainer); - }) - }) + notExistsAsHtmlElement(fixture, createBescheidButtonContainer); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.ts index 7f25c8b6238f31150de1d2b4cfc0e7df56e56076..82595bd9f022a4771a8ab93fd898c8136b4d6f67 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-action-buttons/vorgang-detail-action-buttons.component.ts @@ -25,14 +25,13 @@ import { Component, Input } from '@angular/core'; import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-vorgang-detail-action-buttons', - templateUrl: './vorgang-detail-action-buttons.component.html', - styleUrls: ['./vorgang-detail-action-buttons.component.scss'] + selector: 'alfa-vorgang-detail-action-buttons', + templateUrl: './vorgang-detail-action-buttons.component.html', + styleUrls: ['./vorgang-detail-action-buttons.component.scss'], }) export class VorgangDetailActionButtonsComponent { + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() vorgangWithEingang: VorgangWithEingangResource; - - readonly showAsIconButton: boolean = true; - readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; -} \ No newline at end of file + readonly showAsIconButton: boolean = true; + readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.html index cf2614dab7295acadeb7ed1a6bd97ede4009e1b0..ce45b14b94f61fe78d7ee7ab0dccb824a198deaf 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.html @@ -25,29 +25,70 @@ --> <h3>Antragstellerdaten</h3> <mat-list *ngIf="antragstellerExists; else noAntragsteller" data-test-id="antragsteller-mat-list"> - <mat-list-item *ngIf="name" > - <mat-icon matListItemIcon class="material-icons-outlined" aria-label="Name" aria-hidden="false">assignment_ind</mat-icon> - <div matListItemLine data-test-id="antragsteller-name">{{ name }}</div> - </mat-list-item> - <mat-list-item *ngIf="antragsteller.email"> - <mat-icon matListItemIcon class="material-icons-outlined" aria-label="E-Mail-Adresse" aria-hidden="false">email</mat-icon> - <div matListItemLine data-test-id="antragsteller-email">{{ antragsteller.email }}</div> - </mat-list-item> - <mat-list-item *ngIf="antragsteller.telefon"> - <mat-icon matListItemIcon class="material-icons-outlined" aria-label="Telefonnummer" aria-hidden="false">call_black</mat-icon> - <div matListItemLine data-test-id="antragsteller-telefon">{{ antragsteller.telefon }}</div> - </mat-list-item> - <mat-list-item *ngIf="antragstellerStrasseHausnummer || antragstellerPlzOrt" data-test-id="antragsteller-adresse"> - <mat-icon matListItemIcon class="material-icons-outlined" aria-label="Adresse" aria-hidden="false">location_on</mat-icon> - <div matListItemLine data-test-id="antragsteller-strasse-hausnummer">{{ antragstellerStrasseHausnummer }}</div> - <div matListItemLine data-test-id="antragsteller-plz-ort">{{ antragstellerPlzOrt }}</div> - </mat-list-item> - <mat-list-item *ngIf="geburt"> - <mat-icon matListItemIcon class="material-icons-outlined" aria-label="Geburtsdatum und Geburtsort" aria-hidden="false">cake</mat-icon> - <div matListItemLine data-test-id="antragsteller-geburt">{{ geburt }}</div> - </mat-list-item> + <mat-list-item *ngIf="name"> + <mat-icon matListItemIcon class="material-icons-outlined" aria-label="Name" aria-hidden="false" + >assignment_ind</mat-icon + > + <div matListItemLine data-test-id="antragsteller-name"> + {{ name }} + </div> + </mat-list-item> + <mat-list-item *ngIf="antragsteller.email"> + <mat-icon + matListItemIcon + class="material-icons-outlined" + aria-label="E-Mail-Adresse" + aria-hidden="false" + >email</mat-icon + > + <div matListItemLine data-test-id="antragsteller-email"> + {{ antragsteller.email }} + </div> + </mat-list-item> + <mat-list-item *ngIf="antragsteller.telefon"> + <mat-icon + matListItemIcon + class="material-icons-outlined" + aria-label="Telefonnummer" + aria-hidden="false" + >call_black</mat-icon + > + <div matListItemLine data-test-id="antragsteller-telefon"> + {{ antragsteller.telefon }} + </div> + </mat-list-item> + <mat-list-item + *ngIf="antragstellerStrasseHausnummer || antragstellerPlzOrt" + data-test-id="antragsteller-adresse" + > + <mat-icon + matListItemIcon + class="material-icons-outlined" + aria-label="Adresse" + aria-hidden="false" + >location_on</mat-icon + > + <div matListItemLine data-test-id="antragsteller-strasse-hausnummer"> + {{ antragstellerStrasseHausnummer }} + </div> + <div matListItemLine data-test-id="antragsteller-plz-ort"> + {{ antragstellerPlzOrt }} + </div> + </mat-list-item> + <mat-list-item *ngIf="geburt"> + <mat-icon + matListItemIcon + class="material-icons-outlined" + aria-label="Geburtsdatum und Geburtsort" + aria-hidden="false" + >cake</mat-icon + > + <div matListItemLine data-test-id="antragsteller-geburt"> + {{ geburt }} + </div> + </mat-list-item> </mat-list> <ng-template #noAntragsteller> - <div data-test-id="no-antragsteller">Nicht vorhanden.</div> + <div data-test-id="no-antragsteller">Nicht vorhanden.</div> </ng-template> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.scss index 7590abc0f79483e6ce2c98d6f925204c4822433f..e96819a11e00391965c3d55eabb4e28810473d03 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.scss @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ h3 { - font-weight: 500; -} \ No newline at end of file + font-weight: 500; +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.spec.ts index 68e0376aa4e125e15964161ee7162cb20a25bc12..5d6dce139363b5c5c9971763584fd12ef373e5a7 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.spec.ts @@ -36,248 +36,238 @@ import { VorgangDetailAntragstellerComponent } from './vorgang-detail-antragstel registerLocaleData(localeDe, 'de'); describe('VorgangDetailAntragstellerComponent', () => { - let component: VorgangDetailAntragstellerComponent; - let fixture: ComponentFixture<VorgangDetailAntragstellerComponent>; + let component: VorgangDetailAntragstellerComponent; + let fixture: ComponentFixture<VorgangDetailAntragstellerComponent>; - const antragstellerName: string = '[data-test-id="antragsteller-name"]'; - const antragstellerEmail: string = '[data-test-id="antragsteller-email"]'; - const antragstellerTelefon: string = '[data-test-id="antragsteller-telefon"]'; - const antragstellerStrasseHausnummer: string = '[data-test-id="antragsteller-strasse-hausnummer"]'; - const antragstellerPlzOrt: string = '[data-test-id="antragsteller-plz-ort"]'; - const antragstellerGeburt: string = '[data-test-id="antragsteller-geburt"]'; - const antragstellerAdresse: string = '[data-test-id="antragsteller-adresse"]'; - const antragstellerMatList: string = '[data-test-id="antragsteller-mat-list"]'; - const noAntragsteller: string = '[data-test-id="no-antragsteller"]'; + const antragstellerName: string = '[data-test-id="antragsteller-name"]'; + const antragstellerEmail: string = '[data-test-id="antragsteller-email"]'; + const antragstellerTelefon: string = '[data-test-id="antragsteller-telefon"]'; + const antragstellerStrasseHausnummer: string = + '[data-test-id="antragsteller-strasse-hausnummer"]'; + const antragstellerPlzOrt: string = '[data-test-id="antragsteller-plz-ort"]'; + const antragstellerGeburt: string = '[data-test-id="antragsteller-geburt"]'; + const antragstellerAdresse: string = '[data-test-id="antragsteller-adresse"]'; + const antragstellerMatList: string = '[data-test-id="antragsteller-mat-list"]'; + const noAntragsteller: string = '[data-test-id="no-antragsteller"]'; - const antragsteller: Antragsteller = createAntragsteller(); + const antragsteller: Antragsteller = createAntragsteller(); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailAntragstellerComponent, - MatIcon, - MatList, - MatListItem, - MatRipple, - ], - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VorgangDetailAntragstellerComponent, MatIcon, MatList, MatListItem, MatRipple], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailAntragstellerComponent); - component = fixture.componentInstance; - component.antragsteller = antragsteller; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailAntragstellerComponent); + component = fixture.componentInstance; + component.antragsteller = antragsteller; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }) + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('full name', () => { + describe('full name', () => { + it('should be visible', () => { + component.antragsteller = antragsteller; + fixture.detectChanges(); - it('should be visible', () => { - component.antragsteller = antragsteller; - fixture.detectChanges(); + const element = getElementFromFixture(fixture, antragstellerName); - const element = getElementFromFixture(fixture, antragstellerName); + expect(element).toHaveTextContent(component.name); + }); - expect(element).toHaveTextContent(component.name); - }); + it('should not be visible', () => { + component.antragsteller = { ...antragsteller, anrede: '', vorname: '', nachname: '' }; + fixture.detectChanges(); - it('should not be visible', () => { - component.antragsteller = { ...antragsteller, anrede: '', vorname: '', nachname: '' }; - fixture.detectChanges(); + const element = getElementFromFixture(fixture, antragstellerName); - const element = getElementFromFixture(fixture, antragstellerName); + expect(element).not.toBeInstanceOf(HTMLElement); + }); - expect(element).not.toBeInstanceOf(HTMLElement); - }); + it('should trim multiple spaces to one space', () => { + component.antragsteller = { + ...antragsteller, + anrede: 'huhu', + vorname: null, + nachname: 'duda', + }; - it('should trim multiple spaces to one space', () => { - component.antragsteller = { ...antragsteller, anrede: 'huhu', vorname: null, nachname: 'duda' }; + expect(component.name).toStrictEqual('huhu duda'); + }); + }); - expect(component.name).toStrictEqual('huhu duda'); - }); - }); + describe('email', () => { + it('should be visible', () => { + component.antragsteller = antragsteller; + fixture.detectChanges(); - describe('email', () => { + const element = getElementFromFixture(fixture, antragstellerEmail); - it('should be visible', () => { - component.antragsteller = antragsteller; - fixture.detectChanges(); + expect(element).toHaveTextContent(antragsteller.email); + }); - const element = getElementFromFixture(fixture, antragstellerEmail); + it('should not be visible', () => { + component.antragsteller = { ...antragsteller, email: '' }; + fixture.detectChanges(); - expect(element).toHaveTextContent(antragsteller.email); - }); + const element = getElementFromFixture(fixture, antragstellerEmail); - it('should not be visible', () => { - component.antragsteller = { ...antragsteller, email: '' }; - fixture.detectChanges(); + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); - const element = getElementFromFixture(fixture, antragstellerEmail); + describe('telefon number', () => { + it('should be visible', () => { + component.antragsteller = antragsteller; + fixture.detectChanges(); - expect(element).not.toBeInstanceOf(HTMLElement); - }); - }); + const element = getElementFromFixture(fixture, antragstellerTelefon); - describe('telefon number', () => { + expect(element).toHaveTextContent(antragsteller.telefon); + }); - it('should be visible', () => { - component.antragsteller = antragsteller; - fixture.detectChanges(); + it('should not be visible', () => { + component.antragsteller = { ...antragsteller, telefon: '' }; + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, antragstellerTelefon); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('geburtsdata', () => { + it('should show formatted geburtsdatum and geburtsort', () => { + const geburtsdatum: string = '2022-01-01'; + component.antragsteller = { ...antragsteller, geburtsdatum }; + fixture.detectChanges(); - const element = getElementFromFixture(fixture, antragstellerTelefon); + const element = getElementFromFixture(fixture, antragstellerGeburt); - expect(element).toHaveTextContent(antragsteller.telefon); - }); + expect(element).toHaveTextContent(`01.01.2022 in ${antragsteller.geburtsort}`); + }); - it('should not be visible', () => { - component.antragsteller = { ...antragsteller, telefon: '' }; - fixture.detectChanges(); + it('should show not formatted geburtsdatum on unparsable string and geburtsort', () => { + const geburtsdatum: string = 'quatsch'; + component.antragsteller = { ...antragsteller, geburtsdatum }; + fixture.detectChanges(); - const element = getElementFromFixture(fixture, antragstellerTelefon); + const element = getElementFromFixture(fixture, antragstellerGeburt); - expect(element).not.toBeInstanceOf(HTMLElement); - }); - }); + expect(element).toHaveTextContent(`${geburtsdatum} in ${antragsteller.geburtsort}`); + }); + }); - describe('geburtsdata', () => { + describe('adresse', () => { + beforeEach(() => { + component.antragsteller = antragsteller; + fixture.detectChanges(); + }); - it('should show formatted geburtsdatum and geburtsort', () => { - const geburtsdatum: string = '2022-01-01'; - component.antragsteller = { ...antragsteller, geburtsdatum }; - fixture.detectChanges(); + it('should have strasse + hausnummer of Antragstellerin', () => { + const element = getElementFromFixture(fixture, antragstellerStrasseHausnummer); - const element = getElementFromFixture(fixture, antragstellerGeburt); + expect(element).toHaveTextContent(component.antragstellerStrasseHausnummer); + }); - expect(element).toHaveTextContent(`01.01.2022 in ${antragsteller.geburtsort}`); - }); + it('should have plz + ort of Antragstellerin', () => { + const element = getElementFromFixture(fixture, antragstellerPlzOrt); - it('should show not formatted geburtsdatum on unparsable string and geburtsort', () => { - const geburtsdatum: string = 'quatsch'; - component.antragsteller = { ...antragsteller, geburtsdatum }; - fixture.detectChanges(); + expect(element).toHaveTextContent(component.antragstellerPlzOrt); + }); - const element = getElementFromFixture(fixture, antragstellerGeburt); + it('should be visible', () => { + const element = getElementFromFixture(fixture, antragstellerAdresse); - expect(element).toHaveTextContent(`${geburtsdatum} in ${antragsteller.geburtsort}`); - }) - }) + expect(element).toHaveClass('mdc-list-item'); + }); - describe('adresse', () => { + it('should not be visible', () => { + component.antragsteller = { ...antragsteller, strasse: '', hausnummer: '', plz: '', ort: '' }; + fixture.detectChanges(); - beforeEach(() => { - component.antragsteller = antragsteller; - fixture.detectChanges(); - }); + const element = getElementFromFixture(fixture, antragstellerAdresse); - it('should have strasse + hausnummer of Antragstellerin', () => { - const element = getElementFromFixture(fixture, antragstellerStrasseHausnummer); + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); - expect(element).toHaveTextContent(component.antragstellerStrasseHausnummer); - }); + describe('antragsteller existing', () => { + beforeEach(() => { + component.antragsteller = antragsteller; + fixture.detectChanges(); + }); - it('should have plz + ort of Antragstellerin', () => { - const element = getElementFromFixture(fixture, antragstellerPlzOrt); + it('mat-list should be visible', () => { + const element = getElementFromFixture(fixture, antragstellerMatList); - expect(element).toHaveTextContent(component.antragstellerPlzOrt); - }); + expect(element).toBeInstanceOf(HTMLElement); + }); - it('should be visible', () => { - const element = getElementFromFixture(fixture, antragstellerAdresse); + it('noAntragsteller should not be visible', () => { + const element = getElementFromFixture(fixture, noAntragsteller); - expect(element).toHaveClass('mdc-list-item'); - }); + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); - it('should not be visible', () => { - component.antragsteller = { ...antragsteller, strasse: '', hausnummer: '', plz: '', ort: '' }; - fixture.detectChanges(); + describe('antragsteller empty', () => { + beforeEach(() => { + component.antragsteller = createEmptyAntragsteller(); + fixture.detectChanges(); + }); - const element = getElementFromFixture(fixture, antragstellerAdresse); + function createEmptyAntragsteller(): Antragsteller { + return { + anrede: EMPTY_STRING, + geburtsdatum: EMPTY_STRING, + geburtsname: EMPTY_STRING, + geburtsort: EMPTY_STRING, + nachname: EMPTY_STRING, + vorname: EMPTY_STRING, + email: EMPTY_STRING, + telefon: EMPTY_STRING, + strasse: EMPTY_STRING, + hausnummer: EMPTY_STRING, + plz: EMPTY_STRING, + ort: EMPTY_STRING, + otherData: null, + }; + } + + it('mat-list should not be visible', () => { + const element = getElementFromFixture(fixture, antragstellerMatList); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); - expect(element).not.toBeInstanceOf(HTMLElement); - }); - }); + it('noAntragsteller should be visible', () => { + const element = getElementFromFixture(fixture, noAntragsteller); - describe('antragsteller existing', () => { - - beforeEach(() => { - component.antragsteller = antragsteller; - fixture.detectChanges(); - }); - - it('mat-list should be visible', () => { - const element = getElementFromFixture(fixture, antragstellerMatList); - - expect(element).toBeInstanceOf(HTMLElement); - }); - - it('noAntragsteller should not be visible', () => { - const element = getElementFromFixture(fixture, noAntragsteller); - - expect(element).not.toBeInstanceOf(HTMLElement); - }); - }); - - describe('antragsteller empty', () => { - - beforeEach(() => { - component.antragsteller = createEmptyAntragsteller(); - fixture.detectChanges(); - }); - - function createEmptyAntragsteller(): Antragsteller { - return { - anrede: EMPTY_STRING, - geburtsdatum: EMPTY_STRING, - geburtsname: EMPTY_STRING, - geburtsort: EMPTY_STRING, - nachname: EMPTY_STRING, - vorname: EMPTY_STRING, - email: EMPTY_STRING, - telefon: EMPTY_STRING, - strasse: EMPTY_STRING, - hausnummer: EMPTY_STRING, - plz: EMPTY_STRING, - ort: EMPTY_STRING, - otherData: null - } - } - - it('mat-list should not be visible', () => { - const element = getElementFromFixture(fixture, antragstellerMatList); - - expect(element).not.toBeInstanceOf(HTMLElement); - }); - - it('noAntragsteller should be visible', () => { - const element = getElementFromFixture(fixture, noAntragsteller); - - expect(element).toBeInstanceOf(HTMLElement); - }); - }); - - describe('antragsteller object is null', () => { - - beforeEach(() => { - component.antragsteller = null; - fixture.detectChanges(); - }); - - it('mat-list should not be visible', () => { - const element = getElementFromFixture(fixture, antragstellerMatList); - - expect(element).not.toBeInstanceOf(HTMLElement); - }); - - it('noAntragsteller should be visible', () => { - const element = getElementFromFixture(fixture, noAntragsteller); - - expect(element).toBeInstanceOf(HTMLElement); - }); - }); + expect(element).toBeInstanceOf(HTMLElement); + }); + }); + + describe('antragsteller object is null', () => { + beforeEach(() => { + component.antragsteller = null; + fixture.detectChanges(); + }); + + it('mat-list should not be visible', () => { + const element = getElementFromFixture(fixture, antragstellerMatList); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + + it('noAntragsteller should be visible', () => { + const element = getElementFromFixture(fixture, noAntragsteller); + + expect(element).toBeInstanceOf(HTMLElement); + }); + }); }); - diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.ts index c9b28a57b02a0bc3c2ae637f26c366c214137d37..0376553e4b040129e51a4b0209538d4b734841d5 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-antragsteller/vorgang-detail-antragsteller.component.ts @@ -27,48 +27,59 @@ import { Antragsteller } from '@alfa-client/vorgang-shared'; import { isNull } from 'lodash-es'; @Component({ - selector: 'alfa-vorgang-detail-antragsteller', - templateUrl: './vorgang-detail-antragsteller.component.html', - styleUrls: ['./vorgang-detail-antragsteller.component.scss'] + selector: 'alfa-vorgang-detail-antragsteller', + templateUrl: './vorgang-detail-antragsteller.component.html', + styleUrls: ['./vorgang-detail-antragsteller.component.scss'], }) export class VorgangDetailAntragstellerComponent { + private readonly TRIM_TO_ONE_SPACE = /\s{2,}/g; - private readonly TRIM_TO_ONE_SPACE = /\s{2,}/g; + @Input() antragsteller: Antragsteller; - @Input() antragsteller: Antragsteller; + get antragstellerExists(): boolean { + if (isNull(this.antragsteller)) { + return false; + } + if ( + allEmpty( + this.name, + this.antragstellerStrasseHausnummer, + this.antragstellerPlzOrt, + this.geburt, + this.antragsteller.telefon, + this.antragsteller.email, + ) + ) { + return false; + } + return true; + } - get antragstellerExists(): boolean { - if (isNull(this.antragsteller)) { - return false; - } - if (allEmpty(this.name, this.antragstellerStrasseHausnummer, this.antragstellerPlzOrt, this.geburt, this.antragsteller.telefon ,this.antragsteller.email)) { - return false; - } - return true; - } + get name(): string { + return [this.antragsteller.anrede, this.antragsteller.vorname, this.antragsteller.nachname] + .join(' ') + .trim() + .replace(this.TRIM_TO_ONE_SPACE, ' '); + } - get name(): string { - return [this.antragsteller.anrede, this.antragsteller.vorname, this.antragsteller.nachname].join(' ').trim().replace(this.TRIM_TO_ONE_SPACE, ' '); - } + get antragstellerStrasseHausnummer(): string { + return [this.antragsteller.strasse, this.antragsteller.hausnummer].join(' ').trim(); + } - get antragstellerStrasseHausnummer(): string { - return [this.antragsteller.strasse, this.antragsteller.hausnummer].join(' ').trim(); - } + get antragstellerPlzOrt(): string { + return [this.antragsteller.plz, this.antragsteller.ort].join(' ').trim(); + } - get antragstellerPlzOrt(): string { - return [this.antragsteller.plz, this.antragsteller.ort].join(' ').trim(); - } + get geburt(): string { + return this.geburtsdatum && this.antragsteller.geburtsort ? + `${this.geburtsdatum} in ${this.antragsteller.geburtsort}` + : this.geburtsdatum || this.antragsteller.geburtsort; + } - get geburt(): string { - return this.geburtsdatum && this.antragsteller.geburtsort - ? `${this.geburtsdatum} in ${this.antragsteller.geburtsort}` - : this.geburtsdatum || this.antragsteller.geburtsort; - } - - get geburtsdatum(): string { - if (isParsableToDate(this.antragsteller.geburtsdatum)) { - return formatFullDate(new Date(this.antragsteller.geburtsdatum)); - } - return this.antragsteller.geburtsdatum; - } -} \ No newline at end of file + get geburtsdatum(): string { + if (isParsableToDate(this.antragsteller.geburtsdatum)) { + return formatFullDate(new Date(this.antragsteller.geburtsdatum)); + } + return this.antragsteller.geburtsdatum; + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.html index e56f15883115c8a91b6e21fcf6f4d4eb944754b4..3c820672488e582afcb3d2cd8712563e4fe4d9c3 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.html @@ -26,28 +26,51 @@ <ozgcloud-spinner [stateResource]="vorgangStateResource" class="header-spinner"></ozgcloud-spinner> <ng-container *ngIf="vorgangStateResource.resource as vorgangResource"> - <div class="container"> - <alfa-vorgang-detail-header [vorgangWithEingang]="vorgangResource" data-test-id="vorgang-detail-header"></alfa-vorgang-detail-header> - - <div class="section one-column"> - <alfa-vorgang-detail-formular-daten [vorgangWithEingang]="vorgangResource"></alfa-vorgang-detail-formular-daten> - <alfa-vorgang-detail-formular-buttons [vorgangWithEingang]="vorgangResource"></alfa-vorgang-detail-formular-buttons> - </div> - - <div class="two-column"> - <div class="section" *ngIf="vorgangResource | hasLink: vorgangWithEingangLinkRel.FORWARDING"> - <alfa-vorgang-forwarding-container [vorgang]="vorgangResource" data-test-id="forwarding-container-in-vorgang"></alfa-vorgang-forwarding-container> - </div> - <div class="section" *ngIf="vorgangResource | hasLink: linkRel.WIEDERVORLAGEN"> - <alfa-wiedervorlage-list-in-vorgang-container [vorgangStateResource]="vorgangStateResource" data-test-id="wiedervorlagen-container-in-vorgang"></alfa-wiedervorlage-list-in-vorgang-container> - </div> - <div class="section" *ngIf="vorgangResource | hasLink: linkRel.KOMMENTARE"> - <alfa-kommentar-list-in-vorgang-container [vorgangStateResource]="vorgangStateResource" data-test-id="kommentar-container-in-vorgang"></alfa-kommentar-list-in-vorgang-container> - </div> - </div> - </div> - <div class="right"> - <alfa-vorgang-detail-antragsteller [antragsteller]="vorgangResource.eingang.antragsteller" data-test-id="vorgang-detail-antragsteller"></alfa-vorgang-detail-antragsteller> - <alfa-postfach-mail-list-container *ngIf="vorgangResource | hasLink: linkRel.POSTFACH_MAILS" [vorgangStateResource]="vorgangStateResource" data-test-id="postfach-nachrichten-container-in-vorgang"></alfa-postfach-mail-list-container> - </div> -</ng-container> \ No newline at end of file + <div class="container"> + <alfa-vorgang-detail-header + [vorgangWithEingang]="vorgangResource" + data-test-id="vorgang-detail-header" + ></alfa-vorgang-detail-header> + + <div class="section one-column"> + <alfa-vorgang-detail-formular-daten + [vorgangWithEingang]="vorgangResource" + ></alfa-vorgang-detail-formular-daten> + <alfa-vorgang-detail-formular-buttons + [vorgangWithEingang]="vorgangResource" + ></alfa-vorgang-detail-formular-buttons> + </div> + + <div class="two-column"> + <div class="section" *ngIf="vorgangResource | hasLink: vorgangWithEingangLinkRel.FORWARDING"> + <alfa-vorgang-forwarding-container + [vorgang]="vorgangResource" + data-test-id="forwarding-container-in-vorgang" + ></alfa-vorgang-forwarding-container> + </div> + <div class="section" *ngIf="vorgangResource | hasLink: linkRel.WIEDERVORLAGEN"> + <alfa-wiedervorlage-list-in-vorgang-container + [vorgangStateResource]="vorgangStateResource" + data-test-id="wiedervorlagen-container-in-vorgang" + ></alfa-wiedervorlage-list-in-vorgang-container> + </div> + <div class="section" *ngIf="vorgangResource | hasLink: linkRel.KOMMENTARE"> + <alfa-kommentar-list-in-vorgang-container + [vorgangStateResource]="vorgangStateResource" + data-test-id="kommentar-container-in-vorgang" + ></alfa-kommentar-list-in-vorgang-container> + </div> + </div> + </div> + <div class="right"> + <alfa-vorgang-detail-antragsteller + [antragsteller]="vorgangResource.eingang.antragsteller" + data-test-id="vorgang-detail-antragsteller" + ></alfa-vorgang-detail-antragsteller> + <alfa-postfach-mail-list-container + *ngIf="vorgangResource | hasLink: linkRel.POSTFACH_MAILS" + [vorgangStateResource]="vorgangStateResource" + data-test-id="postfach-nachrichten-container-in-vorgang" + ></alfa-postfach-mail-list-container> + </div> +</ng-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.scss index 7ad83ad65ca0e5a1355392f0a95cfcf0a4a69417..b27537ba49e70f26ea5350c7ca2b70cd2163f2f6 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.scss @@ -26,48 +26,48 @@ @import 'variables'; :host { - position: relative; - display: flex; - background-color: inherit; - width: 100%; + position: relative; + display: flex; + background-color: inherit; + width: 100%; } .container { - width: calc(100% - 300px); - border-left: 1px solid rgba(0, 0, 0, 0.08); - border-right: 1px solid rgba(0, 0, 0, 0.08); - min-height: calc(100vh - $header-height - $navigation-height); + width: calc(100% - 300px); + border-left: 1px solid rgba(0, 0, 0, 0.08); + border-right: 1px solid rgba(0, 0, 0, 0.08); + min-height: calc(100vh - $header-height - $navigation-height); } .right { - right: 21px; - width: 300px; - padding: 12px 16px; - display: flex; - flex-direction: column; + right: 21px; + width: 300px; + padding: 12px 16px; + display: flex; + flex-direction: column; } .header-spinner { - position: absolute; - left: 50%; - top: 0; - transform: translateX(-50%); + position: absolute; + left: 50%; + top: 0; + transform: translateX(-50%); } .section { - width: auto; - padding: 0 16px 16px 16px; + width: auto; + padding: 0 16px 16px 16px; } .two-column { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; - @include media('>xxlDesktop') { - flex-direction: row; + @include media('>xxlDesktop') { + flex-direction: row; - >* { - width: 50%; - } - } -} \ No newline at end of file + > * { + width: 50%; + } + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.spec.ts index df12375ea3d2ca0a35f819926e44909e28ecc008..4b1e075f7c0f3f9cbed83062248d1e6bf1a32575 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.spec.ts @@ -26,9 +26,18 @@ import { MatDialogModule } from '@angular/material/dialog'; import { VorgangForwardingContainerComponent } from '@alfa-client/forwarding'; import { KommentarListInVorgangContainerComponent } from '@alfa-client/kommentar'; import { PostfachMailListContainerComponent } from '@alfa-client/postfach'; -import { HasLinkPipe, ToEmbeddedResourcesPipe, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + HasLinkPipe, + ToEmbeddedResourcesPipe, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; -import { VorgangHeaderLinkRel, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangHeaderLinkRel, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { WiedervorlageListInVorgangContainerComponent } from '@alfa-client/wiedervorlage'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { SpinnerComponent } from 'libs/ui/src/lib/ui/spinner/spinner.component'; @@ -41,131 +50,135 @@ import { VorgangDetailFormularDatenComponent } from './vorgang-detail-formular-d import { VorgangDetailHeaderComponent } from './vorgang-detail-header/vorgang-detail-header.component'; describe('VorgangDetailAreaComponent', () => { - let component: VorgangDetailAreaComponent; - let fixture: ComponentFixture<VorgangDetailAreaComponent>; + let component: VorgangDetailAreaComponent; + let fixture: ComponentFixture<VorgangDetailAreaComponent>; + + const wiedervorlagenContainer: string = getDataTestIdOf('wiedervorlagen-container-in-vorgang'); + const kommentarContainer: string = getDataTestIdOf('kommentar-container-in-vorgang'); + const postfachNachrichtenContainer: string = getDataTestIdOf( + 'postfach-nachrichten-container-in-vorgang', + ); + const forwardingContainer: string = getDataTestIdOf('forwarding-container-in-vorgang'); + + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [MatDialogModule], + declarations: [ + VorgangDetailAreaComponent, + HasLinkPipe, + ToEmbeddedResourcesPipe, + MockComponent(SpinnerComponent), + MockComponent(VorgangDetailHeaderComponent), + MockComponent(VorgangDetailFormularButtonsComponent), + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(WiedervorlageListInVorgangContainerComponent), + MockComponent(KommentarListInVorgangContainerComponent), + MockComponent(PostfachMailListContainerComponent), + MockComponent(VorgangDetailAntragstellerComponent), + MockComponent(VorgangDetailFormularDatenComponent), + MockComponent(VorgangForwardingContainerComponent), + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailAreaComponent); + component = fixture.componentInstance; + component.vorgangStateResource = createEmptyStateResource(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('wiedervorlagen', () => { + it('should be visible', () => { + component.vorgangStateResource = createStateResource( + createVorgangWithEingangResource([VorgangHeaderLinkRel.WIEDERVORLAGEN]), + ); + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector(wiedervorlagenContainer); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should be hidden', () => { + component.vorgangStateResource = createStateResource(vorgang); + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector(wiedervorlagenContainer); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('kommentare', () => { + it('should be visible', () => { + component.vorgangStateResource = createStateResource( + createVorgangWithEingangResource([VorgangHeaderLinkRel.KOMMENTARE]), + ); + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector(kommentarContainer); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should be hidden', () => { + component.vorgangStateResource = createStateResource(vorgang); + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector(kommentarContainer); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('postfach nachrichten', () => { + it('should be visible', () => { + component.vorgangStateResource = createStateResource( + createVorgangWithEingangResource([VorgangHeaderLinkRel.POSTFACH_MAILS]), + ); + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector(postfachNachrichtenContainer); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should be hidden', () => { + component.vorgangStateResource = createStateResource(vorgang); + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector(postfachNachrichtenContainer); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('forwarding', () => { + it('should be visible', () => { + component.vorgangStateResource = createStateResource( + createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARDING]), + ); + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector(forwardingContainer); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should be hidden', () => { + component.vorgangStateResource = createStateResource(vorgang); + fixture.detectChanges(); - const wiedervorlagenContainer: string = getDataTestIdOf('wiedervorlagen-container-in-vorgang'); - const kommentarContainer: string = getDataTestIdOf('kommentar-container-in-vorgang'); - const postfachNachrichtenContainer: string = getDataTestIdOf('postfach-nachrichten-container-in-vorgang'); - const forwardingContainer: string = getDataTestIdOf('forwarding-container-in-vorgang'); + const element = fixture.nativeElement.querySelector(forwardingContainer); - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ - MatDialogModule - ], - declarations: [ - VorgangDetailAreaComponent, - HasLinkPipe, - ToEmbeddedResourcesPipe, - MockComponent(SpinnerComponent), - MockComponent(VorgangDetailHeaderComponent), - MockComponent(VorgangDetailFormularButtonsComponent), - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(WiedervorlageListInVorgangContainerComponent), - MockComponent(KommentarListInVorgangContainerComponent), - MockComponent(PostfachMailListContainerComponent), - MockComponent(VorgangDetailAntragstellerComponent), - MockComponent(VorgangDetailFormularDatenComponent), - MockComponent(VorgangForwardingContainerComponent), - ], - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailAreaComponent); - component = fixture.componentInstance; - component.vorgangStateResource = createEmptyStateResource(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('wiedervorlagen', () => { - - it('should be visible', () => { - component.vorgangStateResource = createStateResource(createVorgangWithEingangResource([VorgangHeaderLinkRel.WIEDERVORLAGEN])); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(wiedervorlagenContainer); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should be hidden', () => { - component.vorgangStateResource = createStateResource(vorgang); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(wiedervorlagenContainer); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('kommentare', () => { - - it('should be visible', () => { - component.vorgangStateResource = createStateResource(createVorgangWithEingangResource([VorgangHeaderLinkRel.KOMMENTARE])); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(kommentarContainer); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should be hidden', () => { - component.vorgangStateResource = createStateResource(vorgang); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(kommentarContainer); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('postfach nachrichten', () => { - - it('should be visible', () => { - component.vorgangStateResource = createStateResource(createVorgangWithEingangResource([VorgangHeaderLinkRel.POSTFACH_MAILS])); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(postfachNachrichtenContainer); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should be hidden', () => { - component.vorgangStateResource = createStateResource(vorgang); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(postfachNachrichtenContainer); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('forwarding', () => { - - it('should be visible', () => { - component.vorgangStateResource = createStateResource(createVorgangWithEingangResource([VorgangWithEingangLinkRel.FORWARDING])); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(forwardingContainer); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should be hidden', () => { - component.vorgangStateResource = createStateResource(vorgang); - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector(forwardingContainer); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) -}); \ No newline at end of file + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.ts index 8a7376e7f23fb065ab4429ba9c1527eeb86b8781..0e3126f95f015005b234f1233820db2cd15cc859 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-area.component.ts @@ -23,17 +23,20 @@ */ import { Component, Input } from '@angular/core'; import { StateResource } from '@alfa-client/tech-shared'; -import { VorgangHeaderLinkRel, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangHeaderLinkRel, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-vorgang-detail-area', - templateUrl: './vorgang-detail-area.component.html', - styleUrls: ['./vorgang-detail-area.component.scss'] + selector: 'alfa-vorgang-detail-area', + templateUrl: './vorgang-detail-area.component.html', + styleUrls: ['./vorgang-detail-area.component.scss'], }) export class VorgangDetailAreaComponent { + @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; - @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; - - readonly linkRel = VorgangHeaderLinkRel; - readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; -} \ No newline at end of file + readonly linkRel = VorgangHeaderLinkRel; + readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.html index d81e7e2be7a49f720a618402e5f33778e1855215..cd1274077811e5f1209ace31c450d648e80c9ea6 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.html @@ -32,9 +32,14 @@ <alfa-abschliessen-button [vorgang]="vorgangWithEingang"></alfa-abschliessen-button> <alfa-wiedereroeffnen-button [vorgang]="vorgangWithEingang"></alfa-wiedereroeffnen-button> <!-- TODO LoeschAnforderung dynamisch laden, wenn Link vorhanden --> -<alfa-loeschen-anfordern-button-container *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.LOESCHEN_ANFORDERN" data-test-id="loeschen-anfordern-button-container" - [vorgang]="vorgangWithEingang"> +<alfa-loeschen-anfordern-button-container + *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.LOESCHEN_ANFORDERN" + data-test-id="loeschen-anfordern-button-container" + [vorgang]="vorgangWithEingang" +> </alfa-loeschen-anfordern-button-container> -<alfa-endgueltig-loeschen-button-container [vorgang]="vorgangWithEingang"></alfa-endgueltig-loeschen-button-container> +<alfa-endgueltig-loeschen-button-container + [vorgang]="vorgangWithEingang" +></alfa-endgueltig-loeschen-button-container> <alfa-loesch-anforderung-zuruecknehmen-button-container></alfa-loesch-anforderung-zuruecknehmen-button-container> -<!-- --> \ No newline at end of file +<!-- --> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.scss index ec8a86b4ded2172fc29b510ed4020ebb62783a50..352ae0e7ecf5a938be49257ca7fcd4c78d2590e3 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.scss @@ -22,11 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - margin-left: 48px; + margin-left: 48px; - ::ng-deep { - ozgcloud-stroked-button-with-spinner { - margin: 0 8px; - } - } + ::ng-deep { + ozgcloud-stroked-button-with-spinner { + margin: 0 8px; + } + } } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.spec.ts index 54417c0baf03799fddd27a9a9dfab831b10257a4..ce14f498d9417c8e456003bc7ab1c0e8e399a001 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.spec.ts @@ -22,7 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { EndgueltigLoeschenButtonContainerComponent, LoeschAnforderungZuruecknehmenButtonContainerComponent, LoeschenAnfordernButtonContainerComponent } from '@alfa-client/loesch-anforderung'; +import { + EndgueltigLoeschenButtonContainerComponent, + LoeschAnforderungZuruecknehmenButtonContainerComponent, + LoeschenAnfordernButtonContainerComponent, +} from '@alfa-client/loesch-anforderung'; import { HasLinkPipe } from '@alfa-client/tech-shared'; import { existsAsHtmlElement, notExistsAsHtmlElement } from '@alfa-client/test-utils'; import { OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; @@ -41,56 +45,59 @@ import { ZurueckstellenButtonComponent } from '../../../buttons/zurueckstellen-b import { VorgangDetailFormularButtonsComponent } from './vorgang-detail-formular-buttons.component'; describe('VorgangDetailFormularButtonsComponent', () => { - let component: VorgangDetailFormularButtonsComponent; - let fixture: ComponentFixture<VorgangDetailFormularButtonsComponent>; + let component: VorgangDetailFormularButtonsComponent; + let fixture: ComponentFixture<VorgangDetailFormularButtonsComponent>; - const loeschenAnfordernButtonContainer: string = getDataTestIdOf('loeschen-anfordern-button-container'); + const loeschenAnfordernButtonContainer: string = getDataTestIdOf( + 'loeschen-anfordern-button-container', + ); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailFormularButtonsComponent, - HasLinkPipe, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(AnnehmenButtonComponent), - MockComponent(BearbeitenButtonComponent), - MockComponent(VerwerfenButtonComponent), - MockComponent(ZurueckholenButtonComponent), - MockComponent(BescheidenButtonComponent), - MockComponent(AbschliessenButtonComponent), - MockComponent(ZurueckstellenButtonComponent), - MockComponent(WiedereroeffnenButtonComponent), - MockComponent(LoeschenAnfordernButtonContainerComponent), - MockComponent(EndgueltigLoeschenButtonContainerComponent), - MockComponent(LoeschAnforderungZuruecknehmenButtonContainerComponent) - ] - }) - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangDetailFormularButtonsComponent, + HasLinkPipe, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(AnnehmenButtonComponent), + MockComponent(BearbeitenButtonComponent), + MockComponent(VerwerfenButtonComponent), + MockComponent(ZurueckholenButtonComponent), + MockComponent(BescheidenButtonComponent), + MockComponent(AbschliessenButtonComponent), + MockComponent(ZurueckstellenButtonComponent), + MockComponent(WiedereroeffnenButtonComponent), + MockComponent(LoeschenAnfordernButtonContainerComponent), + MockComponent(EndgueltigLoeschenButtonContainerComponent), + MockComponent(LoeschAnforderungZuruecknehmenButtonContainerComponent), + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailFormularButtonsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailFormularButtonsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('loeschenAnfordernButtonContainer', () => { + describe('loeschenAnfordernButtonContainer', () => { + it('should show if link is present', () => { + component.vorgangWithEingang = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN, + ]); + fixture.detectChanges(); - it('should show if link is present', () => { - component.vorgangWithEingang = createVorgangWithEingangResource([VorgangWithEingangLinkRel.LOESCHEN_ANFORDERN]); - fixture.detectChanges(); + existsAsHtmlElement(fixture, loeschenAnfordernButtonContainer); + }); - existsAsHtmlElement(fixture, loeschenAnfordernButtonContainer); - }) + it('should hide if link is not present', () => { + component.vorgangWithEingang = createVorgangWithEingangResource(); + fixture.detectChanges(); - it('should hide if link is not present', () => { - component.vorgangWithEingang = createVorgangWithEingangResource(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, loeschenAnfordernButtonContainer); - }) - }) + notExistsAsHtmlElement(fixture, loeschenAnfordernButtonContainer); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.ts index f799fa5ba9aa187b17150b6363ddbfbce24e0c7f..ac9a74a50dfefada217b20209dc53744e7f7dcae 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-buttons/vorgang-detail-formular-buttons.component.ts @@ -25,13 +25,12 @@ import { Component, Input } from '@angular/core'; import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-vorgang-detail-formular-buttons', - templateUrl: './vorgang-detail-formular-buttons.component.html', - styleUrls: ['./vorgang-detail-formular-buttons.component.scss'] + selector: 'alfa-vorgang-detail-formular-buttons', + templateUrl: './vorgang-detail-formular-buttons.component.html', + styleUrls: ['./vorgang-detail-formular-buttons.component.scss'], }) export class VorgangDetailFormularButtonsComponent { + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() vorgangWithEingang: VorgangWithEingangResource; - - readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; + readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.html index 3791a5ad68bc14db675df27b751e49b783fc514f..8093a29cd5aec8c437dc52912e83e28fb26f7805 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.html @@ -24,20 +24,30 @@ --> <div *ngIf="eingang" data-test-id="antragdaten-panel"> - - <ozgcloud-expansion-panel *ngIf="eingang.header as header" data-test-id="header-panel" - headline="Header"> - <alfa-vorgang-detail-eingang-header [eingangHeader]="header"></alfa-vorgang-detail-eingang-header> - </ozgcloud-expansion-panel> - - <ozgcloud-expansion-panel *ngIf="eingang.antragsteller?.otherData as antragstellerOtherData" data-test-id="antragsteller-other-data-table" - [headline]="'Weitere Daten zum Antragsteller'"> - - <alfa-vorgang-detail-form-data-table [formData]="antragstellerOtherData"></alfa-vorgang-detail-form-data-table> - </ozgcloud-expansion-panel> - - <alfa-vorgang-detail-form-data-table *ngIf="antragsData" data-test-id="antragdaten" - [formData]="antragsData"> - </alfa-vorgang-detail-form-data-table> - + <ozgcloud-expansion-panel + *ngIf="eingang.header as header" + data-test-id="header-panel" + headline="Header" + > + <alfa-vorgang-detail-eingang-header + [eingangHeader]="header" + ></alfa-vorgang-detail-eingang-header> + </ozgcloud-expansion-panel> + + <ozgcloud-expansion-panel + *ngIf="eingang.antragsteller?.otherData as antragstellerOtherData" + data-test-id="antragsteller-other-data-table" + [headline]="'Weitere Daten zum Antragsteller'" + > + <alfa-vorgang-detail-form-data-table + [formData]="antragstellerOtherData" + ></alfa-vorgang-detail-form-data-table> + </ozgcloud-expansion-panel> + + <alfa-vorgang-detail-form-data-table + *ngIf="antragsData" + data-test-id="antragdaten" + [formData]="antragsData" + > + </alfa-vorgang-detail-form-data-table> </div> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.scss index 51e3e53f483b666925069a58b65bd0c4587eeadb..8208e684a0309d412d95c4d1e5b3c882bf99dbd4 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.scss @@ -22,7 +22,7 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - margin-top: 0.25rem; - overflow: hidden; + display: flex; + margin-top: 0.25rem; + overflow: hidden; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.spec.ts index 7ba7126135e28efb37bfb161fed578d0698bdb02..d9690003994d5ed80627223e5b6524c53a88cc25 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.spec.ts @@ -32,115 +32,116 @@ import { VorgangDetailAntragDataComponent } from './vorgang-detail-antrag-data.c import { VorgangDetailEingangHeaderComponent } from './vorgang-detail-eingang-header/vorgang-detail-eingang-header.component'; describe('VorgangDetailAntragDataComponent', () => { - let component: VorgangDetailAntragDataComponent; - let fixture: ComponentFixture<VorgangDetailAntragDataComponent>; - - const formulardatenPanelSelector: string = getDataTestIdOf('antragdaten-panel'); - const headerPanelSelector: string = getDataTestIdOf('header-panel'); - const antragdaten: string = getDataTestIdOf('antragdaten'); - const antragstellerOtherDataTableSelector: string = getDataTestIdOf('antragsteller-other-data-table'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailAntragDataComponent, - MockComponent(ExpansionPanelComponent), - MockComponent(VorgangDetailEingangHeaderComponent), - MockComponent(VorgangDetailFormDataTableComponent), - ], - - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailAntragDataComponent); - component = fixture.componentInstance; - component.eingang = null; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('Formulardaten Panel ', () => { - - it('should NOT be visible', () => { - const formulardatenPanel = fixture.nativeElement.querySelector(formulardatenPanelSelector); - - expect(formulardatenPanel).not.toBeInstanceOf(HTMLElement); - }) - - it('should be visible if data has children', () => { - component.eingang = createEingang(); - fixture.detectChanges(); - - const formulardatenPanel = fixture.nativeElement.querySelector(formulardatenPanelSelector); - - expect(formulardatenPanel).toBeInstanceOf(HTMLElement); - }); - }); - - describe('Eingang Header Panel', () => { - - it('should NOT be visible', () => { - const headerPanel = fixture.nativeElement.querySelector(headerPanelSelector); - - expect(headerPanel).not.toBeInstanceOf(HTMLElement); - }) - - it('should be visible if data has children', () => { - component.eingang = createEingang(); - fixture.detectChanges(); - - const headerPanel = fixture.nativeElement.querySelector(headerPanelSelector); - - expect(headerPanel).toBeInstanceOf(HTMLElement); - }); - }); - - describe('Formulardaten Data Table', () => { - - it('should NOT be visible', () => { - const formulardatenDataTable = fixture.nativeElement.querySelector(antragdaten); - - expect(formulardatenDataTable).not.toBeInstanceOf(HTMLElement); - }) - - it('should be visible if data has children', () => { - component.eingang = createEingang(); - component.antragsData = {}; - fixture.detectChanges(); - - const formulardatenDataTable = fixture.nativeElement.querySelector(antragdaten); - - expect(formulardatenDataTable).toBeInstanceOf(HTMLElement); - }); - }); - - describe('Antragsteller Other Data Table', () => { - - it('should NOT be visible', () => { - const antragstellerOtherDataTable = fixture.nativeElement.querySelector(antragstellerOtherDataTableSelector); - - expect(antragstellerOtherDataTable).not.toBeInstanceOf(HTMLElement); - }) - - it('should proceed without antragsteller', () => { - component.eingang = { ...createEingang(), antragsteller: null }; - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, antragstellerOtherDataTableSelector); - }) - - it('should be visible if data has children', () => { - component.eingang = createEingang(); - component.eingang.antragsteller.otherData = new Map(); - fixture.detectChanges(); - - const antragstellerOtherDataTable = fixture.nativeElement.querySelector(antragstellerOtherDataTableSelector); - - expect(antragstellerOtherDataTable).toBeInstanceOf(HTMLElement); - }); - }); + let component: VorgangDetailAntragDataComponent; + let fixture: ComponentFixture<VorgangDetailAntragDataComponent>; + + const formulardatenPanelSelector: string = getDataTestIdOf('antragdaten-panel'); + const headerPanelSelector: string = getDataTestIdOf('header-panel'); + const antragdaten: string = getDataTestIdOf('antragdaten'); + const antragstellerOtherDataTableSelector: string = getDataTestIdOf( + 'antragsteller-other-data-table', + ); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangDetailAntragDataComponent, + MockComponent(ExpansionPanelComponent), + MockComponent(VorgangDetailEingangHeaderComponent), + MockComponent(VorgangDetailFormDataTableComponent), + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailAntragDataComponent); + component = fixture.componentInstance; + component.eingang = null; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('Formulardaten Panel ', () => { + it('should NOT be visible', () => { + const formulardatenPanel = fixture.nativeElement.querySelector(formulardatenPanelSelector); + + expect(formulardatenPanel).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible if data has children', () => { + component.eingang = createEingang(); + fixture.detectChanges(); + + const formulardatenPanel = fixture.nativeElement.querySelector(formulardatenPanelSelector); + + expect(formulardatenPanel).toBeInstanceOf(HTMLElement); + }); + }); + + describe('Eingang Header Panel', () => { + it('should NOT be visible', () => { + const headerPanel = fixture.nativeElement.querySelector(headerPanelSelector); + + expect(headerPanel).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible if data has children', () => { + component.eingang = createEingang(); + fixture.detectChanges(); + + const headerPanel = fixture.nativeElement.querySelector(headerPanelSelector); + + expect(headerPanel).toBeInstanceOf(HTMLElement); + }); + }); + + describe('Formulardaten Data Table', () => { + it('should NOT be visible', () => { + const formulardatenDataTable = fixture.nativeElement.querySelector(antragdaten); + + expect(formulardatenDataTable).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible if data has children', () => { + component.eingang = createEingang(); + component.antragsData = {}; + fixture.detectChanges(); + + const formulardatenDataTable = fixture.nativeElement.querySelector(antragdaten); + + expect(formulardatenDataTable).toBeInstanceOf(HTMLElement); + }); + }); + + describe('Antragsteller Other Data Table', () => { + it('should NOT be visible', () => { + const antragstellerOtherDataTable = fixture.nativeElement.querySelector( + antragstellerOtherDataTableSelector, + ); + + expect(antragstellerOtherDataTable).not.toBeInstanceOf(HTMLElement); + }); + + it('should proceed without antragsteller', () => { + component.eingang = { ...createEingang(), antragsteller: null }; + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, antragstellerOtherDataTableSelector); + }); + + it('should be visible if data has children', () => { + component.eingang = createEingang(); + component.eingang.antragsteller.otherData = new Map(); + fixture.detectChanges(); + + const antragstellerOtherDataTable = fixture.nativeElement.querySelector( + antragstellerOtherDataTableSelector, + ); + + expect(antragstellerOtherDataTable).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.ts index 3a05ece6fa1f625efc15ae0eab46647a28e614c5..8e882f643268f7bcc2de0bb70afebe59449a9391 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-antrag-data.component.ts @@ -25,13 +25,11 @@ import { Component, Input } from '@angular/core'; import { Eingang } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-vorgang-detail-antrag-data', - templateUrl: './vorgang-detail-antrag-data.component.html', - styleUrls: ['./vorgang-detail-antrag-data.component.scss'] + selector: 'alfa-vorgang-detail-antrag-data', + templateUrl: './vorgang-detail-antrag-data.component.html', + styleUrls: ['./vorgang-detail-antrag-data.component.scss'], }) export class VorgangDetailAntragDataComponent { - - @Input() eingang: Eingang; - @Input() antragsData: object; - + @Input() eingang: Eingang; + @Input() antragsData: object; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.html index 825646171942417d8556033f43f0fc113066c370..f380c834f477c400ea3f433c010d5042d310dfe8 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.html @@ -24,44 +24,44 @@ --> <table aria-label="Eingangsdaten"> - <tr> - <th scope="col">Formularfeld</th> - <th scope="col">Formulareingabe</th> - </tr> - <tr> - <td class="key">Erstellungsdatum</td> - <td class="value">{{ eingangHeader.createdAt }}</td> - </tr> - <tr> - <td class="key">Client</td> - <td class="value">{{ eingangHeader.client }}</td> - </tr> - <tr> - <td class="key">Client ID</td> - <td class="value">{{ eingangHeader.clientId }}</td> - </tr> - <tr> - <td class="key">Customer</td> - <td class="value">{{ eingangHeader.customer }}</td> - </tr> - <tr> - <td class="key">Customer ID</td> - <td class="value">{{ eingangHeader.clientId }}</td> - </tr> - <tr> - <td class="key">Formularname</td> - <td class="value">{{ eingangHeader.formName }}</td> - </tr> - <tr> - <td class="key">Formular ID</td> - <td class="value">{{ eingangHeader.formId }}</td> - </tr> - <tr> - <td class="key">Request ID</td> - <td class="value">{{ eingangHeader.requestId }}</td> - </tr> - <tr> - <td class="key">Sender</td> - <td class="value">{{ eingangHeader.sender }}</td> - </tr> + <tr> + <th scope="col">Formularfeld</th> + <th scope="col">Formulareingabe</th> + </tr> + <tr> + <td class="key">Erstellungsdatum</td> + <td class="value">{{ eingangHeader.createdAt }}</td> + </tr> + <tr> + <td class="key">Client</td> + <td class="value">{{ eingangHeader.client }}</td> + </tr> + <tr> + <td class="key">Client ID</td> + <td class="value">{{ eingangHeader.clientId }}</td> + </tr> + <tr> + <td class="key">Customer</td> + <td class="value">{{ eingangHeader.customer }}</td> + </tr> + <tr> + <td class="key">Customer ID</td> + <td class="value">{{ eingangHeader.clientId }}</td> + </tr> + <tr> + <td class="key">Formularname</td> + <td class="value">{{ eingangHeader.formName }}</td> + </tr> + <tr> + <td class="key">Formular ID</td> + <td class="value">{{ eingangHeader.formId }}</td> + </tr> + <tr> + <td class="key">Request ID</td> + <td class="value">{{ eingangHeader.requestId }}</td> + </tr> + <tr> + <td class="key">Sender</td> + <td class="value">{{ eingangHeader.sender }}</td> + </tr> </table> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.scss index 6bd38e71021886ccc190491cf3b43a2ec44e46c3..84315035bc52196849da660ebd00460ae517937b 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.scss @@ -22,26 +22,26 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ table { - border-spacing: 0; - margin: -4px 0 8px 0; - width: 100%; + border-spacing: 0; + margin: -4px 0 8px 0; + width: 100%; } td { - margin: 0; - padding: 0 8px 0 0; - vertical-align: top; - overflow-wrap: break-word; + margin: 0; + padding: 0 8px 0 0; + vertical-align: top; + overflow-wrap: break-word; } .key { - width: 10px; + width: 10px; } .value { - word-break: break-word; + word-break: break-word; } th { - display: none; + display: none; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.spec.ts index bfa55d19a0a620539c56c7dae3de8f6c3394c237..478f24561a20c3faa6b2937cba9da9bfa78d0fdd 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.spec.ts @@ -25,22 +25,20 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { createHeader } from 'libs/vorgang-shared/test/vorgang'; import { VorgangDetailEingangHeaderComponent } from './vorgang-detail-eingang-header.component'; - describe('VorgangWithVorgangDetailEingangHeaderComponent', () => { let component: VorgangDetailEingangHeaderComponent; let fixture: ComponentFixture<VorgangDetailEingangHeaderComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ - declarations: [ VorgangDetailEingangHeaderComponent ] - }) - .compileComponents(); + declarations: [VorgangDetailEingangHeaderComponent], + }).compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(VorgangDetailEingangHeaderComponent); component = fixture.componentInstance; - component.eingangHeader = createHeader() + component.eingangHeader = createHeader(); fixture.detectChanges(); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.ts index 36465f8a55caf3847dd4674c4ce91ab22aad873b..54208bc40899f6e5415af1438ce3e6d31d669df8 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-antrag-data/vorgang-detail-eingang-header/vorgang-detail-eingang-header.component.ts @@ -27,10 +27,8 @@ import { EingangHeader } from '@alfa-client/vorgang-shared'; @Component({ selector: 'alfa-vorgang-detail-eingang-header', templateUrl: './vorgang-detail-eingang-header.component.html', - styleUrls: ['./vorgang-detail-eingang-header.component.scss'] + styleUrls: ['./vorgang-detail-eingang-header.component.scss'], }) export class VorgangDetailEingangHeaderComponent { - - @Input() eingangHeader: EingangHeader - + @Input() eingangHeader: EingangHeader; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.html index e51ffc5c6bdadfed1ead96cb98f6c6baa2fdb3ad..0c6b5172652511b4c53e0ace77438a6a55b0728a 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.html @@ -24,7 +24,7 @@ --> <alfa-vertical-binary-file-list - [fileListResource]="fileListResource$ | async" - [downloadFileNamePrefix]="vorgangWithEingang.nummer" + [fileListResource]="fileListResource$ | async" + [downloadFileNamePrefix]="vorgangWithEingang.nummer" > </alfa-vertical-binary-file-list> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.spec.ts index 644cbc7210e64354c4fddd84e09ffec5f573e54d..a9ec25ceade2c4416584d658de61791a3db9c645 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.spec.ts @@ -24,52 +24,57 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { VerticalBinaryFileListComponent } from '@alfa-client/binary-file'; import { mock } from '@alfa-client/test-utils'; -import { VorgangService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { MockComponent } from 'ng-mocks'; import { VorgangDetailAttachmentListComponent } from './vorgang-detail-attachment-list.component'; describe('VorgangDetailAttachmentListComponent', () => { - let component: VorgangDetailAttachmentListComponent; - let fixture: ComponentFixture<VorgangDetailAttachmentListComponent>; + let component: VorgangDetailAttachmentListComponent; + let fixture: ComponentFixture<VorgangDetailAttachmentListComponent>; - const vorgangService = mock(VorgangService); - const vorgangWithAttachments: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ATTACHMENTS]); + const vorgangService = mock(VorgangService); + const vorgangWithAttachments: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.ATTACHMENTS, + ]); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailAttachmentListComponent, - MockComponent(VerticalBinaryFileListComponent) - ], - providers: [ - { - provide: VorgangService, - useValue: vorgangService, - }, - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangDetailAttachmentListComponent, + MockComponent(VerticalBinaryFileListComponent), + ], + providers: [ + { + provide: VorgangService, + useValue: vorgangService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailAttachmentListComponent); - component = fixture.componentInstance; - component.vorgangWithEingang = createVorgangWithEingangResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailAttachmentListComponent); + component = fixture.componentInstance; + component.vorgangWithEingang = createVorgangWithEingangResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('on vorgang with "attachment" link', () => { + describe('on vorgang with "attachment" link', () => { + it('should call vorgangService methods', () => { + component.vorgangWithEingang = vorgangWithAttachments; - it('should call vorgangService methods', () => { - component.vorgangWithEingang = vorgangWithAttachments; + component.ngOnInit(); - component.ngOnInit(); - - expect(vorgangService.getAttachments).toHaveBeenCalled(); - }); - }); + expect(vorgangService.getAttachments).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.ts index 0f1bd2948465e87acd32cf86958d64863f6adba6..f1d39c242772553f9b49f790df9b3220d3afea05 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-attachment-list/vorgang-detail-attachment-list.component.ts @@ -28,19 +28,20 @@ import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-detail-attachment-list', - templateUrl: './vorgang-detail-attachment-list.component.html', - styleUrls: ['./vorgang-detail-attachment-list.component.scss'] + selector: 'alfa-vorgang-detail-attachment-list', + templateUrl: './vorgang-detail-attachment-list.component.html', + styleUrls: ['./vorgang-detail-attachment-list.component.scss'], }) export class VorgangDetailAttachmentListComponent implements OnInit { + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() vorgangWithEingang: VorgangWithEingangResource; + fileListResource$: Observable<StateResource<BinaryFileListResource>> = of( + createEmptyStateResource<BinaryFileListResource>(), + ); - fileListResource$: Observable<StateResource<BinaryFileListResource>> = of(createEmptyStateResource<BinaryFileListResource>()); + constructor(private vorgangService: VorgangService) {} - constructor(private vorgangService: VorgangService) { } - - ngOnInit(): void { - this.fileListResource$ = this.vorgangService.getAttachments(); - } + ngOnInit(): void { + this.fileListResource$ = this.vorgangService.getAttachments(); + } } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.html index a11a17aacc7b8cef426aabde9e1fea57df8837ba..0fe8366d794c27918ea8b9379d8f62177093f1fd 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.html @@ -24,33 +24,35 @@ --> <table aria-label="Formulardaten" *ngIf="isObject(formData) && !isArray(formData)"> - <tr> - <th scope="col">Formularfeld</th> - <th scope="col">Formulareingabe</th> - </tr> - <tr *ngFor="let row of formData | keyvalue: originalOrder"> - <td colspan="2" *ngIf="isExpandable(row.value); else keyValueEntry"> - <ozgcloud-expansion-panel [headline]="getLabel(row)" data-test-class="panel"> - <alfa-vorgang-detail-form-data-table [formData]="row.value.value"></alfa-vorgang-detail-form-data-table> - </ozgcloud-expansion-panel> - </td> - <ng-template #keyValueEntry> - <td class="key">{{getLabel(row)}}</td> - <td class="value">{{row.value.value}}</td> - </ng-template> - </tr> + <tr> + <th scope="col">Formularfeld</th> + <th scope="col">Formulareingabe</th> + </tr> + <tr *ngFor="let row of formData | keyvalue: originalOrder"> + <td colspan="2" *ngIf="isExpandable(row.value); else keyValueEntry"> + <ozgcloud-expansion-panel [headline]="getLabel(row)" data-test-class="panel"> + <alfa-vorgang-detail-form-data-table + [formData]="row.value.value" + ></alfa-vorgang-detail-form-data-table> + </ozgcloud-expansion-panel> + </td> + <ng-template #keyValueEntry> + <td class="key">{{ getLabel(row) }}</td> + <td class="value">{{ row.value.value }}</td> + </ng-template> + </tr> </table> <table aria-label="Formulardaten" *ngIf="isArray(formData)"> - <tr> - <th scope="col">Formulareingabe</th> - </tr> - <tr *ngFor="let row of formData"> - <td *ngIf="isObject(row); else valueEntry"> - <alfa-vorgang-detail-form-data-table [formData]="row"></alfa-vorgang-detail-form-data-table> - </td> - <ng-template #valueEntry> - <td class="value">{{row}}</td> - </ng-template> - </tr> + <tr> + <th scope="col">Formulareingabe</th> + </tr> + <tr *ngFor="let row of formData"> + <td *ngIf="isObject(row); else valueEntry"> + <alfa-vorgang-detail-form-data-table [formData]="row"></alfa-vorgang-detail-form-data-table> + </td> + <ng-template #valueEntry> + <td class="value">{{ row }}</td> + </ng-template> + </tr> </table> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.scss index afcf7211993795be528632af248aa42401ec1af1..fb8b69faabddc2c8f4f5f0d8046ea0e27e8dac6d 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.scss @@ -22,26 +22,26 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ table { - border-spacing: 0; - margin: -4px 0 8px 0; + border-spacing: 0; + margin: -4px 0 8px 0; } td { - margin: 0; - padding: 0 8px 0 0; - vertical-align: top; - overflow-wrap: break-word; + margin: 0; + padding: 0 8px 0 0; + vertical-align: top; + overflow-wrap: break-word; } .key { - padding-right: 30px + padding-right: 30px; } .value { - overflow-wrap: anywhere; - white-space: pre-line; + overflow-wrap: anywhere; + white-space: pre-line; } th { - display: none; + display: none; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.spec.ts index a842c1b8c7eb9bef28dd8a6e590fa1be32c28ce8..b74f4f2cdc9c5f544ece5d4fdbf4c30af751dbde 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.spec.ts @@ -24,112 +24,110 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ExpansionPanelComponent } from 'libs/ui/src/lib/ui/expansion-panel/expansion-panel.component'; import { MockComponent } from 'ng-mocks'; -import { FormField, VorgangDetailFormDataTableComponent } from './vorgang-detail-form-data-table.component'; +import { + FormField, + VorgangDetailFormDataTableComponent, +} from './vorgang-detail-form-data-table.component'; describe('VorgangDetailFormDataTableComponent', () => { - let component: VorgangDetailFormDataTableComponent; - let fixture: ComponentFixture<VorgangDetailFormDataTableComponent>; + let component: VorgangDetailFormDataTableComponent; + let fixture: ComponentFixture<VorgangDetailFormDataTableComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailFormDataTableComponent, - MockComponent(ExpansionPanelComponent) - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VorgangDetailFormDataTableComponent, MockComponent(ExpansionPanelComponent)], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailFormDataTableComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailFormDataTableComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('isExpandable', () => { + describe('isExpandable', () => { + describe('should return true', () => { + it('on object with object as value', () => { + const value: FormField = { + value: { + oneNode: {}, + }, + }; - describe('should return true', () => { + const result: boolean = component.isExpandable(value); - it('on object with object as value', () => { - const value: FormField = { - value: { - oneNode: {}, - } - }; + expect(result).toBeTruthy(); + }); - const result: boolean = component.isExpandable(value); + it('on object with array as value', () => { + const value: FormField = { + value: [ + { + oneNode: {}, + }, + ], + }; - expect(result).toBeTruthy(); - }) + const result: boolean = component.isExpandable(value); - it('on object with array as value', () => { - const value: FormField = { - value: [{ - oneNode: {}, - }] - }; + expect(result).toBeTruthy(); + }); + }); - const result: boolean = component.isExpandable(value); + describe('should return false', () => { + it('on object with string as value', () => { + const value: FormField = { value: 'StringValue' }; - expect(result).toBeTruthy(); - }) - }) + const result: boolean = component.isExpandable(value); - describe('should return false', () => { + expect(result).toBeFalsy(); + }); - it('on object with string as value', () => { - const value: FormField = { value: 'StringValue' }; + it('on object without value', () => { + const result: boolean = component.isExpandable({ irgendwasAusserValue: 'zb' }); - const result: boolean = component.isExpandable(value); + expect(result).toBeFalsy(); + }); + }); + }); - expect(result).toBeFalsy(); - }) + describe('hasLabel', () => { + it('should return true if node has label', () => { + const value: FormField = { value: 'value', label: 'TestLabel' }; - it('on object without value', () => { - const result: boolean = component.isExpandable({ irgendwasAusserValue: 'zb'}); + const result: boolean = component.hasLabel(value); - expect(result).toBeFalsy(); - }) - }) - }); + expect(result).toBeTruthy(); + }); - describe('hasLabel', () => { + it('should return false if node has no label', () => { + const value: FormField = { value: 'value' }; - it('should return true if node has label', () => { - const value: FormField = { value: 'value', label: 'TestLabel' }; + const result: boolean = component.hasLabel(value); - const result: boolean = component.hasLabel(value); + expect(result).toBeFalsy(); + }); + }); - expect(result).toBeTruthy(); - }) + describe('getFieldLabel', () => { + it('should return field label from node with label', () => { + const row = { key: 'label', value: { value: 'valueWithLabel', label: 'TestLabel' } }; - it('should return false if node has no label', () => { - const value: FormField = { value: 'value' }; + const label: string = component.getLabel(row); - const result: boolean = component.hasLabel(value); + expect(label).toBe('TestLabel'); + }); - expect(result).toBeFalsy(); - }) - }) + it('should return field key from node without label', () => { + const row = { key: 'value', value: { value: 'simpleValue' } }; - describe('getFieldLabel', () => { - it('should return field label from node with label', () => { - const row = { key: 'label', value: { value: 'valueWithLabel', label: 'TestLabel' } }; + const label: string = component.getLabel(row); - const label: string = component.getLabel(row) - - expect(label).toBe('TestLabel'); - }) - - it('should return field key from node without label', () => { - const row = { key: 'value', value: { value: 'simpleValue' } }; - - const label: string = component.getLabel(row) - - expect(label).toBe(row.key); - }) - }) + expect(label).toBe(row.key); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.ts index 10563967bf35975353605468a04ca90f2940ea92..59480bd19ad07e62fd2e25c35dd91ae9e0549baa 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-form-data-table/vorgang-detail-form-data-table.component.ts @@ -26,43 +26,42 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'; import { isArray, isObject, isString } from 'lodash-es'; @Component({ - selector: 'alfa-vorgang-detail-form-data-table', - templateUrl: './vorgang-detail-form-data-table.component.html', - styleUrls: ['./vorgang-detail-form-data-table.component.scss'], - changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'alfa-vorgang-detail-form-data-table', + templateUrl: './vorgang-detail-form-data-table.component.html', + styleUrls: ['./vorgang-detail-form-data-table.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush, }) export class VorgangDetailFormDataTableComponent { + @Input() formData: ReadonlyMap<number, string> | object; - @Input() formData: ReadonlyMap<number, string> | object; + readonly valueKey = 'value'; + readonly labelKey = 'label'; - readonly valueKey = 'value'; - readonly labelKey = 'label'; + public isArray = isArray; + public isObject = isObject; - public isArray = isArray; - public isObject = isObject; + public originalOrder = (a: KeyValue<number, string>, b: KeyValue<number, string>): number => { + return 0; + }; - public originalOrder = (a: KeyValue<number, string>, b: KeyValue<number, string>): number => { - return 0; - } + public isExpandable(value: unknown): boolean { + return this.hasValue(value) && !isString((<FormField>value).value); + } - public isExpandable(value: unknown): boolean { - return this.hasValue(value) && !isString((<FormField>value).value); - } + private hasValue(value: unknown): boolean { + return value.hasOwnProperty(this.valueKey); + } - private hasValue(value: unknown): boolean { - return value.hasOwnProperty(this.valueKey); - } + public getLabel(row: any): string { + return this.hasLabel(row.value) ? row.value.label : row.key; + } - public getLabel(row: any): string { - return this.hasLabel(row.value) ? row.value.label : row.key; - } - - hasLabel(value: unknown): boolean { - return value.hasOwnProperty(this.labelKey); - } + hasLabel(value: unknown): boolean { + return value.hasOwnProperty(this.labelKey); + } } export interface FormField { - value: object | string, - label?: string, -} \ No newline at end of file + value: object | string; + label?: string; +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html index 8cc03b1f500f31c7f08a563ae6a05d809ae11702..fdb75c0c568b35de0627f2b6295459812f1d2b8f 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.html @@ -23,34 +23,61 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ozgcloud-expansion-panel *ngIf="vorgangWithEingang.eingang" data-test-id="formulardaten-panel" - headline="Formulardaten"> - - <mat-tab-group mat-stretch-tabs="false" mat-align-tabs="start" animationDuration="0" [selectedIndex]="defaultSelection"> - <mat-tab label="Antragsdaten"> - <alfa-vorgang-detail-antrag-data [eingang]="vorgangWithEingang.eingang" [antragsData]="antragsData"></alfa-vorgang-detail-antrag-data> - </mat-tab> - <mat-tab label="Metadaten" [disabled]="!metaData"> - <alfa-vorgang-detail-meta-data data-test-id="tab-meta-data"[metaData]="metaData"></alfa-vorgang-detail-meta-data> - </mat-tab> - <mat-tab label="Datenrepräsentation ({{vorgangWithEingang.eingang.numberOfRepresentations}})" - [disabled]="vorgangWithEingang | notHasLink: vorgangWithEingangLinkRel.REPRESENTATIONS"> - <ng-template matTabContent> - <alfa-vorgang-detail-representation-list data-test-id="tab-representations-list" [vorgangWithEingang]="vorgangWithEingang"></alfa-vorgang-detail-representation-list> - </ng-template> - </mat-tab> - <mat-tab label="Anhänge ({{vorgangWithEingang.eingang.numberOfAttachments}})" - [disabled]="vorgangWithEingang | notHasLink: vorgangWithEingangLinkRel.ATTACHMENTS"> - <ng-template matTabContent> - <alfa-vorgang-detail-attachment-list data-test-id="tab-attachments-list" [vorgangWithEingang]="vorgangWithEingang"></alfa-vorgang-detail-attachment-list> - </ng-template> - </mat-tab> - <mat-tab label="Historie" *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.HISTORIE"> - <ng-template matTabContent> - <alfa-historie-container data-test-id="tab-historie-container" [vorgangWithEingang]="vorgangWithEingang"></alfa-historie-container> - </ng-template> - </mat-tab> - </mat-tab-group> - +<ozgcloud-expansion-panel + *ngIf="vorgangWithEingang.eingang" + data-test-id="formulardaten-panel" + headline="Formulardaten" +> + <mat-tab-group + mat-stretch-tabs="false" + mat-align-tabs="start" + animationDuration="0" + [selectedIndex]="defaultSelection" + > + <mat-tab label="Antragsdaten"> + <alfa-vorgang-detail-antrag-data + [eingang]="vorgangWithEingang.eingang" + [antragsData]="antragsData" + ></alfa-vorgang-detail-antrag-data> + </mat-tab> + <mat-tab label="Metadaten" [disabled]="!metaData"> + <alfa-vorgang-detail-meta-data + data-test-id="tab-meta-data" + [metaData]="metaData" + ></alfa-vorgang-detail-meta-data> + </mat-tab> + <mat-tab + label="Datenrepräsentation ({{ vorgangWithEingang.eingang.numberOfRepresentations }})" + [disabled]="vorgangWithEingang | notHasLink: vorgangWithEingangLinkRel.REPRESENTATIONS" + > + <ng-template matTabContent> + <alfa-vorgang-detail-representation-list + data-test-id="tab-representations-list" + [vorgangWithEingang]="vorgangWithEingang" + ></alfa-vorgang-detail-representation-list> + </ng-template> + </mat-tab> + <mat-tab + label="Anhänge ({{ vorgangWithEingang.eingang.numberOfAttachments }})" + [disabled]="vorgangWithEingang | notHasLink: vorgangWithEingangLinkRel.ATTACHMENTS" + > + <ng-template matTabContent> + <alfa-vorgang-detail-attachment-list + data-test-id="tab-attachments-list" + [vorgangWithEingang]="vorgangWithEingang" + ></alfa-vorgang-detail-attachment-list> + </ng-template> + </mat-tab> + <mat-tab + label="Historie" + *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.HISTORIE" + > + <ng-template matTabContent> + <alfa-historie-container + data-test-id="tab-historie-container" + [vorgangWithEingang]="vorgangWithEingang" + ></alfa-historie-container> + </ng-template> + </mat-tab> + </mat-tab-group> </ozgcloud-expansion-panel> - diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.scss index 9f607857523b629e18fa464c85895762ed6b3499..0398e355577626ab5eb2c15f4a48ef0779fcc557 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.scss @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ mat-tab-group { - padding-right: 1rem; + padding-right: 1rem; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts index 3e20131c52d576c3549153870e4ea1defd0fdf49..dfe0151ba8bf70bb061b862471ec6b678e1b1952 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.spec.ts @@ -38,177 +38,174 @@ import { VorgangDetailMetaDataComponent } from './vorgang-detail-meta-data/vorga import { VorgangDetailRepresentationListComponent } from './vorgang-detail-representation-list/vorgang-detail-representation-list.component'; describe('VorgangDetailFormularDatenComponent', () => { - let component: VorgangDetailFormularDatenComponent; - let fixture: ComponentFixture<VorgangDetailFormularDatenComponent>; + let component: VorgangDetailFormularDatenComponent; + let fixture: ComponentFixture<VorgangDetailFormularDatenComponent>; + + const tabMetaData: string = getTabByIndex(2); + const tabRepresentations: string = getTabByIndex(3); + const tabAttachments: string = getTabByIndex(4); + const tabHistorie: string = getTabByIndex(5); + + function getTabByIndex(index: number): string { + return `div[role=tab]:nth-child(${index})`; + } + + const disabledTabClass: string = 'mat-mdc-tab-disabled'; + + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const vorgangWithHistorie: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.HISTORIE, + ]); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [NoopAnimationsModule, MatTabsModule], + declarations: [ + HasLinkPipe, + NotHasLinkPipe, + VorgangDetailFormularDatenComponent, + MockComponent(VorgangDetailAntragDataComponent), + MockComponent(VorgangDetailMetaDataComponent), + MockComponent(VorgangDetailAttachmentListComponent), + MockComponent(VorgangDetailRepresentationListComponent), + MockComponent(ExpansionPanelComponent), + MockComponent(HistorieContainerComponent), + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailFormularDatenComponent); + component = fixture.componentInstance; + component.vorgangWithEingang = vorgangWithEingang; + fixture.detectChanges(); + }); - const tabMetaData: string = getTabByIndex(2);; - const tabRepresentations: string = getTabByIndex(3); - const tabAttachments: string = getTabByIndex(4); - const tabHistorie: string = getTabByIndex(5); + it('should create', () => { + expect(component).toBeTruthy(); + }); - function getTabByIndex(index: number): string { - return `div[role=tab]:nth-child(${ index })` - } + describe('Metadaten', () => { + it('should show tab enabled if Vorgang contains metadata', () => { + component.metaData = { test: 'testValue' }; - const disabledTabClass: string = 'mat-mdc-tab-disabled'; + fixture.detectChanges(); + const metaDataTab = getElementFromFixture(fixture, tabMetaData); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const vorgangWithHistorie: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.HISTORIE]); + expect(metaDataTab).not.toHaveClass(disabledTabClass); + }); - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - NoopAnimationsModule, - MatTabsModule - ], - declarations: [ - HasLinkPipe, - NotHasLinkPipe, - VorgangDetailFormularDatenComponent, - MockComponent(VorgangDetailAntragDataComponent), - MockComponent(VorgangDetailMetaDataComponent), - MockComponent(VorgangDetailAttachmentListComponent), - MockComponent(VorgangDetailRepresentationListComponent), - MockComponent(ExpansionPanelComponent), - MockComponent(HistorieContainerComponent), - ] - }).compileComponents(); - }); + it('should disable tab if Vorgang contains no metadata', () => { + fixture.detectChanges(); + const metaDataTab = getElementFromFixture(fixture, tabMetaData); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailFormularDatenComponent); - component = fixture.componentInstance; - component.vorgangWithEingang = vorgangWithEingang; - fixture.detectChanges(); - }); + expect(metaDataTab).toHaveClass(disabledTabClass); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should show MetaData label', () => { + fixture.detectChanges(); + const metaDataTab = getElementFromFixture(fixture, tabMetaData); - describe('Metadaten', () => { + expect(metaDataTab).toHaveTextContent('Metadaten'); + }); + }); - it('should show tab enabled if Vorgang contains metadata', () => { - component.metaData = { 'test': 'testValue' }; + describe('Tab Datenrepräsentation', () => { + const vorgangWithRepresentations: VorgangWithEingangResource = createVorgangWithEingangResource( + [VorgangWithEingangLinkRel.REPRESENTATIONS], + ); - fixture.detectChanges(); - const metaDataTab = getElementFromFixture(fixture, tabMetaData); + it('should be enabled and selected if representations links is present', () => { + component.vorgangWithEingang = vorgangWithRepresentations; - expect(metaDataTab).not.toHaveClass(disabledTabClass); - }) + fixture.detectChanges(); + const tab = getElementFromFixture(fixture, tabRepresentations); - it('should disable tab if Vorgang contains no metadata', () => { - fixture.detectChanges(); - const metaDataTab = getElementFromFixture(fixture, tabMetaData); + expect(tab).not.toHaveClass(disabledTabClass); + expect(tab).toHaveAttribute('aria-selected', 'true'); + }); - expect(metaDataTab).toHaveClass(disabledTabClass); - }) + it('should be disable and not selected if representations link is NOT present', () => { + component.vorgangWithEingang = vorgangWithEingang; - it('should show MetaData label', () => { - fixture.detectChanges(); - const metaDataTab = getElementFromFixture(fixture, tabMetaData); + fixture.detectChanges(); + const tab = getElementFromFixture(fixture, tabRepresentations); - expect(metaDataTab).toHaveTextContent('Metadaten'); - }) - }) + expect(tab).toHaveClass(disabledTabClass); + expect(tab).toHaveAttribute('aria-selected', 'false'); + }); - describe('Tab Datenrepräsentation', () => { + it('should show number of Representations in the label', () => { + component.vorgangWithEingang = vorgangWithRepresentations; - const vorgangWithRepresentations: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.REPRESENTATIONS]); + fixture.detectChanges(); + const tab = getElementFromFixture(fixture, tabRepresentations); + const tabLabel = `Datenrepräsentation (${vorgangWithRepresentations.eingang.numberOfRepresentations})`; - it('should be enabled and selected if representations links is present', () => { - component.vorgangWithEingang = vorgangWithRepresentations; + expect(tab).toHaveTextContent(tabLabel); + }); + }); - fixture.detectChanges(); - const tab = getElementFromFixture(fixture, tabRepresentations); + describe('Tab Anhänge', () => { + const vorgangWithAttachments: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.ATTACHMENTS, + ]); - expect(tab).not.toHaveClass(disabledTabClass); - expect(tab).toHaveAttribute('aria-selected', 'true'); - }) + it('should be enabled if attachments link is present', () => { + component.vorgangWithEingang = vorgangWithAttachments; - it('should be disable and not selected if representations link is NOT present', () => { - component.vorgangWithEingang = vorgangWithEingang; + fixture.detectChanges(); + const tab = getElementFromFixture(fixture, tabAttachments); - fixture.detectChanges(); - const tab = getElementFromFixture(fixture, tabRepresentations); + expect(tab).not.toHaveClass(disabledTabClass); + }); - expect(tab).toHaveClass(disabledTabClass); - expect(tab).toHaveAttribute('aria-selected', 'false'); - }) + it('should be disable if attachments link is NOT present', () => { + component.vorgangWithEingang = vorgangWithEingang; - it('should show number of Representations in the label', () => { - component.vorgangWithEingang = vorgangWithRepresentations; + fixture.detectChanges(); + const tab = getElementFromFixture(fixture, tabAttachments); - fixture.detectChanges(); - const tab = getElementFromFixture(fixture, tabRepresentations); - const tabLabel = `Datenrepräsentation (${vorgangWithRepresentations.eingang.numberOfRepresentations})`; + expect(tab).toHaveClass(disabledTabClass); + }); - expect(tab).toHaveTextContent(tabLabel); - }) + it('should show number of Attachments in the label', () => { + component.vorgangWithEingang = vorgangWithAttachments; - }) + fixture.detectChanges(); + const tab = getElementFromFixture(fixture, tabAttachments); + const tabLabel = `Anhänge (${vorgangWithAttachments.eingang.numberOfAttachments})`; - describe('Tab Anhänge', () => { + expect(tab).toHaveTextContent(tabLabel); + }); + }); - const vorgangWithAttachments: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ATTACHMENTS]); + describe('Tab Historie', () => { + it('should be visible if Link "historie" exists', () => { + component.vorgangWithEingang = vorgangWithHistorie; - it('should be enabled if attachments link is present', () => { - component.vorgangWithEingang = vorgangWithAttachments; + fixture.detectChanges(); + const tab = getElementFromFixture(fixture, tabHistorie); - fixture.detectChanges(); - const tab = getElementFromFixture(fixture, tabAttachments); + expect(tab).toBeInTheDocument(); + }); - expect(tab).not.toHaveClass(disabledTabClass); - }) + it('should not be visible if no Link "historie"', () => { + component.vorgangWithEingang = vorgangWithEingang; - it('should be disable if attachments link is NOT present', () => { - component.vorgangWithEingang = vorgangWithEingang; + fixture.detectChanges(); + const tab = getElementFromFixture(fixture, tabHistorie); - fixture.detectChanges(); - const tab = getElementFromFixture(fixture, tabAttachments); + expect(tab).not.toBeInTheDocument(); + }); - expect(tab).toHaveClass(disabledTabClass); - }) + it('should show historie label', () => { + component.vorgangWithEingang = vorgangWithHistorie; - it('should show number of Attachments in the label', () => { - component.vorgangWithEingang = vorgangWithAttachments; + fixture.detectChanges(); + const metaDataTab = getElementFromFixture(fixture, tabHistorie); - fixture.detectChanges(); - const tab = getElementFromFixture(fixture, tabAttachments); - const tabLabel = `Anhänge (${vorgangWithAttachments.eingang.numberOfAttachments})`; - - expect(tab).toHaveTextContent(tabLabel); - }) - }) - - describe('Tab Historie', () => { - - it('should be visible if Link "historie" exists', () => { - component.vorgangWithEingang = vorgangWithHistorie; - - fixture.detectChanges(); - const tab = getElementFromFixture(fixture, tabHistorie); - - expect(tab).toBeInTheDocument(); - }) - - it('should not be visible if no Link "historie"', () => { - component.vorgangWithEingang = vorgangWithEingang; - - fixture.detectChanges(); - const tab = getElementFromFixture(fixture, tabHistorie); - - expect(tab).not.toBeInTheDocument(); - }) - - it('should show historie label', () => { - component.vorgangWithEingang = vorgangWithHistorie; - - fixture.detectChanges(); - const metaDataTab = getElementFromFixture(fixture, tabHistorie); - - expect(metaDataTab).toHaveTextContent('Historie'); - }) - }) - -}); \ No newline at end of file + expect(metaDataTab).toHaveTextContent('Historie'); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.ts index af81c929b11800062455cf2a95c6cdbee9bda646..89c9894be1cd94b8e61ce7981abf3f4688c33caf 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-formular-daten.component.ts @@ -26,24 +26,23 @@ import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-cli import { hasLink } from '@ngxp/rest'; @Component({ - selector: 'alfa-vorgang-detail-formular-daten', - templateUrl: './vorgang-detail-formular-daten.component.html', - styleUrls: ['./vorgang-detail-formular-daten.component.scss'], + selector: 'alfa-vorgang-detail-formular-daten', + templateUrl: './vorgang-detail-formular-daten.component.html', + styleUrls: ['./vorgang-detail-formular-daten.component.scss'], }) export class VorgangDetailFormularDatenComponent implements OnInit { + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() vorgangWithEingang: VorgangWithEingangResource; + metaData: object; + antragsData: object; - metaData: object; - antragsData: object; + readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; - readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; + ngOnInit(): void { + this.antragsData = this.vorgangWithEingang.eingang.formData; + } - ngOnInit(): void { - this.antragsData = this.vorgangWithEingang.eingang.formData; - } - - get defaultSelection(): number { - return hasLink(this.vorgangWithEingang, this.vorgangWithEingangLinkRel.REPRESENTATIONS) ? 2 : 0; - } -} \ No newline at end of file + get defaultSelection(): number { + return hasLink(this.vorgangWithEingang, this.vorgangWithEingangLinkRel.REPRESENTATIONS) ? 2 : 0; + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.html index d86d88b0f1cf3baa909b0262f62b525cc011fb03..993f0b128ebd152b9b054e1f2c76acd5c54fd198 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.html @@ -23,4 +23,7 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-vorgang-detail-form-data-table data-test-id="metadaten" [formData]="metaData"></alfa-vorgang-detail-form-data-table> +<alfa-vorgang-detail-form-data-table + data-test-id="metadaten" + [formData]="metaData" +></alfa-vorgang-detail-form-data-table> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.scss index 23b0dc2dbe267d14a6dae801e964d2af13e73614..b571b3c71b2625b19658760f31f072dc3134468d 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.scss @@ -22,7 +22,7 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: inline-block; - margin-top: 0.5rem; - overflow: hidden; -} \ No newline at end of file + display: inline-block; + margin-top: 0.5rem; + overflow: hidden; +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.spec.ts index 27775a4301233ebaa80cf86e7c7ce40b47cf7902..9a253e89f86b3dd11bfe9811f02f0839b141e315 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.spec.ts @@ -27,25 +27,25 @@ import { VorgangDetailFormDataTableComponent } from '../vorgang-detail-form-data import { VorgangDetailMetaDataComponent } from './vorgang-detail-meta-data.component'; describe('VorgangDetailMetaDataComponent', () => { - let component: VorgangDetailMetaDataComponent; - let fixture: ComponentFixture<VorgangDetailMetaDataComponent>; + let component: VorgangDetailMetaDataComponent; + let fixture: ComponentFixture<VorgangDetailMetaDataComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailMetaDataComponent, - MockComponent(VorgangDetailFormDataTableComponent), - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangDetailMetaDataComponent, + MockComponent(VorgangDetailFormDataTableComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailMetaDataComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailMetaDataComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.ts index 4633c9cef816762b560fbfc1d88ce40273da5946..1ab47d3436611b4542506e51920f2e3dda936b6a 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-meta-data/vorgang-detail-meta-data.component.ts @@ -26,9 +26,8 @@ import { Component, Input } from '@angular/core'; @Component({ selector: 'alfa-vorgang-detail-meta-data', templateUrl: './vorgang-detail-meta-data.component.html', - styleUrls: ['./vorgang-detail-meta-data.component.scss'] + styleUrls: ['./vorgang-detail-meta-data.component.scss'], }) export class VorgangDetailMetaDataComponent { - - @Input() metaData: object; + @Input() metaData: object; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.html index e51ffc5c6bdadfed1ead96cb98f6c6baa2fdb3ad..0c6b5172652511b4c53e0ace77438a6a55b0728a 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.html @@ -24,7 +24,7 @@ --> <alfa-vertical-binary-file-list - [fileListResource]="fileListResource$ | async" - [downloadFileNamePrefix]="vorgangWithEingang.nummer" + [fileListResource]="fileListResource$ | async" + [downloadFileNamePrefix]="vorgangWithEingang.nummer" > </alfa-vertical-binary-file-list> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.spec.ts index 016a5a674e4e7cd99e8fefdcab6cbaad1b3d94d6..04a6e0a8f98a6568cade6dadaa49deeab04ebeab 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.spec.ts @@ -24,55 +24,57 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { VerticalBinaryFileListComponent } from '@alfa-client/binary-file'; import { mock } from '@alfa-client/test-utils'; -import { VorgangService, VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangService, + VorgangWithEingangLinkRel, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { MockComponent } from 'ng-mocks'; import { VorgangDetailRepresentationListComponent } from './vorgang-detail-representation-list.component'; - describe('VorgangDetailRepresentationListComponent', () => { - let component: VorgangDetailRepresentationListComponent; - let fixture: ComponentFixture<VorgangDetailRepresentationListComponent>; - - const vorgangService = mock(VorgangService); - const vorgangWithRepresentations: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.REPRESENTATIONS]); + let component: VorgangDetailRepresentationListComponent; + let fixture: ComponentFixture<VorgangDetailRepresentationListComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailRepresentationListComponent, - MockComponent(VerticalBinaryFileListComponent), - ], - providers: [ - { - provide: VorgangService, - useValue: vorgangService, - }, - ], - }).compileComponents(); - }); + const vorgangService = mock(VorgangService); + const vorgangWithRepresentations: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.REPRESENTATIONS, + ]); - beforeEach(() => { - fixture = TestBed.createComponent( - VorgangDetailRepresentationListComponent - ); - component = fixture.componentInstance; - component.vorgangWithEingang = createVorgangWithEingangResource(); - fixture.detectChanges(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangDetailRepresentationListComponent, + MockComponent(VerticalBinaryFileListComponent), + ], + providers: [ + { + provide: VorgangService, + useValue: vorgangService, + }, + ], + }).compileComponents(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailRepresentationListComponent); + component = fixture.componentInstance; + component.vorgangWithEingang = createVorgangWithEingangResource(); + fixture.detectChanges(); + }); - describe('on vorgang with "representation" link', () => { - it('should call vorgangService methods', () => { - component.vorgangWithEingang = vorgangWithRepresentations; + it('should create', () => { + expect(component).toBeTruthy(); + }); - component.ngOnInit(); + describe('on vorgang with "representation" link', () => { + it('should call vorgangService methods', () => { + component.vorgangWithEingang = vorgangWithRepresentations; - expect(vorgangService.getRepresentations).toHaveBeenCalled(); - }); - }); + component.ngOnInit(); + expect(vorgangService.getRepresentations).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.ts index 20b493edcbb05ee08b8153d30ec1ec280db45ec2..2007d106199389a23bd6370bee91fd36f5cfca2f 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-formular-daten/vorgang-detail-representation-list/vorgang-detail-representation-list.component.ts @@ -28,19 +28,20 @@ import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-detail-representation-list', - templateUrl: './vorgang-detail-representation-list.component.html', - styleUrls: ['./vorgang-detail-representation-list.component.scss'] + selector: 'alfa-vorgang-detail-representation-list', + templateUrl: './vorgang-detail-representation-list.component.html', + styleUrls: ['./vorgang-detail-representation-list.component.scss'], }) export class VorgangDetailRepresentationListComponent implements OnInit { + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() vorgangWithEingang: VorgangWithEingangResource; + fileListResource$: Observable<StateResource<BinaryFileListResource>> = of( + createEmptyStateResource<BinaryFileListResource>(), + ); - fileListResource$: Observable<StateResource<BinaryFileListResource>> = of(createEmptyStateResource<BinaryFileListResource>()); + constructor(private vorgangService: VorgangService) {} - constructor(private vorgangService: VorgangService) { } - - ngOnInit(): void { - this.fileListResource$ = this.vorgangService.getRepresentations(); - } -} \ No newline at end of file + ngOnInit(): void { + this.fileListResource$ = this.vorgangService.getRepresentations(); + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.html index ef6a1b7579181d0d7aed400cfceedba2141f3d71..ce3a0bb498d0e3e4dbaf85a8e9776095c45982c9 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.html @@ -25,21 +25,34 @@ --> <alfa-vorgang-status-dot [status]="vorgang.status" class="status-dot"></alfa-vorgang-status-dot> -<alfa-vorgang-status-text [status]="vorgang.status" data-test-id="status-text" - class="status-text"></alfa-vorgang-status-text> - -<div class="initial-date" data-test-id="created-at">{{ vorgang.createdAt | date : 'EEEE, d. LLLL y, H:mm'}}</div> +<alfa-vorgang-status-text + [status]="vorgang.status" + data-test-id="status-text" + class="status-text" +></alfa-vorgang-status-text> + +<div class="initial-date" data-test-id="created-at"> + {{ vorgang.createdAt | date: 'EEEE, d. LLLL y, H:mm' }} +</div> <alfa-vorgang-nummer class="vorgang-nummer big" [vorgang]="vorgang"></alfa-vorgang-nummer> <div class="aktenzeichen" [class.aktenzeichen--active]="hasAktenzeichen"> - <mat-icon svgIcon="az"></mat-icon> - <alfa-aktenzeichen-editable class="aktenzeichen-editable" [vorgang]="vorgang"></alfa-aktenzeichen-editable> + <mat-icon svgIcon="az"></mat-icon> + <alfa-aktenzeichen-editable + class="aktenzeichen-editable" + [vorgang]="vorgang" + ></alfa-aktenzeichen-editable> </div> -<div data-test-id="name" class="name">{{ vorgang.name }}</div> +<div data-test-id="name" class="name"> + {{ vorgang.name }} +</div> -<alfa-user-profile-in-vorgang-container *ngIf="vorgang | hasLink: linkRel.ASSIGN" data-test-id="vorgang-header-user-icon" - [vorgang]="vorgang" - class="user"> +<alfa-user-profile-in-vorgang-container + *ngIf="vorgang | hasLink: linkRel.ASSIGN" + data-test-id="vorgang-header-user-icon" + [vorgang]="vorgang" + class="user" +> </alfa-user-profile-in-vorgang-container> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.scss index e93e5ba611a2bace877622f9d9178825c80e9d21..07b88a6e807731512de0b029fad0310132830226 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.scss @@ -26,82 +26,82 @@ @import 'variables'; :host { - display: grid; - row-gap: 10px; - align-items: center; - grid-template-columns: 48px 1fr 8%; - grid-template-areas: - "status-dot status-text initial-date" - ". name user" - ". vorgang-nummer user" - ". aktenzeichen aktenzeichen"; + display: grid; + row-gap: 10px; + align-items: center; + grid-template-columns: 48px 1fr 8%; + grid-template-areas: + 'status-dot status-text initial-date' + '. name user' + '. vorgang-nummer user' + '. aktenzeichen aktenzeichen'; - padding: 1rem 1.5rem; + padding: 1rem 1.5rem; } .name { - line-height: 1.4; - margin: 8px 0 4px 0; - font-size: 16px; - font-weight: 500; + line-height: 1.4; + margin: 8px 0 4px 0; + font-size: 16px; + font-weight: 500; } .ellipsis { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } mat-icon { - margin: 0 0.5rem 0 -0rem; - height: 1.875rem; - min-height: 1.875rem; - width: 1.875rem; - min-width: 1.875rem; + margin: 0 0.5rem 0 -0rem; + height: 1.875rem; + min-height: 1.875rem; + width: 1.875rem; + min-width: 1.875rem; } .status-dot { - grid-area: status-dot; + grid-area: status-dot; } .status-text { - grid-area: status-text; + grid-area: status-text; } .initial-date { - grid-area: initial-date; - justify-self: end; - white-space: nowrap; + grid-area: initial-date; + justify-self: end; + white-space: nowrap; } .aktenzeichen { - grid-area: aktenzeichen; - margin-left: -2px; - display: flex; - align-items: center; - color: #c2c2c2; + grid-area: aktenzeichen; + margin-left: -2px; + display: flex; + align-items: center; + color: #c2c2c2; - &--active { - color: unset; - } + &--active { + color: unset; + } - .aktenzeichen-editable { - width: calc(100% - 82px); - } + .aktenzeichen-editable { + width: calc(100% - 82px); + } } .vorgang-nummer { - grid-area: vorgang-nummer; - margin-left: -2px; + grid-area: vorgang-nummer; + margin-left: -2px; } .name { - grid-area: name; - align-self: start; + grid-area: name; + align-self: start; } .user { - grid-area: user; - align-self: start; - justify-self: end; + grid-area: user; + align-self: start; + justify-self: end; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.spec.ts index 968591200b6c1739d36b8a204a0974de4cfb5e10..672de0dbf99b25da297705daa6b1bbc161978a8e 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.spec.ts @@ -26,7 +26,11 @@ import { MatIcon } from '@angular/material/icon'; import { MatIconTestingModule } from '@angular/material/icon/testing'; import { EMPTY_STRING, EnumToLabelPipe, HasLinkPipe } from '@alfa-client/tech-shared'; import { VorgangHeaderLinkRel } from '@alfa-client/vorgang-shared'; -import { VorgangNummerComponent, VorgangStatusDotComponent, VorgangStatusTextComponent } from '@alfa-client/vorgang-shared-ui'; +import { + VorgangNummerComponent, + VorgangStatusDotComponent, + VorgangStatusTextComponent, +} from '@alfa-client/vorgang-shared-ui'; import { UserProfileInVorgangContainerComponent } from 'libs/user-profile/src/lib/user-profile-in-vorgang-container/user-profile-in-vorgang-container.component'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { MockComponent } from 'ng-mocks'; @@ -36,96 +40,95 @@ import { getDebugElementFromFixtureByCss } from '@alfa-client/test-utils'; import { DebugElement } from '@angular/core'; describe('VorgangDetailHeaderComponent', () => { - let component: VorgangDetailHeaderComponent; - let fixture: ComponentFixture<VorgangDetailHeaderComponent>; - - const user: string = '[data-test-id="vorgang-header-user-icon"]'; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailHeaderComponent, - EnumToLabelPipe, - HasLinkPipe, - MatIcon, - MockComponent(UserProfileInVorgangContainerComponent), - MockComponent(VorgangStatusDotComponent), - MockComponent(VorgangStatusTextComponent), - MockComponent(AktenzeichenEditableComponent), - MockComponent(VorgangNummerComponent), - ], - imports: [ - MatIconTestingModule, - ], - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailHeaderComponent); - component = fixture.componentInstance; - component.vorgangWithEingang = createVorgangWithEingangResource(); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }) - - describe('bearbeiter/user icon', () => { - - it('should be visible', () => { - component.vorgangWithEingang = createVorgangWithEingangResource([VorgangHeaderLinkRel.ASSIGN]); - fixture.detectChanges(); - - const userElement = fixture.nativeElement.querySelector(user); - - expect(userElement).toBeInstanceOf(HTMLElement); - }) - - it('should NOT be visible', () => { - component.vorgangWithEingang = createVorgangWithEingangResource(); - fixture.detectChanges(); - - const userElement = fixture.nativeElement.querySelector(user); - - expect(userElement).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('set vorgangWithEingang', () => { - - it('should have Aktenzeichen', () => { - expect(component.hasAktenzeichen).toBeTruthy(); - }) - - it.each([null, EMPTY_STRING])('should NOT have aktenzeichen for %s', (aktenzeichen: string) => { - const vorgangWithEingang = createVorgangWithEingangResource(); - vorgangWithEingang.aktenzeichen = aktenzeichen; - component.vorgangWithEingang = vorgangWithEingang; - - expect(component.hasAktenzeichen).toBeFalsy(); - }) - - it('should set class aktenzeichen--active for aktenzeichen', () => { - fixture.detectChanges(); - - const element = getDebugElementFromFixtureByCss(fixture, 'div.aktenzeichen--active'); - - expect(element).toBeInstanceOf(DebugElement); - }) - - it.each([null, EMPTY_STRING])('should NOT set class aktenzeichen--active for aktenzeichen %s', (aktenzeichen: string) => { - const vorgangWithEingang = createVorgangWithEingangResource(); - vorgangWithEingang.aktenzeichen = aktenzeichen; - component.vorgangWithEingang = vorgangWithEingang; - - fixture.detectChanges(); - - const element = getDebugElementFromFixtureByCss(fixture, 'div.aktenzeichen--active'); - - expect(element).not.toBeInstanceOf(DebugElement); - }) - - }) - + let component: VorgangDetailHeaderComponent; + let fixture: ComponentFixture<VorgangDetailHeaderComponent>; + + const user: string = '[data-test-id="vorgang-header-user-icon"]'; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangDetailHeaderComponent, + EnumToLabelPipe, + HasLinkPipe, + MatIcon, + MockComponent(UserProfileInVorgangContainerComponent), + MockComponent(VorgangStatusDotComponent), + MockComponent(VorgangStatusTextComponent), + MockComponent(AktenzeichenEditableComponent), + MockComponent(VorgangNummerComponent), + ], + imports: [MatIconTestingModule], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailHeaderComponent); + component = fixture.componentInstance; + component.vorgangWithEingang = createVorgangWithEingangResource(); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('bearbeiter/user icon', () => { + it('should be visible', () => { + component.vorgangWithEingang = createVorgangWithEingangResource([ + VorgangHeaderLinkRel.ASSIGN, + ]); + fixture.detectChanges(); + + const userElement = fixture.nativeElement.querySelector(user); + + expect(userElement).toBeInstanceOf(HTMLElement); + }); + + it('should NOT be visible', () => { + component.vorgangWithEingang = createVorgangWithEingangResource(); + fixture.detectChanges(); + + const userElement = fixture.nativeElement.querySelector(user); + + expect(userElement).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('set vorgangWithEingang', () => { + it('should have Aktenzeichen', () => { + expect(component.hasAktenzeichen).toBeTruthy(); + }); + + it.each([null, EMPTY_STRING])('should NOT have aktenzeichen for %s', (aktenzeichen: string) => { + const vorgangWithEingang = createVorgangWithEingangResource(); + vorgangWithEingang.aktenzeichen = aktenzeichen; + component.vorgangWithEingang = vorgangWithEingang; + + expect(component.hasAktenzeichen).toBeFalsy(); + }); + + it('should set class aktenzeichen--active for aktenzeichen', () => { + fixture.detectChanges(); + + const element = getDebugElementFromFixtureByCss(fixture, 'div.aktenzeichen--active'); + + expect(element).toBeInstanceOf(DebugElement); + }); + + it.each([null, EMPTY_STRING])( + 'should NOT set class aktenzeichen--active for aktenzeichen %s', + (aktenzeichen: string) => { + const vorgangWithEingang = createVorgangWithEingangResource(); + vorgangWithEingang.aktenzeichen = aktenzeichen; + component.vorgangWithEingang = vorgangWithEingang; + + fixture.detectChanges(); + + const element = getDebugElementFromFixtureByCss(fixture, 'div.aktenzeichen--active'); + + expect(element).not.toBeInstanceOf(DebugElement); + }, + ); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.ts index 051811750bbb2022878076fe64f0efc8589ac9c3..e0a5d6854b61a58401ea6c9830a9b76ea8a95cbf 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-area/vorgang-detail-header/vorgang-detail-header.component.ts @@ -27,19 +27,20 @@ import { isNotEmpty } from '@alfa-client/tech-shared'; import { createVorgangWithEingangResource } from '../../../../../../vorgang-shared/test/vorgang'; @Component({ - selector: 'alfa-vorgang-detail-header', - templateUrl: './vorgang-detail-header.component.html', - styleUrls: ['./vorgang-detail-header.component.scss'] + selector: 'alfa-vorgang-detail-header', + templateUrl: './vorgang-detail-header.component.html', + styleUrls: ['./vorgang-detail-header.component.scss'], }) export class VorgangDetailHeaderComponent { + readonly linkRel = VorgangWithEingangLinkRel; - readonly linkRel = VorgangWithEingangLinkRel; + vorgang = createVorgangWithEingangResource(); + hasAktenzeichen = false; - vorgang = createVorgangWithEingangResource(); - hasAktenzeichen = false; - - @Input('vorgangWithEingang') set vorgangWithEingang(vorgangWithEingang: VorgangWithEingangResource) { - this.vorgang = vorgangWithEingang; - this.hasAktenzeichen = isNotEmpty(vorgangWithEingang.aktenzeichen); - } + @Input('vorgangWithEingang') set vorgangWithEingang( + vorgangWithEingang: VorgangWithEingangResource, + ) { + this.vorgang = vorgangWithEingang; + this.hasAktenzeichen = isNotEmpty(vorgangWithEingang.aktenzeichen); + } } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.html index 810960ac79334984415424025f202b220bfc0a8a..8934101398ef406d51e3da4037e9a710382d21b3 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.html @@ -23,4 +23,4 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-vorgang-detail-back-button [routePath]="routePath$ | async"></alfa-vorgang-detail-back-button> \ No newline at end of file +<alfa-vorgang-detail-back-button [routePath]="routePath$ | async"></alfa-vorgang-detail-back-button> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.spec.ts index 53ab203999239f198abaa7e2e355a8d91d913845..39e979600e15ac362af17ea1949c2e3ab955f0a4 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.spec.ts @@ -29,42 +29,41 @@ import { VorgangDetailBackButtonContainerComponent } from './vorgang-detail-back import { VorgangDetailBackButtonComponent } from './vorgang-detail-back-button/vorgang-detail-back-button.component'; describe('VorgangDetailBackButtonContainerComponent', () => { - let component: VorgangDetailBackButtonContainerComponent; - let fixture: ComponentFixture<VorgangDetailBackButtonContainerComponent>; + let component: VorgangDetailBackButtonContainerComponent; + let fixture: ComponentFixture<VorgangDetailBackButtonContainerComponent>; - const vorgangService = mock(VorgangService); + const vorgangService = mock(VorgangService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailBackButtonContainerComponent, - MockComponent(VorgangDetailBackButtonComponent) - ], - providers: [ - { - provide: VorgangService, - useValue: vorgangService - } - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangDetailBackButtonContainerComponent, + MockComponent(VorgangDetailBackButtonComponent), + ], + providers: [ + { + provide: VorgangService, + useValue: vorgangService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailBackButtonContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailBackButtonContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should call vorgangService getBackButtonUrl', () => { + component.ngOnInit(); - it('should call vorgangService getBackButtonUrl', () => { - component.ngOnInit(); - - expect(vorgangService.getBackButtonUrl).toHaveBeenCalled(); - }) - }) + expect(vorgangService.getBackButtonUrl).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.ts index bb32635ea8a0459362d31a2c868cbaefb7199bd9..398b076a0355c2e7784a8fe77c3360f7ca6a83e4 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button-container.component.ts @@ -26,17 +26,16 @@ import { VorgangService } from '@alfa-client/vorgang-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-detail-back-button-container', - templateUrl: './vorgang-detail-back-button-container.component.html', - styleUrls: ['./vorgang-detail-back-button-container.component.scss'] + selector: 'alfa-vorgang-detail-back-button-container', + templateUrl: './vorgang-detail-back-button-container.component.html', + styleUrls: ['./vorgang-detail-back-button-container.component.scss'], }) export class VorgangDetailBackButtonContainerComponent implements OnInit { + routePath$: Observable<string>; - routePath$: Observable<string> + constructor(private vorgangService: VorgangService) {} - constructor(private vorgangService: VorgangService) { } - - ngOnInit(): void { - this.routePath$ = this.vorgangService.getBackButtonUrl(); - } + ngOnInit(): void { + this.routePath$ = this.vorgangService.getBackButtonUrl(); + } } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.html index 3bfbfe78c25d0d6b700a28cde2eebac828c7a394..43b4236c8390d1dd077b0091e73ab60425f4ec6e 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.html @@ -23,4 +23,4 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ozgcloud-back-button [linkTo]="routePath" label="zurück zur Vorgangsliste"></ozgcloud-back-button> \ No newline at end of file +<ozgcloud-back-button [linkTo]="routePath" label="zurück zur Vorgangsliste"></ozgcloud-back-button> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.spec.ts index d1aa35990c9c5586eec219767d309d18b58861fa..507787ba91132eec55d6795c2346b4bc5fd6b496 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.spec.ts @@ -28,26 +28,22 @@ import { MockComponent } from 'ng-mocks'; import { VorgangDetailBackButtonComponent } from './vorgang-detail-back-button.component'; describe('VorgangDetailBackButtonComponent', () => { - let component: VorgangDetailBackButtonComponent; - let fixture: ComponentFixture<VorgangDetailBackButtonComponent>; + let component: VorgangDetailBackButtonComponent; + let fixture: ComponentFixture<VorgangDetailBackButtonComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MatIcon, - MockComponent(BackButtonComponent), - VorgangDetailBackButtonComponent - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [MatIcon, MockComponent(BackButtonComponent), VorgangDetailBackButtonComponent], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailBackButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailBackButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}) \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.ts index e79f93f1ffad3bb487117b721d6b7d897f321372..1ec4819605b6ccea076ba6f5efab52e230c8468e 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-back-button-container/vorgang-detail-back-button/vorgang-detail-back-button.component.ts @@ -24,12 +24,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'alfa-vorgang-detail-back-button', - templateUrl: './vorgang-detail-back-button.component.html', - styleUrls: ['./vorgang-detail-back-button.component.scss'] + selector: 'alfa-vorgang-detail-back-button', + templateUrl: './vorgang-detail-back-button.component.html', + styleUrls: ['./vorgang-detail-back-button.component.scss'], }) export class VorgangDetailBackButtonComponent { - - @Input() routePath: string; - -} \ No newline at end of file + @Input() routePath: string; +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html index d67c311da72cf9d259ca77979ca1e4585a16f425..6ca2dbaa357252cc367ef1109f7a506ecc9c278e 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.html @@ -1,21 +1,39 @@ -<button *ngIf="buttonEnabled" mat-icon-button [matMenuTriggerFor]="moreMenu.matMenu" #menuTrigger="matMenuTrigger" data-test-id="more-menu-button"> - <ozgcloud-icon icon="more_horiz"></ozgcloud-icon> +<button + *ngIf="buttonEnabled" + mat-icon-button + [matMenuTriggerFor]="moreMenu.matMenu" + #menuTrigger="matMenuTrigger" + data-test-id="more-menu-button" +> + <ozgcloud-icon icon="more_horiz"></ozgcloud-icon> </button> <ozgcloud-menu #moreMenu data-test-id="more-menu"> - <ozgcloud-menu-item *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.EXPORT" data-test-id="vorgang-exportieren-button" - headline="Vorgang exportieren" - text="Alle Informationen und Anhänge des Vorgangs zur Archivierung im DMS." - icon="xdomea_file" - [iconSizeBig]="true" - (click)="$event.stopPropagation()"> - <alfa-vorgang-export-container [vorgangWithEingang]="vorgangWithEingang" (closeMenu)="closeMenu()"></alfa-vorgang-export-container> - </ozgcloud-menu-item> - <ozgcloud-menu-item *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.PROCESS_VORGANG" data-test-id="vorgang-process-vorgang-button" - headline="Vorgang automatisiert vorprüfen" - text="Eine Vorprüfung wird durchgeführt. Das Ergebnis wird als Kommentar hinzugefügt." - icon="vorgang_vorpruefen" - [iconSizeBig]="true" - (click)="$event.stopPropagation()"> - <alfa-vorgang-process-vorgang-container [vorgangWithEingang]="vorgangWithEingang" (closeMenu)="closeMenu()"></alfa-vorgang-process-vorgang-container> - </ozgcloud-menu-item> + <ozgcloud-menu-item + *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.EXPORT" + data-test-id="vorgang-exportieren-button" + headline="Vorgang exportieren" + text="Alle Informationen und Anhänge des Vorgangs zur Archivierung im DMS." + icon="xdomea_file" + [iconSizeBig]="true" + (click)="$event.stopPropagation()" + > + <alfa-vorgang-export-container + [vorgangWithEingang]="vorgangWithEingang" + (closeMenu)="closeMenu()" + ></alfa-vorgang-export-container> + </ozgcloud-menu-item> + <ozgcloud-menu-item + *ngIf="vorgangWithEingang | hasLink: vorgangWithEingangLinkRel.PROCESS_VORGANG" + data-test-id="vorgang-process-vorgang-button" + headline="Vorgang automatisiert vorprüfen" + text="Eine Vorprüfung wird durchgeführt. Das Ergebnis wird als Kommentar hinzugefügt." + icon="vorgang_vorpruefen" + [iconSizeBig]="true" + (click)="$event.stopPropagation()" + > + <alfa-vorgang-process-vorgang-container + [vorgangWithEingang]="vorgangWithEingang" + (closeMenu)="closeMenu()" + ></alfa-vorgang-process-vorgang-container> + </ozgcloud-menu-item> </ozgcloud-menu> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts index cff674801959c6e3b928d231184d70de34f289bb..ccc2742029338f17a3ce3d1aa5a67535dde60af3 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.spec.ts @@ -1,4 +1,8 @@ -import { getElementFromDomRoot, getElementFromFixture, getMockComponent } from '@alfa-client/test-utils'; +import { + getElementFromDomRoot, + getElementFromFixture, + getMockComponent, +} from '@alfa-client/test-utils'; import { MenuItemComponent, OzgcloudIconComponent, UiModule } from '@alfa-client/ui'; import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; import { ChangeDetectorRef, SimpleChanges } from '@angular/core'; @@ -12,266 +16,269 @@ import { VorgangExportContainerComponent } from './vorgang-export-container/vorg import { ProcessVorgangContainerComponent } from './vorgang-process-vorgang-container/vorgang-process-vorgang-container.component'; describe('VorgangDetailMoreMenuComponent', () => { - let component: VorgangDetailMoreMenuComponent; - let fixture: ComponentFixture<VorgangDetailMoreMenuComponent>; + let component: VorgangDetailMoreMenuComponent; + let fixture: ComponentFixture<VorgangDetailMoreMenuComponent>; - const moreMenuButton: string = getDataTestIdOf('more-menu-button'); - const exportMenuItem: string = getDataTestIdOf('vorgang-exportieren-button'); - const processVorgangMenuItem: string = getDataTestIdOf('vorgang-process-vorgang-button'); + const moreMenuButton: string = getDataTestIdOf('more-menu-button'); + const exportMenuItem: string = getDataTestIdOf('vorgang-exportieren-button'); + const processVorgangMenuItem: string = getDataTestIdOf('vorgang-process-vorgang-button'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailMoreMenuComponent, - MockComponent(MenuItemComponent), - MockComponent(OzgcloudIconComponent), - MockComponent(VorgangExportContainerComponent), - MockComponent(ProcessVorgangContainerComponent) - ], - imports: [ - UiModule, - NoopAnimationsModule, - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangDetailMoreMenuComponent, + MockComponent(MenuItemComponent), + MockComponent(OzgcloudIconComponent), + MockComponent(VorgangExportContainerComponent), + MockComponent(ProcessVorgangContainerComponent), + ], + imports: [UiModule, NoopAnimationsModule], + }).compileComponents(); - fixture = TestBed.createComponent(VorgangDetailMoreMenuComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(VorgangDetailMoreMenuComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnChanges', () => { + describe('ngOnChanges', () => { + it('should call vorgangWithEingangChanged if vorgangWithEingang changed', () => { + const simpleChanges: SimpleChanges = <any>{ vorgangWithEingang: {} }; + const spy = jest.spyOn(component, 'vorgangWithEingangChanged'); - it('should call vorgangWithEingangChanged if vorgangWithEingang changed', () => { - const simpleChanges: SimpleChanges = <any>{ vorgangWithEingang: {} }; - const spy = jest.spyOn(component, 'vorgangWithEingangChanged'); + component.ngOnChanges(simpleChanges); - component.ngOnChanges(simpleChanges); + expect(spy).toHaveBeenCalled(); + }); - expect(spy).toHaveBeenCalled(); - }) + it('should not call vorgangWithEingangChanged if vorgangWithEingang did not change', () => { + const simpleChanges: SimpleChanges = <any>{ dummy: {} }; + const spy = jest.spyOn(component, 'vorgangWithEingangChanged'); - it('should not call vorgangWithEingangChanged if vorgangWithEingang did not change', () => { - const simpleChanges: SimpleChanges = <any>{ dummy: {} }; - const spy = jest.spyOn(component, 'vorgangWithEingangChanged'); + component.ngOnChanges(simpleChanges); - component.ngOnChanges(simpleChanges); + expect(spy).not.toHaveBeenCalled(); + }); + }); - expect(spy).not.toHaveBeenCalled(); - }) - }) + describe('vorgangWithEingangChanged', () => { + it('should call detectChanges', () => { + const changeDetectorRef = fixture.debugElement.injector.get(ChangeDetectorRef); + const detectChangesSpy = jest.spyOn(changeDetectorRef.constructor.prototype, 'detectChanges'); - describe('vorgangWithEingangChanged', () => { - it('should call detectChanges', () => { - const changeDetectorRef = fixture.debugElement.injector.get(ChangeDetectorRef); - const detectChangesSpy = jest.spyOn(changeDetectorRef.constructor.prototype, 'detectChanges'); + component.vorgangWithEingangChanged(); - component.vorgangWithEingangChanged(); + expect(detectChangesSpy).toHaveBeenCalled(); + }); - expect(detectChangesSpy).toHaveBeenCalled(); - }) + it('should call isButtonDisabled', () => { + const spy = jest.spyOn(component, 'isButtonEnabled'); - it('should call isButtonDisabled', () => { - const spy = jest.spyOn(component, 'isButtonEnabled'); + component.vorgangWithEingangChanged(); - component.vorgangWithEingangChanged(); + expect(spy).toHaveBeenCalled(); + }); + }); - expect(spy).toHaveBeenCalled(); - }) - }) + describe('isButtonEnabled', () => { + it('should return true if at least 1 menu item exists', () => { + component.menuItems.reset([new MenuItemComponent()]); - describe('isButtonEnabled', () => { - it('should return true if at least 1 menu item exists', () => { - component.menuItems.reset([new MenuItemComponent()]); + const res: boolean = component.isButtonEnabled(); - const res: boolean = component.isButtonEnabled(); + expect(res).toBeTruthy(); + }); - expect(res).toBeTruthy(); - }) + it('should return false if no menu item exists', () => { + component.menuItems.reset([]); - it('should return false if no menu item exists', () => { - component.menuItems.reset([]); + const res: boolean = component.isButtonEnabled(); - const res: boolean = component.isButtonEnabled(); + expect(res).toBeFalsy(); + }); + }); - expect(res).toBeFalsy(); - }) - }) + describe('closeMenu', () => { + //TODO Auf das event vom Button ausweiten + it.skip('should closeMenu by trigger', () => { + jest.spyOn(component.trigger, 'closeMenu'); - describe('closeMenu', () => { + component.closeMenu(); - //TODO Auf das event vom Button ausweiten - it.skip('should closeMenu by trigger', () => { - jest.spyOn(component.trigger, 'closeMenu'); + expect(component.trigger.closeMenu).toHaveBeenCalled(); + }); + }); - component.closeMenu(); + describe('export menu item', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.EXPORT, + ]); - expect(component.trigger.closeMenu).toHaveBeenCalled(); - }) - }) + beforeEach(() => { + component.buttonEnabled = true; + fixture.detectChanges(); + }); - describe('export menu item', () => { + it('should be visible if link exists', () => { + component.vorgangWithEingang = vorgangWithEingang; + fixture.detectChanges(); + getElementFromFixture(fixture, moreMenuButton).click(); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.EXPORT]); + const element = getElementFromDomRoot(fixture, exportMenuItem); - beforeEach(() => { - component.buttonEnabled = true; - fixture.detectChanges(); - }) + expect(element).toBeInTheDocument(); + }); - it('should be visible if link exists', () => { - component.vorgangWithEingang = vorgangWithEingang; - fixture.detectChanges(); - getElementFromFixture(fixture, moreMenuButton).click(); + it('should NOT be visible if link is missing', () => { + component.vorgangWithEingang = createVorgangWithEingangResource(); + fixture.detectChanges(); + getElementFromFixture(fixture, moreMenuButton).click(); - const element = getElementFromDomRoot(fixture, exportMenuItem); + const element = getElementFromDomRoot(fixture, exportMenuItem); - expect(element).toBeInTheDocument(); - }) + expect(element).not.toBeInTheDocument(); + }); - it('should NOT be visible if link is missing', () => { - component.vorgangWithEingang = createVorgangWithEingangResource(); - fixture.detectChanges(); - getElementFromFixture(fixture, moreMenuButton).click(); + describe('input property', () => { + beforeEach(() => { + component.vorgangWithEingang = vorgangWithEingang; + fixture.detectChanges(); + }); - const element = getElementFromDomRoot(fixture, exportMenuItem); + it('should contains headline', () => { + getElementFromFixture(fixture, moreMenuButton).click(); - expect(element).not.toBeInTheDocument(); - }) + const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); - describe('input property', () => { + expect(menuItem.headline).toBe('Vorgang exportieren'); + }); - beforeEach(() => { - component.vorgangWithEingang = vorgangWithEingang; - fixture.detectChanges(); - }) + it('should contains text', () => { + getElementFromFixture(fixture, moreMenuButton).click(); - it('should contains headline', () => { - getElementFromFixture(fixture, moreMenuButton).click(); + const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); + expect(menuItem.text).toBe( + 'Alle Informationen und Anhänge des Vorgangs zur Archivierung im DMS.', + ); + }); - expect(menuItem.headline).toBe('Vorgang exportieren'); - }) + it('should contains icon', () => { + getElementFromFixture(fixture, moreMenuButton).click(); - it('should contains text', () => { - getElementFromFixture(fixture, moreMenuButton).click(); + const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); + expect(menuItem.icon).toBe('xdomea_file'); + }); - expect(menuItem.text).toBe('Alle Informationen und Anhänge des Vorgangs zur Archivierung im DMS.'); - }) + it('should contains iconSizeBig', () => { + getElementFromFixture(fixture, moreMenuButton).click(); - it('should contains icon', () => { - getElementFromFixture(fixture, moreMenuButton).click(); + const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); + expect(menuItem.iconSizeBig).toBeTruthy(); + }); - expect(menuItem.icon).toBe('xdomea_file'); - }) + describe('for button', () => { + it.skip('should contains vorgangWithEingang', () => { + getElementFromFixture(fixture, moreMenuButton).click(); - it('should contains iconSizeBig', () => { - getElementFromFixture(fixture, moreMenuButton).click(); + const button: ProcessVorgangContainerComponent = getMockComponent( + fixture, + ProcessVorgangContainerComponent, + ); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); + expect(button.vorgangWithEingang).toBe(vorgangWithEingang); + }); + }); + }); + }); - expect(menuItem.iconSizeBig).toBeTruthy(); - }) + describe('processVorgang menu item', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.PROCESS_VORGANG, + ]); - describe('for button', () => { + beforeEach(() => { + component.buttonEnabled = true; + fixture.detectChanges(); + }); - it.skip('should contains vorgangWithEingang', () => { - getElementFromFixture(fixture, moreMenuButton).click(); + it('should be visible if link exists', () => { + component.vorgangWithEingang = vorgangWithEingang; + fixture.detectChanges(); + getElementFromFixture(fixture, moreMenuButton).click(); - const button: ProcessVorgangContainerComponent = getMockComponent(fixture, ProcessVorgangContainerComponent); + const element = getElementFromDomRoot(fixture, processVorgangMenuItem); - expect(button.vorgangWithEingang).toBe(vorgangWithEingang); - }) - }) - }) - }) + expect(element).toBeInTheDocument(); + }); - describe('processVorgang menu item', () => { + it('should NOT be visible if link is missing', () => { + component.vorgangWithEingang = createVorgangWithEingangResource(); + fixture.detectChanges(); + getElementFromFixture(fixture, moreMenuButton).click(); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.PROCESS_VORGANG]); + const element = getElementFromDomRoot(fixture, processVorgangMenuItem); - beforeEach(() => { - component.buttonEnabled = true; - fixture.detectChanges(); - }) + expect(element).not.toBeInTheDocument(); + }); - it('should be visible if link exists', () => { - component.vorgangWithEingang = vorgangWithEingang; - fixture.detectChanges(); - getElementFromFixture(fixture, moreMenuButton).click(); + describe('input property', () => { + beforeEach(() => { + component.vorgangWithEingang = vorgangWithEingang; + fixture.detectChanges(); + }); - const element = getElementFromDomRoot(fixture, processVorgangMenuItem); + it('should contains headline', () => { + getElementFromFixture(fixture, moreMenuButton).click(); - expect(element).toBeInTheDocument(); - }) + const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); - it('should NOT be visible if link is missing', () => { - component.vorgangWithEingang = createVorgangWithEingangResource(); - fixture.detectChanges(); - getElementFromFixture(fixture, moreMenuButton).click(); + expect(menuItem.headline).toBe('Vorgang automatisiert vorprüfen'); + }); - const element = getElementFromDomRoot(fixture, processVorgangMenuItem); + it('should contains text', () => { + getElementFromFixture(fixture, moreMenuButton).click(); - expect(element).not.toBeInTheDocument(); - }) + const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); - describe('input property', () => { + expect(menuItem.text).toBe( + 'Eine Vorprüfung wird durchgeführt. Das Ergebnis wird als Kommentar hinzugefügt.', + ); + }); - beforeEach(() => { - component.vorgangWithEingang = vorgangWithEingang; - fixture.detectChanges(); - }) + it('should contains icon', () => { + getElementFromFixture(fixture, moreMenuButton).click(); - it('should contains headline', () => { - getElementFromFixture(fixture, moreMenuButton).click(); + const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); + expect(menuItem.icon).toBe('vorgang_vorpruefen'); + }); - expect(menuItem.headline).toBe('Vorgang automatisiert vorprüfen'); - }) + it('should contains iconSizeBig', () => { + getElementFromFixture(fixture, moreMenuButton).click(); - it('should contains text', () => { - getElementFromFixture(fixture, moreMenuButton).click(); + const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); + expect(menuItem.iconSizeBig).toBeTruthy(); + }); - expect(menuItem.text).toBe('Eine Vorprüfung wird durchgeführt. Das Ergebnis wird als Kommentar hinzugefügt.'); - }) + describe('for button', () => { + it.skip('should contains vorgangWithEingang', () => { + getElementFromFixture(fixture, moreMenuButton).click(); - it('should contains icon', () => { - getElementFromFixture(fixture, moreMenuButton).click(); + const button: VorgangExportContainerComponent = getMockComponent( + fixture, + VorgangExportContainerComponent, + ); - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); - - expect(menuItem.icon).toBe('vorgang_vorpruefen'); - }) - - it('should contains iconSizeBig', () => { - getElementFromFixture(fixture, moreMenuButton).click(); - - const menuItem: MenuItemComponent = getMockComponent(fixture, MenuItemComponent); - - expect(menuItem.iconSizeBig).toBeTruthy(); - }) - - describe('for button', () => { - - it.skip('should contains vorgangWithEingang', () => { - getElementFromFixture(fixture, moreMenuButton).click(); - - const button: VorgangExportContainerComponent = getMockComponent(fixture, VorgangExportContainerComponent); - - expect(button.vorgangWithEingang).toBe(vorgangWithEingang); - }) - }) - }) - }) + expect(button.vorgangWithEingang).toBe(vorgangWithEingang); + }); + }); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.ts index c5e38ed632eb8bd25ddbc6fe7c1887a3b36932df..6d0da624ef8e8e10d9de5c0affd1605e783948d6 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-detail-more-menu.component.ts @@ -1,4 +1,13 @@ -import { ChangeDetectorRef, Component, Input, OnChanges, QueryList, SimpleChanges, ViewChild, ViewChildren } from '@angular/core'; +import { + ChangeDetectorRef, + Component, + Input, + OnChanges, + QueryList, + SimpleChanges, + ViewChild, + ViewChildren, +} from '@angular/core'; import { MatMenuTrigger } from '@angular/material/menu'; import { isNotUndefined } from '@alfa-client/tech-shared'; import { MenuItemComponent } from '@alfa-client/ui'; @@ -6,41 +15,40 @@ import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@alfa-cli import { has } from 'lodash-es'; @Component({ - selector: 'alfa-vorgang-detail-more-menu', - templateUrl: './vorgang-detail-more-menu.component.html', - styleUrls: ['./vorgang-detail-more-menu.component.scss'], + selector: 'alfa-vorgang-detail-more-menu', + templateUrl: './vorgang-detail-more-menu.component.html', + styleUrls: ['./vorgang-detail-more-menu.component.scss'], }) export class VorgangDetailMoreMenuComponent implements OnChanges { + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() vorgangWithEingang: VorgangWithEingangResource; + @ViewChild('menuTrigger') trigger: MatMenuTrigger; + @ViewChildren(MenuItemComponent) menuItems!: QueryList<MenuItemComponent>; - @ViewChild('menuTrigger') trigger: MatMenuTrigger; - @ViewChildren(MenuItemComponent) menuItems!: QueryList<MenuItemComponent>; + buttonEnabled: boolean = false; - buttonEnabled: boolean = false; + readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; - readonly vorgangWithEingangLinkRel = VorgangWithEingangLinkRel; + constructor(private changeDetectorRef: ChangeDetectorRef) {} - constructor(private changeDetectorRef: ChangeDetectorRef) { } + ngOnChanges(changes: SimpleChanges): void { + if (has(changes, 'vorgangWithEingang')) { + this.vorgangWithEingangChanged(); + } + } - ngOnChanges(changes: SimpleChanges): void { - if (has(changes, 'vorgangWithEingang')) { - this.vorgangWithEingangChanged(); - } - } + public vorgangWithEingangChanged(): void { + this.changeDetectorRef.detectChanges(); + this.buttonEnabled = this.isButtonEnabled(); + } - public vorgangWithEingangChanged(): void { - this.changeDetectorRef.detectChanges(); - this.buttonEnabled = this.isButtonEnabled(); - } + public isButtonEnabled(): boolean { + return this.menuItems?.length > 0; + } - public isButtonEnabled(): boolean { - return this.menuItems?.length > 0; - } - - public closeMenu(): void { - if(isNotUndefined(this.trigger)){ - this.trigger.closeMenu(); - } - } + public closeMenu(): void { + if (isNotUndefined(this.trigger)) { + this.trigger.closeMenu(); + } + } } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html index c81312c2fd3a4d388dab360b636b63772d2008a2..8af626e25c56a8500686ece7d085e7bee3a1f6f3 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.html @@ -1,6 +1,8 @@ -<ozgcloud-button-with-spinner dataTestId="export-vorgang" - [showSpinner]="(exportStateResource$ | async)?.loading" - (clickEmitter)="export()" - text="Herunterladen" - icon="save_alt"> -</ozgcloud-button-with-spinner> \ No newline at end of file +<ozgcloud-button-with-spinner + dataTestId="export-vorgang" + [showSpinner]="(exportStateResource$ | async)?.loading" + (clickEmitter)="export()" + text="Herunterladen" + icon="save_alt" +> +</ozgcloud-button-with-spinner> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts index b2e961a97ce58654df0ff7f9899e48845a6e552d..23b7002028757884d9700ccc7eca370207b1427a 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.spec.ts @@ -8,64 +8,61 @@ import { of } from 'rxjs'; import { VorgangExportContainerComponent } from './vorgang-export-container.component'; describe('VorgangExportContainerComponent', () => { - let component: VorgangExportContainerComponent; - let fixture: ComponentFixture<VorgangExportContainerComponent>; - - const vorgangExportStateResource: StateResource<boolean> = createStateResource(false); - const vorgangService = mock(VorgangService); - - const buttonWithSpinner: string = '[dataTestId="export-vorgang"]'; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangExportContainerComponent, - MockComponent(OzgcloudButtonWithSpinnerComponent), - ], - providers: [ - { - provide: VorgangService, - useValue: vorgangService - } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(VorgangExportContainerComponent); - component = fixture.componentInstance; - vorgangService.getVorgangExport.mockReturnValue(of(vorgangExportStateResource)); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should get export', () => { - component.ngOnInit(); - - expect(vorgangService.getVorgangExport).toHaveBeenCalled(); - }) - }) - - describe('isExportDone', () => { - - it('should closeMenu if export is done', () => { - jest.spyOn(component.closeMenu, 'emit'); - - component.isExportDone(createStateResource(true)); - - expect(component.closeMenu.emit).toHaveBeenCalled(); - }) - }) - - describe('export', () => { - - it('should call vorgangService.export', () => { - dispatchEventFromFixture(fixture, buttonWithSpinner, 'clickEmitter'); - - expect(vorgangService.export).toHaveBeenCalled(); - }) - }) + let component: VorgangExportContainerComponent; + let fixture: ComponentFixture<VorgangExportContainerComponent>; + + const vorgangExportStateResource: StateResource<boolean> = createStateResource(false); + const vorgangService = mock(VorgangService); + + const buttonWithSpinner: string = '[dataTestId="export-vorgang"]'; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangExportContainerComponent, + MockComponent(OzgcloudButtonWithSpinnerComponent), + ], + providers: [ + { + provide: VorgangService, + useValue: vorgangService, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(VorgangExportContainerComponent); + component = fixture.componentInstance; + vorgangService.getVorgangExport.mockReturnValue(of(vorgangExportStateResource)); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should get export', () => { + component.ngOnInit(); + + expect(vorgangService.getVorgangExport).toHaveBeenCalled(); + }); + }); + + describe('isExportDone', () => { + it('should closeMenu if export is done', () => { + jest.spyOn(component.closeMenu, 'emit'); + + component.isExportDone(createStateResource(true)); + + expect(component.closeMenu.emit).toHaveBeenCalled(); + }); + }); + + describe('export', () => { + it('should call vorgangService.export', () => { + dispatchEventFromFixture(fixture, buttonWithSpinner, 'clickEmitter'); + + expect(vorgangService.export).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts index 4d71e9133b7c6e67612ce483723faf8dca090f7f..76499065c513750bf5528c8d335471a1382c57f4 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-export-container/vorgang-export-container.component.ts @@ -4,29 +4,30 @@ import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang import { Observable, tap } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-export-container', - templateUrl: './vorgang-export-container.component.html', - styleUrls: ['./vorgang-export-container.component.scss'], + selector: 'alfa-vorgang-export-container', + templateUrl: './vorgang-export-container.component.html', + styleUrls: ['./vorgang-export-container.component.scss'], }) export class VorgangExportContainerComponent implements OnInit { + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() vorgangWithEingang: VorgangWithEingangResource; + @Output() public closeMenu: EventEmitter<void> = new EventEmitter(); - @Output() public closeMenu: EventEmitter<void> = new EventEmitter(); + public exportStateResource$: Observable<StateResource<boolean>>; - public exportStateResource$: Observable<StateResource<boolean>>; + constructor(private vorgangService: VorgangService) {} - constructor(private vorgangService: VorgangService) {} + ngOnInit(): void { + this.exportStateResource$ = this.vorgangService + .getVorgangExport() + .pipe(tap((vorgangExportStateResource) => this.isExportDone(vorgangExportStateResource))); + } - ngOnInit(): void { - this.exportStateResource$ = this.vorgangService.getVorgangExport().pipe(tap(vorgangExportStateResource => this.isExportDone(vorgangExportStateResource))); - } + isExportDone(vorgangExportStateResource: StateResource<boolean>): void { + if (vorgangExportStateResource.resource) this.closeMenu.emit(); + } - isExportDone(vorgangExportStateResource: StateResource<boolean>): void { - if(vorgangExportStateResource.resource) this.closeMenu.emit(); - } - - public export(): void { - this.vorgangService.export(this.vorgangWithEingang); - } + public export(): void { + this.vorgangService.export(this.vorgangWithEingang); + } } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.html index a72547075ec163aa5180c81c30bbf541d3a6a1da..4a457267cf2716bfcea39abc804a4c145cb3b79d 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.html @@ -1,6 +1,8 @@ -<ozgcloud-button-with-spinner dataTestId="process-vorgang" - [stateResource]="commandStateResource$ | async" - (clickEmitter)="processVorgang()" - text="Vorgang vorprüfen" - svgIcon="done"> -</ozgcloud-button-with-spinner> \ No newline at end of file +<ozgcloud-button-with-spinner + dataTestId="process-vorgang" + [stateResource]="commandStateResource$ | async" + (clickEmitter)="processVorgang()" + text="Vorgang vorprüfen" + svgIcon="done" +> +</ozgcloud-button-with-spinner> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.spec.ts index ed6269edcb9bece1cc47dfa3616d10f0b060f73c..99a7568d5a0e5150acac159114065b98308bbda0 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.spec.ts @@ -1,6 +1,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CommandResource } from '@alfa-client/command-shared'; -import { StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { dispatchEventFromFixture, getMockComponent, mock } from '@alfa-client/test-utils'; import { OzgcloudButtonWithSpinnerComponent } from '@alfa-client/ui'; import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @@ -11,78 +15,85 @@ import { of } from 'rxjs'; import { ProcessVorgangContainerComponent } from './vorgang-process-vorgang-container.component'; describe('ProcessVorgangContainerComponent', () => { - let component: ProcessVorgangContainerComponent; - let fixture: ComponentFixture<ProcessVorgangContainerComponent>; - - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const vorgangService = mock(VorgangService); - - const button: string = '[dataTestId="process-vorgang"]'; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - ProcessVorgangContainerComponent, - MockComponent(OzgcloudButtonWithSpinnerComponent) - ], - providers: [ - { - provide: VorgangService, - useValue: vorgangService - } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(ProcessVorgangContainerComponent); - component = fixture.componentInstance; - component.vorgangWithEingang = vorgangWithEingang; - vorgangService.processVorgang.mockReturnValue(of(commandStateResource)); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('handleCommand', () => { - - it('should closeMenu if processing is done', () => { - jest.spyOn(component.closeMenu, 'emit'); - - component.handleCommand(createStateResource(createCommandResource())); - - expect(component.closeMenu.emit).toHaveBeenCalled(); - }) - }) - - describe('processVorgang', () => { - - it('should call service processVorgang', () => { - dispatchEventFromFixture(fixture, button, 'clickEmitter'); - - expect(vorgangService.processVorgang).toHaveBeenCalledWith(vorgangWithEingang); - }) - }) - - describe('button component should be called with', () => { - - it('stateResource', () => { - const button: OzgcloudButtonWithSpinnerComponent = getMockComponent(fixture, OzgcloudButtonWithSpinnerComponent); - - expect(button.stateResource).toEqual(createEmptyStateResource()); - }) - - it('text', () => { - const button: OzgcloudButtonWithSpinnerComponent = getMockComponent(fixture, OzgcloudButtonWithSpinnerComponent); - - expect(button.text).toBe('Vorgang vorprüfen'); - }) - - it('icon', () => { - const button: OzgcloudButtonWithSpinnerComponent = getMockComponent(fixture, OzgcloudButtonWithSpinnerComponent); - - expect(button.svgIcon).toBe('done'); - }) - }) -}) \ No newline at end of file + let component: ProcessVorgangContainerComponent; + let fixture: ComponentFixture<ProcessVorgangContainerComponent>; + + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const vorgangService = mock(VorgangService); + + const button: string = '[dataTestId="process-vorgang"]'; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + ProcessVorgangContainerComponent, + MockComponent(OzgcloudButtonWithSpinnerComponent), + ], + providers: [ + { + provide: VorgangService, + useValue: vorgangService, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(ProcessVorgangContainerComponent); + component = fixture.componentInstance; + component.vorgangWithEingang = vorgangWithEingang; + vorgangService.processVorgang.mockReturnValue(of(commandStateResource)); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('handleCommand', () => { + it('should closeMenu if processing is done', () => { + jest.spyOn(component.closeMenu, 'emit'); + + component.handleCommand(createStateResource(createCommandResource())); + + expect(component.closeMenu.emit).toHaveBeenCalled(); + }); + }); + + describe('processVorgang', () => { + it('should call service processVorgang', () => { + dispatchEventFromFixture(fixture, button, 'clickEmitter'); + + expect(vorgangService.processVorgang).toHaveBeenCalledWith(vorgangWithEingang); + }); + }); + + describe('button component should be called with', () => { + it('stateResource', () => { + const button: OzgcloudButtonWithSpinnerComponent = getMockComponent( + fixture, + OzgcloudButtonWithSpinnerComponent, + ); + + expect(button.stateResource).toEqual(createEmptyStateResource()); + }); + + it('text', () => { + const button: OzgcloudButtonWithSpinnerComponent = getMockComponent( + fixture, + OzgcloudButtonWithSpinnerComponent, + ); + + expect(button.text).toBe('Vorgang vorprüfen'); + }); + + it('icon', () => { + const button: OzgcloudButtonWithSpinnerComponent = getMockComponent( + fixture, + OzgcloudButtonWithSpinnerComponent, + ); + + expect(button.svgIcon).toBe('done'); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.ts index 5f79616a527787399aec65653134c372b6515262..287cb46bbe357f3ceeb4cf135fb886204bc9341a 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-more-menu/vorgang-process-vorgang-container/vorgang-process-vorgang-container.component.ts @@ -5,27 +5,28 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; import { Observable, of, tap } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-process-vorgang-container', - templateUrl: './vorgang-process-vorgang-container.component.html', - styleUrls: ['./vorgang-process-vorgang-container.component.scss'], + selector: 'alfa-vorgang-process-vorgang-container', + templateUrl: './vorgang-process-vorgang-container.component.html', + styleUrls: ['./vorgang-process-vorgang-container.component.scss'], }) export class ProcessVorgangContainerComponent { + @Input() vorgangWithEingang: VorgangWithEingangResource; - @Input() vorgangWithEingang: VorgangWithEingangResource; + @Output() public closeMenu: EventEmitter<void> = new EventEmitter(); - @Output() public closeMenu: EventEmitter<void> = new EventEmitter(); + public commandStateResource$: Observable<StateResource<CommandResource>> = of( + createEmptyStateResource<CommandResource>(), + ); - public commandStateResource$: Observable<StateResource<CommandResource>> = of(createEmptyStateResource<CommandResource>()); + constructor(private vorgangService: VorgangService) {} - constructor(private vorgangService: VorgangService) { } + public processVorgang(): void { + this.commandStateResource$ = this.vorgangService + .processVorgang(this.vorgangWithEingang) + .pipe(tap((vorgangExportStateResource) => this.handleCommand(vorgangExportStateResource))); + } - public processVorgang(): void { - this.commandStateResource$ = this.vorgangService.processVorgang(this.vorgangWithEingang).pipe( - tap(vorgangExportStateResource => this.handleCommand(vorgangExportStateResource)), - ); - } - - handleCommand(vorgangExportStateResource: StateResource<CommandResource>): void { - if(isLoaded(vorgangExportStateResource)) this.closeMenu.emit(); - } -} \ No newline at end of file + handleCommand(vorgangExportStateResource: StateResource<CommandResource>): void { + if (isLoaded(vorgangExportStateResource)) this.closeMenu.emit(); + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html index b9e219cc88e5d683f64e9fcb1b21ce50aaa85142..73a496083b822f8f6debca5fc54711cd9066032b 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.html @@ -24,18 +24,26 @@ --> <ng-container *ngIf="vorgangStateResource$ | async as vorgangStateResource"> - - <ozgcloud-subnavigation class="mat-app-background"> - <alfa-vorgang-detail-back-button-container></alfa-vorgang-detail-back-button-container> - <alfa-vorgang-detail-action-buttons [vorgangWithEingang]="vorgangStateResource.resource"></alfa-vorgang-detail-action-buttons> - <alfa-vorgang-detail-more-menu [vorgangWithEingang]="vorgangStateResource.resource"></alfa-vorgang-detail-more-menu> - </ozgcloud-subnavigation> - - <div class="l-scroll-area--full"> - <alfa-vorgang-detail-area [vorgangStateResource]="vorgangStateResource"></alfa-vorgang-detail-area> - </div> - + <ozgcloud-subnavigation class="mat-app-background"> + <alfa-vorgang-detail-back-button-container></alfa-vorgang-detail-back-button-container> + <alfa-vorgang-detail-action-buttons + [vorgangWithEingang]="vorgangStateResource.resource" + ></alfa-vorgang-detail-action-buttons> + <alfa-vorgang-detail-more-menu + [vorgangWithEingang]="vorgangStateResource.resource" + ></alfa-vorgang-detail-more-menu> + </ozgcloud-subnavigation> + + <div class="l-scroll-area--full"> + <alfa-vorgang-detail-area + [vorgangStateResource]="vorgangStateResource" + ></alfa-vorgang-detail-area> + </div> </ng-container> -<ozgcloud-progress-bar [stateResource]="revokeCommandStateResource$ | async"></ozgcloud-progress-bar> -<ozgcloud-spinner-transparency [stateResource]="vorgangLoeschenCommandStateResource$ | async"></ozgcloud-spinner-transparency> \ No newline at end of file +<ozgcloud-progress-bar + [stateResource]="revokeCommandStateResource$ | async" +></ozgcloud-progress-bar> +<ozgcloud-spinner-transparency + [stateResource]="vorgangLoeschenCommandStateResource$ | async" +></ozgcloud-spinner-transparency> diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.scss b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.scss index 688daf0a90438b6fb05da882249e70d2811355df..7e09d057c1d9b65934edb37077bb8cc2e8cf4511 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.scss +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.scss @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .back-button { - margin-right: 6px; + margin-right: 6px; } diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.spec.ts index 264ffaefc7942403d1222072215ad1c3657f806d..c22913961fe75585bd7180358e4f78ae886c4c85 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.spec.ts @@ -27,7 +27,12 @@ import { LoeschAnforderungService } from '@alfa-client/loesch-anforderung-shared import { StateResource, createStateResource } from '@alfa-client/tech-shared'; import { getDebugElementFromFixtureByCss, mock } from '@alfa-client/test-utils'; import { SpinnerComponent, SpinnerTransparencyComponent } from '@alfa-client/ui'; -import { VorgangCommandService, VorgangService, VorgangWithEingang, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangCommandService, + VorgangService, + VorgangWithEingang, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { ProgressBarComponent } from 'libs/ui/src/lib/ui/progress-bar/progress-bar.component'; import { SubnavigationComponent } from 'libs/ui/src/lib/ui/subnavigation/subnavigation.component'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; @@ -40,100 +45,101 @@ import { VorgangDetailBackButtonContainerComponent } from './vorgang-detail-back import { VorgangDetailPageComponent } from './vorgang-detail-page.component'; describe('VorgangDetailPageComponent', () => { - let component: VorgangDetailPageComponent; - let fixture: ComponentFixture<VorgangDetailPageComponent>; - - const getVorgangWithEingangSubj: Subject<StateResource<VorgangWithEingang>> = new Subject(); - const vorgangService = { ...mock(VorgangService), getVorgangWithEingang: () => getVorgangWithEingangSubj }; - const vorgangCommandService = mock(VorgangCommandService); - const loeschAnforderungService = mock(LoeschAnforderungService); - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - const subnavigation: string = 'ozgcloud-subnavigation'; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangDetailPageComponent, - MatIcon, - MockComponent(ProgressBarComponent), - MockComponent(SubnavigationComponent), - MockComponent(VorgangDetailAreaComponent), - MockComponent(VorgangDetailActionButtonsComponent), - MockComponent(VorgangDetailFormularButtonsComponent), - MockComponent(VorgangDetailBackButtonContainerComponent), - MockComponent(SpinnerComponent), - MockComponent(SpinnerTransparencyComponent) - ], - providers: [ - { - provide: VorgangService, - useValue: vorgangService - }, - { - provide: VorgangCommandService, - useValue: vorgangCommandService - }, - { - provide: LoeschAnforderungService, - useValue: loeschAnforderungService - } - ] - }) - }); - - beforeEach(() => { - fixture = TestBed.createComponent(VorgangDetailPageComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should get vorgangWithEingang', () => { - vorgangService.getVorgangWithEingang = jest.fn(); - - component.ngOnInit(); - - expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); - }) - - it('should get getRevokeCommand', () => { - component.ngOnInit(); - - expect(vorgangCommandService.getRevokeCommand).toHaveBeenCalled(); - }) - - it('should get vorgangLoeschenCommand', () => { - component.ngOnInit(); - - expect(loeschAnforderungService.getEndgueltigLoeschenCommand).toHaveBeenCalled(); - }) - }) - - describe('subnavigation', () => { - - it('should be hidden', () => { - getVorgangWithEingangSubj.next(null); - fixture.detectChanges(); - - const subnavigationElement = getDebugElementFromFixtureByCss(fixture, subnavigation); - - expect(subnavigationElement).toBeNull(); - }) - - it('should be visible', () => { - getVorgangWithEingangSubj.next(createStateResource(vorgangWithEingang)); - fixture.detectChanges(); - - const subnavigationElement = getDebugElementFromFixtureByCss(fixture, subnavigation); - - expect(subnavigationElement).toBeDefined(); - }) - }) + let component: VorgangDetailPageComponent; + let fixture: ComponentFixture<VorgangDetailPageComponent>; + + const getVorgangWithEingangSubj: Subject<StateResource<VorgangWithEingang>> = new Subject(); + const vorgangService = { + ...mock(VorgangService), + getVorgangWithEingang: () => getVorgangWithEingangSubj, + }; + const vorgangCommandService = mock(VorgangCommandService); + const loeschAnforderungService = mock(LoeschAnforderungService); + + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + const subnavigation: string = 'ozgcloud-subnavigation'; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangDetailPageComponent, + MatIcon, + MockComponent(ProgressBarComponent), + MockComponent(SubnavigationComponent), + MockComponent(VorgangDetailAreaComponent), + MockComponent(VorgangDetailActionButtonsComponent), + MockComponent(VorgangDetailFormularButtonsComponent), + MockComponent(VorgangDetailBackButtonContainerComponent), + MockComponent(SpinnerComponent), + MockComponent(SpinnerTransparencyComponent), + ], + providers: [ + { + provide: VorgangService, + useValue: vorgangService, + }, + { + provide: VorgangCommandService, + useValue: vorgangCommandService, + }, + { + provide: LoeschAnforderungService, + useValue: loeschAnforderungService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangDetailPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should get vorgangWithEingang', () => { + vorgangService.getVorgangWithEingang = jest.fn(); + + component.ngOnInit(); + + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); + + it('should get getRevokeCommand', () => { + component.ngOnInit(); + + expect(vorgangCommandService.getRevokeCommand).toHaveBeenCalled(); + }); + + it('should get vorgangLoeschenCommand', () => { + component.ngOnInit(); + + expect(loeschAnforderungService.getEndgueltigLoeschenCommand).toHaveBeenCalled(); + }); + }); + + describe('subnavigation', () => { + it('should be hidden', () => { + getVorgangWithEingangSubj.next(null); + fixture.detectChanges(); + + const subnavigationElement = getDebugElementFromFixtureByCss(fixture, subnavigation); + + expect(subnavigationElement).toBeNull(); + }); + + it('should be visible', () => { + getVorgangWithEingangSubj.next(createStateResource(vorgangWithEingang)); + fixture.detectChanges(); + + const subnavigationElement = getDebugElementFromFixtureByCss(fixture, subnavigation); + + expect(subnavigationElement).toBeDefined(); + }); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.ts index e2983991d34c6e799a3c0d0cd8034a782513d6e6..8f00b12309fb7cfbf1cc4323f9d9f4a2aa2be2ab 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail-page/vorgang-detail-page.component.ts @@ -24,26 +24,34 @@ import { Component, OnInit } from '@angular/core'; import { LoeschAnforderungService } from '@alfa-client/loesch-anforderung-shared'; import { StateResource } from '@alfa-client/tech-shared'; -import { VorgangCommandService, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangCommandService, + VorgangService, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { CommandResource } from 'libs/command-shared/src/lib/command.model'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-detail-page', - templateUrl: './vorgang-detail-page.component.html', - styleUrls: ['./vorgang-detail-page.component.scss'] + selector: 'alfa-vorgang-detail-page', + templateUrl: './vorgang-detail-page.component.html', + styleUrls: ['./vorgang-detail-page.component.scss'], }) export class VorgangDetailPageComponent implements OnInit { + vorgangStateResource$: Observable<StateResource<VorgangWithEingangResource>>; + revokeCommandStateResource$: Observable<StateResource<CommandResource>>; + vorgangLoeschenCommandStateResource$: Observable<StateResource<CommandResource>>; - vorgangStateResource$: Observable<StateResource<VorgangWithEingangResource>>; - revokeCommandStateResource$: Observable<StateResource<CommandResource>>; - vorgangLoeschenCommandStateResource$: Observable<StateResource<CommandResource>>; + constructor( + private vorgangService: VorgangService, + private vorgangCommandService: VorgangCommandService, + private loeschAnforderungService: LoeschAnforderungService, + ) {} - constructor(private vorgangService: VorgangService, private vorgangCommandService: VorgangCommandService, private loeschAnforderungService: LoeschAnforderungService) { } - - ngOnInit(): void { - this.vorgangStateResource$ = this.vorgangService.getVorgangWithEingang(); - this.revokeCommandStateResource$ = this.vorgangCommandService.getRevokeCommand(); - this.vorgangLoeschenCommandStateResource$ = this.loeschAnforderungService.getEndgueltigLoeschenCommand(); - } -} \ No newline at end of file + ngOnInit(): void { + this.vorgangStateResource$ = this.vorgangService.getVorgangWithEingang(); + this.revokeCommandStateResource$ = this.vorgangCommandService.getRevokeCommand(); + this.vorgangLoeschenCommandStateResource$ = + this.loeschAnforderungService.getEndgueltigLoeschenCommand(); + } +} diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.spec.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.spec.ts index ec85e24b13d12525e6554c7bfdd39aae294e1d3e..aab4e7112b91c9d9348a17c0287f0fde35ce779b 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.spec.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { VorgangDetailModule } from './vorgang-detail.module'; describe('VorgangDetailModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [VorgangDetailModule] - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [VorgangDetailModule], + }).compileComponents(); + }); - it('should create', () => { - expect(VorgangDetailModule).toBeDefined(); - }); + it('should create', () => { + expect(VorgangDetailModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts index cc97bc6bf3b6089aa5169ae076d78e7568ea0373..f702107b14fb0f6a17b9bd7e37d9f796612d5abf 100644 --- a/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts +++ b/alfa-client/libs/vorgang-detail/src/lib/vorgang-detail.module.ts @@ -70,69 +70,69 @@ import { AktenzeichenEditDialogComponent } from './aktenzeichen-edit-dialog/akte import { AktenzeichenEditableComponent } from './aktenzeichen-editable/aktenzeichen-editable.component'; const routes: Routes = [ - { - path: '', - component: VorgangDetailPageComponent, - }, + { + path: '', + component: VorgangDetailPageComponent, + }, ]; @NgModule({ - imports: [ - CommonModule, - RouterModule.forChild(routes), - VorgangSharedModule, - UiModule, - TechSharedModule, - WiedervorlageModule, - BinaryFileModule, - ForwardingModule, - KommentarModule, - VorgangSharedUiModule, - UserProfileModule, - UserProfileSharedModule, - PostfachSharedModule, - PostfachModule, - HistorieModule, - LoeschAnforderungModule, - LoeschAnforderungSharedModule, - BescheidModule, - ], - declarations: [ - VorgangDetailPageComponent, - VorgangDetailAreaComponent, - VorgangDetailHeaderComponent, - VorgangDetailEingangHeaderComponent, - VorgangDetailFormDataTableComponent, - VorgangDetailActionButtonsComponent, - VorgangDetailFormularButtonsComponent, - AnnehmenButtonComponent, - BearbeitenButtonComponent, - VerwerfenButtonComponent, - ZurueckholenButtonComponent, - BescheidenButtonComponent, - AbschliessenButtonComponent, - ZurueckstellenButtonComponent, - WiedereroeffnenButtonComponent, - VorgangDetailAntragstellerComponent, - VorgangDetailBackButtonComponent, - VorgangDetailBackButtonContainerComponent, - VorgangDetailFormularDatenComponent, - VorgangDetailAntragDataComponent, - VorgangDetailMetaDataComponent, - VorgangDetailAttachmentListComponent, - VorgangDetailRepresentationListComponent, - VorgangDetailMoreMenuComponent, - VorgangExportContainerComponent, - ProcessVorgangContainerComponent, - AktenzeichenEditableComponent, - AktenzeichenEditDialogComponent, - ], - exports: [ - VorgangDetailAntragstellerComponent, - VorgangDetailAntragDataComponent, - VorgangDetailMetaDataComponent, - VorgangDetailAttachmentListComponent, - VorgangDetailRepresentationListComponent, - ], + imports: [ + CommonModule, + RouterModule.forChild(routes), + VorgangSharedModule, + UiModule, + TechSharedModule, + WiedervorlageModule, + BinaryFileModule, + ForwardingModule, + KommentarModule, + VorgangSharedUiModule, + UserProfileModule, + UserProfileSharedModule, + PostfachSharedModule, + PostfachModule, + HistorieModule, + LoeschAnforderungModule, + LoeschAnforderungSharedModule, + BescheidModule, + ], + declarations: [ + VorgangDetailPageComponent, + VorgangDetailAreaComponent, + VorgangDetailHeaderComponent, + VorgangDetailEingangHeaderComponent, + VorgangDetailFormDataTableComponent, + VorgangDetailActionButtonsComponent, + VorgangDetailFormularButtonsComponent, + AnnehmenButtonComponent, + BearbeitenButtonComponent, + VerwerfenButtonComponent, + ZurueckholenButtonComponent, + BescheidenButtonComponent, + AbschliessenButtonComponent, + ZurueckstellenButtonComponent, + WiedereroeffnenButtonComponent, + VorgangDetailAntragstellerComponent, + VorgangDetailBackButtonComponent, + VorgangDetailBackButtonContainerComponent, + VorgangDetailFormularDatenComponent, + VorgangDetailAntragDataComponent, + VorgangDetailMetaDataComponent, + VorgangDetailAttachmentListComponent, + VorgangDetailRepresentationListComponent, + VorgangDetailMoreMenuComponent, + VorgangExportContainerComponent, + ProcessVorgangContainerComponent, + AktenzeichenEditableComponent, + AktenzeichenEditDialogComponent, + ], + exports: [ + VorgangDetailAntragstellerComponent, + VorgangDetailAntragDataComponent, + VorgangDetailMetaDataComponent, + VorgangDetailAttachmentListComponent, + VorgangDetailRepresentationListComponent, + ], }) export class VorgangDetailModule {} diff --git a/alfa-client/libs/vorgang-detail/src/test-setup.ts b/alfa-client/libs/vorgang-detail/src/test-setup.ts index 5870fdabb6470fd0f6f3f63be3d4f6b8041b4dd2..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/vorgang-detail/src/test-setup.ts +++ b/alfa-client/libs/vorgang-detail/src/test-setup.ts @@ -26,17 +26,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/vorgang-detail/tsconfig.json b/alfa-client/libs/vorgang-detail/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/vorgang-detail/tsconfig.json +++ b/alfa-client/libs/vorgang-detail/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/vorgang-detail/tsconfig.lib.json b/alfa-client/libs/vorgang-detail/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/vorgang-detail/tsconfig.lib.json +++ b/alfa-client/libs/vorgang-detail/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/vorgang-detail/tsconfig.spec.json b/alfa-client/libs/vorgang-detail/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/vorgang-detail/tsconfig.spec.json +++ b/alfa-client/libs/vorgang-detail/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/vorgang-shared-ui/.eslintrc.json b/alfa-client/libs/vorgang-shared-ui/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/vorgang-shared-ui/.eslintrc.json +++ b/alfa-client/libs/vorgang-shared-ui/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/vorgang-shared-ui/jest.config.ts b/alfa-client/libs/vorgang-shared-ui/jest.config.ts index 7ebc66395a15cabd62a5124f3429e2a2f8d13203..ab027a40a3efeb46ff1756d3ced8b550dc0f0f96 100644 --- a/alfa-client/libs/vorgang-shared-ui/jest.config.ts +++ b/alfa-client/libs/vorgang-shared-ui/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'vorgang-shared-ui', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/vorgang-shared-ui', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'vorgang-shared-ui', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/vorgang-shared-ui', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/vorgang-shared-ui/project.json b/alfa-client/libs/vorgang-shared-ui/project.json index 58e0ad680004fc5b650d8c94bc5c32ccf9ce9953..03283d733388b6ced7a7962275f6053a97ed319a 100644 --- a/alfa-client/libs/vorgang-shared-ui/project.json +++ b/alfa-client/libs/vorgang-shared-ui/project.json @@ -1,29 +1,29 @@ { - "name": "vorgang-shared-ui", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/vorgang-shared-ui/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/vorgang-shared-ui/src/**/*.ts", - "libs/vorgang-shared-ui/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/vorgang-shared-ui"], - "options": { - "tsConfig": "libs/vorgang-shared-ui/tsconfig.spec.json", - "jestConfig": "libs/vorgang-shared-ui/jest.config.ts", - "passWithNoTests": true - } - } - }, - "tags": [] + "name": "vorgang-shared-ui", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/vorgang-shared-ui/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/vorgang-shared-ui/src/**/*.ts", + "libs/vorgang-shared-ui/src/**/*.html" + ] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/vorgang-shared-ui"], + "options": { + "tsConfig": "libs/vorgang-shared-ui/tsconfig.spec.json", + "jestConfig": "libs/vorgang-shared-ui/jest.config.ts", + "passWithNoTests": true + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/vorgang-shared-ui/src/index.ts b/alfa-client/libs/vorgang-shared-ui/src/index.ts index 9eaa20eb859543bc75409fdd7d44b2b3d15099c2..8184426d005669520ee4aecfb7c9089f7500fbda 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/index.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/index.ts @@ -29,4 +29,3 @@ export * from './lib/vorgang-shared-ui.module'; export * from './lib/vorgang-status-dot/vorgang-status-dot.component'; export * from './lib/vorgang-status-text/vorgang-status-text.component'; export * from './lib/vorgang-util'; - diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/aktenzeichen/aktenzeichen.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/aktenzeichen/aktenzeichen.component.spec.ts index f5baadf117e2ba01ed7ae99f4afd4a2064a94fc5..32bad0caeef5fb45a8b21978294d17a529f4d1fb 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/aktenzeichen/aktenzeichen.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/aktenzeichen/aktenzeichen.component.spec.ts @@ -29,50 +29,47 @@ import { VORGANG_KEIN_AKTENZEICHEN_ZUGEWIESEN } from '../vorgang-util'; import { AktenzeichenComponent } from './aktenzeichen.component'; describe('AktenzeichenComponent', () => { - let component: AktenzeichenComponent; - let fixture: ComponentFixture<AktenzeichenComponent>; + let component: AktenzeichenComponent; + let fixture: ComponentFixture<AktenzeichenComponent>; - const vorgang: VorgangResource = createVorgangResource(); + const vorgang: VorgangResource = createVorgangResource(); - const aktenzeichen: string = '[data-test-id="aktenzeichen"]'; + const aktenzeichen: string = '[data-test-id="aktenzeichen"]'; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - AktenzeichenComponent, - MatTooltipDirective - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [AktenzeichenComponent, MatTooltipDirective], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(AktenzeichenComponent); - component = fixture.componentInstance; - component.vorgang = vorgang; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(AktenzeichenComponent); + component = fixture.componentInstance; + component.vorgang = vorgang; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('aktenzeichen', () => { - it('should show default message', () => { - component.vorgang = { ...vorgang, aktenzeichen: null }; + describe('aktenzeichen', () => { + it('should show default message', () => { + component.vorgang = { ...vorgang, aktenzeichen: null }; - fixture.detectChanges(); - const aktenzeichenMessage: HTMLElement = fixture.nativeElement.querySelector(aktenzeichen); + fixture.detectChanges(); + const aktenzeichenMessage: HTMLElement = fixture.nativeElement.querySelector(aktenzeichen); - expect(aktenzeichenMessage.innerHTML).toBe(VORGANG_KEIN_AKTENZEICHEN_ZUGEWIESEN); - }) + expect(aktenzeichenMessage.innerHTML).toBe(VORGANG_KEIN_AKTENZEICHEN_ZUGEWIESEN); + }); - it('should show aktenzeichen', () => { - component.vorgang = vorgang; + it('should show aktenzeichen', () => { + component.vorgang = vorgang; - fixture.detectChanges(); - const aktenzeichenMessage: HTMLElement = fixture.nativeElement.querySelector(aktenzeichen); + fixture.detectChanges(); + const aktenzeichenMessage: HTMLElement = fixture.nativeElement.querySelector(aktenzeichen); - expect(aktenzeichenMessage.textContent).toBe(vorgang.aktenzeichen); - }) - }) + expect(aktenzeichenMessage.textContent).toBe(vorgang.aktenzeichen); + }); + }); }); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/aktenzeichen/aktenzeichen.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/aktenzeichen/aktenzeichen.component.ts index 3a41b60e5d75fbe1c153b008b8278c57ce673a0a..fa9f015be39ef504d0049973e5b77e81478ff01c 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/aktenzeichen/aktenzeichen.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/aktenzeichen/aktenzeichen.component.ts @@ -27,15 +27,14 @@ import { getAktenzeichenText } from '../vorgang-util'; import { EMPTY_STRING } from '@alfa-client/tech-shared'; @Component({ - selector: '[alfa-aktenzeichen]', - templateUrl: './aktenzeichen.component.html', - styleUrls: ['./aktenzeichen.component.scss'] + selector: '[alfa-aktenzeichen]', + templateUrl: './aktenzeichen.component.html', + styleUrls: ['./aktenzeichen.component.scss'], }) export class AktenzeichenComponent { + public aktenzeichen: string = EMPTY_STRING; - public aktenzeichen: string = EMPTY_STRING; - - @Input('vorgang') set vorgang(vorgang: Vorgang) { - this.aktenzeichen = getAktenzeichenText(vorgang); - } -} \ No newline at end of file + @Input('vorgang') set vorgang(vorgang: Vorgang) { + this.aktenzeichen = getAktenzeichenText(vorgang); + } +} diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.html index e272c50a994db733986571cf736c3602778213d0..c8de63c7fdfba1ac8c851fe64f6c50b40100ec20 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.html +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.html @@ -23,4 +23,7 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-vorgang-in-postfach-breadcrumb [vorgangStateResource]="vorgangStateResource$ | async" data-test-id="postfach-breadcrump"></alfa-vorgang-in-postfach-breadcrumb> \ No newline at end of file +<alfa-vorgang-in-postfach-breadcrumb + [vorgangStateResource]="vorgangStateResource$ | async" + data-test-id="postfach-breadcrump" +></alfa-vorgang-in-postfach-breadcrumb> diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.spec.ts index 427ec35483388aa0e595b636442311fc19e86fe1..369a11caaf327063d67485a3b978ab158b167ffa 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.spec.ts @@ -29,43 +29,41 @@ import { VorgangInPostfachBreadcrumbContainerComponent } from './vorgang-in-post import { VorgangInPostfachBreadcrumbComponent } from './vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component'; describe('VorgangInPostfachBreadcrumbContainerComponent', () => { - let component: VorgangInPostfachBreadcrumbContainerComponent; - let fixture: ComponentFixture<VorgangInPostfachBreadcrumbContainerComponent>; + let component: VorgangInPostfachBreadcrumbContainerComponent; + let fixture: ComponentFixture<VorgangInPostfachBreadcrumbContainerComponent>; - const vorgangService: Mock<VorgangService> = mock(VorgangService); + const vorgangService: Mock<VorgangService> = mock(VorgangService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangInPostfachBreadcrumbContainerComponent, - MockComponent(VorgangInPostfachBreadcrumbComponent) - ], - providers: [ - { - provide: VorgangService, - useValue: vorgangService - } - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangInPostfachBreadcrumbContainerComponent, + MockComponent(VorgangInPostfachBreadcrumbComponent), + ], + providers: [ + { + provide: VorgangService, + useValue: vorgangService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangInPostfachBreadcrumbContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangInPostfachBreadcrumbContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should call vorgang service', () => { + component.ngOnInit(); - it('should call vorgang service', () => { - component.ngOnInit(); - - expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); - }) - }) -}); \ No newline at end of file + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.ts index 0aacc6859de5652a6a9ae0a6f2a265b06305efe7..bde0eba9d92b2abdac24b3d3270d9d49e89475e2 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb-container.component.ts @@ -27,17 +27,16 @@ import { VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-in-postfach-breadcrumb-container', - templateUrl: './vorgang-in-postfach-breadcrumb-container.component.html', - styleUrls: ['./vorgang-in-postfach-breadcrumb-container.component.scss'] + selector: 'alfa-vorgang-in-postfach-breadcrumb-container', + templateUrl: './vorgang-in-postfach-breadcrumb-container.component.html', + styleUrls: ['./vorgang-in-postfach-breadcrumb-container.component.scss'], }) export class VorgangInPostfachBreadcrumbContainerComponent implements OnInit { + vorgangStateResource$: Observable<StateResource<VorgangWithEingangResource>>; - vorgangStateResource$: Observable<StateResource<VorgangWithEingangResource>>; + constructor(private vorgangService: VorgangService) {} - constructor(private vorgangService: VorgangService) { } - - ngOnInit(): void { - this.vorgangStateResource$ = this.vorgangService.getVorgangWithEingang(); - } + ngOnInit(): void { + this.vorgangStateResource$ = this.vorgangService.getVorgangWithEingang(); + } } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.html index 76fbd0fcdad0369b636ee22e55d8cab06cbbff52..b51eccd1277977c1a109c3a87718fd11a4091901 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.html +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.html @@ -24,7 +24,7 @@ --> <span *ngIf="vorgangStateResource.resource as vorgang"> - <a routerLink='/vorgang/{{ vorgang | toResourceUri }}' alfa-aktenzeichen [vorgang]="vorgang"></a> - <span>/</span> - <span>Nachrichten</span> -</span> \ No newline at end of file + <a routerLink="/vorgang/{{ vorgang | toResourceUri }}" alfa-aktenzeichen [vorgang]="vorgang"></a> + <span>/</span> + <span>Nachrichten</span> +</span> diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.scss b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.scss index e464165e3caa071427d0d983d92f8eeff45c0bf1..4df2ebcfa6f39b46618043b2ddb18650cea2f619 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.scss +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.scss @@ -24,23 +24,23 @@ @import 'variables'; :host { - display: block; - font-size: 18px; - padding: 16px 24px 4px 26px; + display: block; + font-size: 18px; + padding: 16px 24px 4px 26px; - ::ng-deep span { - margin: 0 4px; - } + ::ng-deep span { + margin: 0 4px; + } - a { - text-decoration: none; - outline: 0; - margin: -3px; - padding: 3px; + a { + text-decoration: none; + outline: 0; + margin: -3px; + padding: 3px; - &:focus { - border-radius: 12px; - background-color: rgba(#777, 0.16); - } - } + &:focus { + border-radius: 12px; + background-color: rgba(#777, 0.16); + } + } } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.spec.ts index b1d96ea6e647acad7839a63912203cd4285ce483..f5bdd3e8a9e65ad7adcd8f08453e914f3b06a6de 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.spec.ts @@ -30,31 +30,28 @@ import { AktenzeichenComponent } from '../../aktenzeichen/aktenzeichen.component import { VorgangInPostfachBreadcrumbComponent } from './vorgang-in-postfach-breadcrumb.component'; describe('VorgangInPostfachBreadcrumbComponent', () => { - let component: VorgangInPostfachBreadcrumbComponent; - let fixture: ComponentFixture<VorgangInPostfachBreadcrumbComponent>; + let component: VorgangInPostfachBreadcrumbComponent; + let fixture: ComponentFixture<VorgangInPostfachBreadcrumbComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangInPostfachBreadcrumbComponent, - ToResourceUriPipe, - MockComponent(AktenzeichenComponent) - ], - imports: [ - RouterTestingModule - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangInPostfachBreadcrumbComponent, + ToResourceUriPipe, + MockComponent(AktenzeichenComponent), + ], + imports: [RouterTestingModule], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangInPostfachBreadcrumbComponent); - component = fixture.componentInstance; - component.vorgangStateResource = createStateResource(createVorgangWithEingangResource()); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangInPostfachBreadcrumbComponent); + component = fixture.componentInstance; + component.vorgangStateResource = createStateResource(createVorgangWithEingangResource()); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.ts index f427162f2df359757594525bc9fbee00e342e753..0268ce2c96d75db36678288fd07fd6022af3b069 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-in-postfach-breadcrumb-container/vorgang-in-postfach-breadcrumb/vorgang-in-postfach-breadcrumb.component.ts @@ -26,11 +26,10 @@ import { StateResource } from '@alfa-client/tech-shared'; import { VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-vorgang-in-postfach-breadcrumb', - templateUrl: './vorgang-in-postfach-breadcrumb.component.html', - styleUrls: ['./vorgang-in-postfach-breadcrumb.component.scss'] + selector: 'alfa-vorgang-in-postfach-breadcrumb', + templateUrl: './vorgang-in-postfach-breadcrumb.component.html', + styleUrls: ['./vorgang-in-postfach-breadcrumb.component.scss'], }) export class VorgangInPostfachBreadcrumbComponent { - - @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; -} \ No newline at end of file + @Input() vorgangStateResource: StateResource<VorgangWithEingangResource>; +} diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/_vorgang-nummer.component.theme.scss b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/_vorgang-nummer.component.theme.scss index 7178db5371302f28f93ffa26899f2019bd041a18..00e4305df64ad8278be645380fe84dc15f92cd4b 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/_vorgang-nummer.component.theme.scss +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/_vorgang-nummer.component.theme.scss @@ -22,37 +22,37 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ alfa-vorgang-nummer { - div { - display: flex; - align-items: center; - margin: 0; - } + div { + display: flex; + align-items: center; + margin: 0; + } - mat-icon { - margin-right: 0.25rem; - height: 1.5rem; - min-height: 1.5rem; - width: 1.5rem; - min-width: 1.5rem; - } + mat-icon { + margin-right: 0.25rem; + height: 1.5rem; + min-height: 1.5rem; + width: 1.5rem; + min-width: 1.5rem; + } - span { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - } + span { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } - &.big { - div { - font-size: 16px; - font-weight: 300; - } - mat-icon { - margin-right: 0.5rem; - height: 1.875rem; - min-height: 1.875rem; - width: 1.875rem; - min-width: 1.875rem; - } - } + &.big { + div { + font-size: 16px; + font-weight: 300; + } + mat-icon { + margin-right: 0.5rem; + height: 1.875rem; + min-height: 1.875rem; + width: 1.875rem; + min-width: 1.875rem; + } + } } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.html index b1e65b74a0d734d1ac16cee30eed1151a5ff88cc..79e54f9224cda253b209638ff7a340ee55b2c555 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.html +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.html @@ -24,6 +24,6 @@ --> <div> - <mat-icon svgIcon="nr"></mat-icon> - <span [matTooltip]="vorgang.nummer" data-test-id="vorgang-nummer">{{ vorgang.nummer }}</span> + <mat-icon svgIcon="nr"></mat-icon> + <span [matTooltip]="vorgang.nummer" data-test-id="vorgang-nummer">{{ vorgang.nummer }}</span> </div> diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.spec.ts index 4937db082b54f7ea6ea8b495f4c965bf1fc39548..a132c63ec75151e104990c486307cdca393fca72 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.spec.ts @@ -32,41 +32,35 @@ import { createVorgangResource } from 'libs/vorgang-shared/test/vorgang'; import { VorgangNummerComponent } from './vorgang-nummer.component'; describe('VorgangNummerComponent', () => { - let component: VorgangNummerComponent; - let fixture: ComponentFixture<VorgangNummerComponent>; + let component: VorgangNummerComponent; + let fixture: ComponentFixture<VorgangNummerComponent>; - const vorgang: VorgangResource = createVorgangResource(); - const vorgangnummer: string = getDataTestIdOf('vorgang-nummer'); + const vorgang: VorgangResource = createVorgangResource(); + const vorgangnummer: string = getDataTestIdOf('vorgang-nummer'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MatIcon, - MatTooltipDirective, - VorgangNummerComponent - ], - imports: [ - MatIconTestingModule - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [MatIcon, MatTooltipDirective, VorgangNummerComponent], + imports: [MatIconTestingModule], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangNummerComponent); - component = fixture.componentInstance; - component.vorgang = vorgang; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangNummerComponent); + component = fixture.componentInstance; + component.vorgang = vorgang; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('vorgangnummer', () => { - it('should show vorgang.nummer', () => { - const text: HTMLElement = getElementFromFixture(fixture, vorgangnummer); + describe('vorgangnummer', () => { + it('should show vorgang.nummer', () => { + const text: HTMLElement = getElementFromFixture(fixture, vorgangnummer); - expect(text.textContent).toBe(vorgang.nummer); - }); - }); + expect(text.textContent).toBe(vorgang.nummer); + }); + }); }); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.ts index a82cbe397be674aad3a3641e5b3a224dd7513e4a..610e020a9d73ba64a29ef19537ecba26a6c0e3dc 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-nummer/vorgang-nummer.component.ts @@ -26,10 +26,8 @@ import { Vorgang } from '@alfa-client/vorgang-shared'; @Component({ selector: 'alfa-vorgang-nummer', - templateUrl: './vorgang-nummer.component.html' + templateUrl: './vorgang-nummer.component.html', }) export class VorgangNummerComponent { - - @Input() vorgang: Vorgang; - + @Input() vorgang: Vorgang; } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/_vorgang-search-container.theme.scss b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/_vorgang-search-container.theme.scss index 3c0e07d8c7619986f99c7ec3bb93e656a10e640c..f50729efdd4e5759424fba235265e25b10b0a0d5 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/_vorgang-search-container.theme.scss +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/_vorgang-search-container.theme.scss @@ -25,40 +25,39 @@ @use '@angular/material' as mat; alfa-vorgang-search-container { - .search-field { - box-shadow: 0 0 0 1px rgba(#000, 0.08); - background-color: $background; - - - &:hover, - &:focus-within { - box-shadow: 0 1px 4px 0 rgba(#000, 0.4); - background-color: #fff; - } - } - - input::placeholder { - color: rgba(#000, 0.2); - } + .search-field { + box-shadow: 0 0 0 1px rgba(#000, 0.08); + background-color: $background; + + &:hover, + &:focus-within { + box-shadow: 0 1px 4px 0 rgba(#000, 0.4); + background-color: #fff; + } + } + + input::placeholder { + color: rgba(#000, 0.2); + } } body.dark alfa-vorgang-search-container { - .search-field { - background-color: $dark-background; - } + .search-field { + background-color: $dark-background; + } - input::placeholder { - color: rgba(#fff, 0.2); - } + input::placeholder { + color: rgba(#fff, 0.2); + } } @mixin search-container($theme) { - $color-config: mat.get-color-config($theme); - $primary: map.get($color-config, 'primary'); - - alfa-vorgang-search-container { - .search-icon { - color: mat.get-color-from-palette($primary); - } - } + $color-config: mat.get-color-config($theme); + $primary: map.get($color-config, 'primary'); + + alfa-vorgang-search-container { + .search-icon { + color: mat.get-color-from-palette($primary); + } + } } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.html index c6c46f18ecdcee40d34ed732c0bfe06eb22399a5..699ef1145ac32af29bd11b5597034f1a30bdc0f2 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.html +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.html @@ -24,10 +24,15 @@ --> <ng-container *ngIf="apiRoot$ | async as apiRootStateResource"> - - <alfa-vorgang-search *ngIf="(apiRootStateResource.resource | hasLink: apiRootLinkRel.SEARCH_ALLE) || (apiRootStateResource.resource | hasLink: apiRootLinkRel.SEARCH_MEINE)" data-test-id="vorgang-search" - [vorgangSearchPreviewList]="vorgangSearchPreviewList$ | async" [searchString]="searchString$ | async" - (clearVorgangSearchPreviewList)="clearVorgangSearchPreviewList()"> - </alfa-vorgang-search> - -</ng-container> \ No newline at end of file + <alfa-vorgang-search + *ngIf=" + (apiRootStateResource.resource | hasLink: apiRootLinkRel.SEARCH_ALLE) || + (apiRootStateResource.resource | hasLink: apiRootLinkRel.SEARCH_MEINE) + " + data-test-id="vorgang-search" + [vorgangSearchPreviewList]="vorgangSearchPreviewList$ | async" + [searchString]="searchString$ | async" + (clearVorgangSearchPreviewList)="clearVorgangSearchPreviewList()" + > + </alfa-vorgang-search> +</ng-container> diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.spec.ts index 67b9121d20bf7ff8baf597b32d853fe35d8597ec..a59df3549b6041ed34fceb1de24b75de5c4f1085 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.spec.ts @@ -34,96 +34,97 @@ import { VorgangSearchContainerComponent } from './vorgang-search-container.comp import { VorgangSearchComponent } from './vorgang-search/vorgang-search.component'; describe('VorgangSearchContainerComponent', () => { - let component: VorgangSearchContainerComponent; - let fixture: ComponentFixture<VorgangSearchContainerComponent>; - - const apiRootFacade = mock(ApiRootFacade); - const vorgangListService = mock(VorgangListService); - - const vorgangSearch: string = getDataTestIdOf('vorgang-search'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangSearchContainerComponent, - HasLinkPipe, - MockComponent(VorgangSearchComponent) - ], - providers: [ - { - provide: ApiRootFacade, - useValue: apiRootFacade - }, - { - provide: VorgangListService, - useValue: vorgangListService - } - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(VorgangSearchContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call apiRootFacade to get apiRoot', () => { - component.ngOnInit(); - - expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); - }) - - it('should call vorgangListService to get searchPreviewList', () => { - component.ngOnInit(); - - expect(vorgangListService.getSearchPreviewList).toHaveBeenCalled(); - }) - - it('should call vorgangListService to get searchString', () => { - component.ngOnInit(); - - expect(vorgangListService.getSearchString).toHaveBeenCalled(); - }) - }) - - describe('vorgang-search', () => { - - it('should hide on no link exists', () => { - component.apiRoot$ = of(createStateResource(createApiRootResource())); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, vorgangSearch); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - - it.each([ApiRootLinkRel.SEARCH_ALLE, ApiRootLinkRel.SEARCH_MEINE]) - ('should show on link "%s"', (linkRel: string) => { - component.apiRoot$ = of(createStateResource(createApiRootResource([linkRel]))); - fixture.detectChanges(); - - const element = getElementFromFixture(fixture, vorgangSearch); - - expect(element).toBeInstanceOf(HTMLElement); - }); - }) - - describe('clear vorgangSearchPreviewList event', () => { - - it('should call service clearSearchPreviewList', () => { - component.apiRoot$ = of(createStateResource(createApiRootResource([ApiRootLinkRel.SEARCH_ALLE]))); - fixture.detectChanges(); - - dispatchEventFromFixture(fixture, vorgangSearch, 'clearVorgangSearchPreviewList'); - - expect(vorgangListService.clearSearchPreviewList).toHaveBeenCalled(); - }) - }) -}); \ No newline at end of file + let component: VorgangSearchContainerComponent; + let fixture: ComponentFixture<VorgangSearchContainerComponent>; + + const apiRootFacade = mock(ApiRootFacade); + const vorgangListService = mock(VorgangListService); + + const vorgangSearch: string = getDataTestIdOf('vorgang-search'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangSearchContainerComponent, + HasLinkPipe, + MockComponent(VorgangSearchComponent), + ], + providers: [ + { + provide: ApiRootFacade, + useValue: apiRootFacade, + }, + { + provide: VorgangListService, + useValue: vorgangListService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangSearchContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call apiRootFacade to get apiRoot', () => { + component.ngOnInit(); + + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }); + + it('should call vorgangListService to get searchPreviewList', () => { + component.ngOnInit(); + + expect(vorgangListService.getSearchPreviewList).toHaveBeenCalled(); + }); + + it('should call vorgangListService to get searchString', () => { + component.ngOnInit(); + + expect(vorgangListService.getSearchString).toHaveBeenCalled(); + }); + }); + + describe('vorgang-search', () => { + it('should hide on no link exists', () => { + component.apiRoot$ = of(createStateResource(createApiRootResource())); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, vorgangSearch); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + + it.each([ApiRootLinkRel.SEARCH_ALLE, ApiRootLinkRel.SEARCH_MEINE])( + 'should show on link "%s"', + (linkRel: string) => { + component.apiRoot$ = of(createStateResource(createApiRootResource([linkRel]))); + fixture.detectChanges(); + + const element = getElementFromFixture(fixture, vorgangSearch); + + expect(element).toBeInstanceOf(HTMLElement); + }, + ); + }); + + describe('clear vorgangSearchPreviewList event', () => { + it('should call service clearSearchPreviewList', () => { + component.apiRoot$ = of( + createStateResource(createApiRootResource([ApiRootLinkRel.SEARCH_ALLE])), + ); + fixture.detectChanges(); + + dispatchEventFromFixture(fixture, vorgangSearch, 'clearVorgangSearchPreviewList'); + + expect(vorgangListService.clearSearchPreviewList).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.ts index 1700672e3de1a5be6745b4a58e7917efa3314f5f..5fda995381b0d70a58e897190b0aa70164622241 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search-container.component.ts @@ -28,28 +28,34 @@ import { VorgangListResource, VorgangListService } from '@alfa-client/vorgang-sh import { Observable, of } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-search-container', - templateUrl: './vorgang-search-container.component.html', - styleUrls: ['./vorgang-search-container.component.scss'] + selector: 'alfa-vorgang-search-container', + templateUrl: './vorgang-search-container.component.html', + styleUrls: ['./vorgang-search-container.component.scss'], }) export class VorgangSearchContainerComponent implements OnInit { + public apiRoot$: Observable<StateResource<ApiRootResource>> = of( + createEmptyStateResource<ApiRootResource>(), + ); + public vorgangSearchPreviewList$: Observable<StateResource<VorgangListResource>> = of( + createEmptyStateResource<VorgangListResource>(), + ); + public searchString$: Observable<string>; - public apiRoot$: Observable<StateResource<ApiRootResource>> = of(createEmptyStateResource<ApiRootResource>()); - public vorgangSearchPreviewList$: Observable<StateResource<VorgangListResource>> = of(createEmptyStateResource<VorgangListResource>()); - public searchString$: Observable<string>; + readonly apiRootLinkRel = ApiRootLinkRel; - readonly apiRootLinkRel = ApiRootLinkRel; + constructor( + private apiRootFacade: ApiRootFacade, + private vorgangListService: VorgangListService, + ) {} - constructor(private apiRootFacade: ApiRootFacade, private vorgangListService: VorgangListService) { } + ngOnInit(): void { + this.apiRoot$ = this.apiRootFacade.getApiRoot(); + this.vorgangSearchPreviewList$ = this.vorgangListService.getSearchPreviewList(); + this.searchString$ = this.vorgangListService.getSearchString(); + } - ngOnInit(): void { - this.apiRoot$ = this.apiRootFacade.getApiRoot(); - this.vorgangSearchPreviewList$ = this.vorgangListService.getSearchPreviewList(); - this.searchString$ = this.vorgangListService.getSearchString(); - } - - clearVorgangSearchPreviewList(): void { - this.vorgangListService.clearSearchPreviewList(); - this.vorgangListService.clearSearchString(); - } -} \ No newline at end of file + clearVorgangSearchPreviewList(): void { + this.vorgangListService.clearSearchPreviewList(); + this.vorgangListService.clearSearchString(); + } +} diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.html index a3550647c7bd0fa071ca29f7ea3794a53a171992..46477601508330b0571dd313f2308126ca9397da 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.html +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.html @@ -24,18 +24,20 @@ --> <div class="line name-date"> - <span class="name" data-test-id="preview-list-item-vorgang-name">{{vorgang.name}}</span> - <div class="date"> - <mat-icon svgIcon="incoming"></mat-icon> - <span data-test-id="preview-list-item-created-at">{{ vorgang.createdAt | formatToPrettyDate }}</span> - </div> + <span class="name" data-test-id="preview-list-item-vorgang-name">{{ vorgang.name }}</span> + <div class="date"> + <mat-icon svgIcon="incoming"></mat-icon> + <span data-test-id="preview-list-item-created-at">{{ + vorgang.createdAt | formatToPrettyDate + }}</span> + </div> </div> <div class="line full-width"> - <alfa-vorgang-nummer [vorgang]="vorgang"></alfa-vorgang-nummer> + <alfa-vorgang-nummer [vorgang]="vorgang"></alfa-vorgang-nummer> </div> <div class="line full-width"> - <div class="aktenzeichen" data-test-id="preview-list-item-vorgang-aktenzeichen"> - <mat-icon svgIcon="az"></mat-icon> - <span alfa-aktenzeichen [vorgang]="vorgang"></span> - </div> -</div> \ No newline at end of file + <div class="aktenzeichen" data-test-id="preview-list-item-vorgang-aktenzeichen"> + <mat-icon svgIcon="az"></mat-icon> + <span alfa-aktenzeichen [vorgang]="vorgang"></span> + </div> +</div> diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.scss b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.scss index 17b215dd7f25b21e3f1854982d2f81dd2414e0d4..b461af4a33b65b4610c67624aba8e6684a5c83d7 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.scss +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.scss @@ -22,47 +22,47 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ a { - color: inherit; - text-decoration: none; + color: inherit; + text-decoration: none; } .line { - display: grid; - grid-auto-flow: column; - grid-auto-columns: 1fr; - gap: 0.5rem; - align-items: center; - padding: 0.188rem 0; - white-space: normal; + display: grid; + grid-auto-flow: column; + grid-auto-columns: 1fr; + gap: 0.5rem; + align-items: center; + padding: 0.188rem 0; + white-space: normal; - &.full-width > * { - width: 100%; - } - &.name-date { - grid-template-columns: 1fr auto; - &.date { - white-space: nowrap; - overflow: hidden; - } - } + &.full-width > * { + width: 100%; + } + &.name-date { + grid-template-columns: 1fr auto; + &.date { + white-space: nowrap; + overflow: hidden; + } + } - alfa-vorgang-nummer span { - white-space: normal; - overflow: auto; - text-overflow: unset; - word-break: break-all; - } + alfa-vorgang-nummer span { + white-space: normal; + overflow: auto; + text-overflow: unset; + word-break: break-all; + } } .aktenzeichen { - display: flex; - align-items: center; - span { - word-break: break-all; - } + display: flex; + align-items: center; + span { + word-break: break-all; + } } .name { - font-weight: bold; - white-space: normal; -} \ No newline at end of file + font-weight: bold; + white-space: normal; +} diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.spec.ts index bf0246912ffacee3c90613b65bd352a83680ab4a..16b8d6cca3041e8deebdd4957b5b5416e566b1b7 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.spec.ts @@ -36,32 +36,30 @@ import { VorgangSearchAutocompleteOptionsContentComponent } from './vorgang-sear registerLocaleData(localeDe); describe('VorgangSearchAutocompleteOptionsComponent', () => { - let component: VorgangSearchAutocompleteOptionsContentComponent; - let fixture: ComponentFixture<VorgangSearchAutocompleteOptionsContentComponent>; + let component: VorgangSearchAutocompleteOptionsContentComponent; + let fixture: ComponentFixture<VorgangSearchAutocompleteOptionsContentComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangSearchAutocompleteOptionsContentComponent, - FormatToPrettyDatePipe, - MatIcon, - MockComponent(AktenzeichenComponent), - MockComponent(VorgangNummerComponent), - ], - imports: [ - MatIconTestingModule - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangSearchAutocompleteOptionsContentComponent, + FormatToPrettyDatePipe, + MatIcon, + MockComponent(AktenzeichenComponent), + MockComponent(VorgangNummerComponent), + ], + imports: [MatIconTestingModule], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangSearchAutocompleteOptionsContentComponent); - component = fixture.componentInstance; - component.vorgang = createVorgangResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangSearchAutocompleteOptionsContentComponent); + component = fixture.componentInstance; + component.vorgang = createVorgangResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.ts index 3531f73eaa15b9e645e3889eb84e9fca0b3125df..27ecdc1a64a9efb8c2fa0c8b3b9ec0942ece2432 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-autocomplete-options-content/vorgang-search-autocomplete-options-content.component.ts @@ -25,11 +25,10 @@ import { Component, Input } from '@angular/core'; import { VorgangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-vorgang-search-autocomplete-options-content', - templateUrl: './vorgang-search-autocomplete-options-content.component.html', - styleUrls: ['./vorgang-search-autocomplete-options-content.component.scss'] + selector: 'alfa-vorgang-search-autocomplete-options-content', + templateUrl: './vorgang-search-autocomplete-options-content.component.html', + styleUrls: ['./vorgang-search-autocomplete-options-content.component.scss'], }) export class VorgangSearchAutocompleteOptionsContentComponent { - - @Input() vorgang: VorgangResource; -} \ No newline at end of file + @Input() vorgang: VorgangResource; +} diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.html index 7b67eb7286f6aa82fb4e8eae3ce59de30505790b..abd54b224325031f152a658b0e9d3d70f78d34ca 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.html +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.html @@ -23,10 +23,13 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<button data-test-id="clear-button" - (click)="clear.emit()" - class="clear-button" - type="button" - mat-icon-button aria-label="Suchfeld leeren"> - <mat-icon>close</mat-icon> -</button> \ No newline at end of file +<button + data-test-id="clear-button" + (click)="clear.emit()" + class="clear-button" + type="button" + mat-icon-button + aria-label="Suchfeld leeren" +> + <mat-icon>close</mat-icon> +</button> diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.scss b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.scss index 0f2687373a1bb15a6038de0461a45874a1e01da7..72c748db297482a7260239598dfe5fe24779251b 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.scss +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.scss @@ -22,10 +22,10 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .clear-button { - position: absolute; - right: 0; + position: absolute; + right: 0; - .mat-icon { - opacity: 0.4; - } + .mat-icon { + opacity: 0.4; + } } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.spec.ts index 64fa00dba149a147457a02bbe6b97f3494b5075b..372d6c93ad5f6c8a7ce8f48969f5cad3f864550d 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.spec.ts @@ -27,34 +27,30 @@ import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { VorgangSearchClearButtonComponent } from './vorgang-search-clear-button.component'; describe('VorgangSearchClearButtonComponent', () => { - let component: VorgangSearchClearButtonComponent; - let fixture: ComponentFixture<VorgangSearchClearButtonComponent>; + let component: VorgangSearchClearButtonComponent; + let fixture: ComponentFixture<VorgangSearchClearButtonComponent>; - const clearButton: string = getDataTestIdOf('clear-button'); + const clearButton: string = getDataTestIdOf('clear-button'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangSearchClearButtonComponent, - MatIcon - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VorgangSearchClearButtonComponent, MatIcon], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangSearchClearButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangSearchClearButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('clear button should shown', () => { - const button = fixture.nativeElement.querySelector(clearButton); + it('clear button should shown', () => { + const button = fixture.nativeElement.querySelector(clearButton); - expect(button).toBeInstanceOf(HTMLElement); - }) -}); \ No newline at end of file + expect(button).toBeInstanceOf(HTMLElement); + }); +}); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.ts index 262e7d3abf91bd1a64d4b3d5948d835e3fbac6a7..ce31aeb2acc9b66e8e8e7fbb7303b564b0afe4d9 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search-clear-button/vorgang-search-clear-button.component.ts @@ -24,11 +24,10 @@ import { Component, EventEmitter, Output } from '@angular/core'; @Component({ - selector: 'alfa-vorgang-search-clear-button', - templateUrl: './vorgang-search-clear-button.component.html', - styleUrls: ['./vorgang-search-clear-button.component.scss'] + selector: 'alfa-vorgang-search-clear-button', + templateUrl: './vorgang-search-clear-button.component.html', + styleUrls: ['./vorgang-search-clear-button.component.scss'], }) export class VorgangSearchClearButtonComponent { - - @Output() clear: EventEmitter<void> = new EventEmitter(); -} \ No newline at end of file + @Output() clear: EventEmitter<void> = new EventEmitter(); +} diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.html index 5b5c0601667a29b016e28b77971ae20227b0cb31..f1ac25eb71af847bdcb522fe3f231474f1341c78 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.html +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.html @@ -23,44 +23,71 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<form (ngSubmit)="submit()" [formGroup]="formService.form" - [class.search-field--open]="searchAutoComplete.isOpen" class="search-field" - data-test-id="search-form"> - <button - #searchSubmitButton - type="submit" - data-test-id="search-button" - mat-icon-button aria-label="Vorgang suchen"> - <mat-icon matPrefix class="search-icon">search</mat-icon> - </button> - <mat-form-field floatLabel="never" subscriptSizing="dynamic"> - <input matInput data-test-id="search-input" - #searchInput - placeholder="Vorgang suchen" - aria-label="Vorgang suchen" - type="text" - maxlength="50" - [matAutocomplete]="searchAutoComplete" - [formControlName]="formService.SEARCH_FIELD" - name="searchString" - (focusout)="focusOut($event)" - (focusin)="focusIn()"/> +<form + (ngSubmit)="submit()" + [formGroup]="formService.form" + [class.search-field--open]="searchAutoComplete.isOpen" + class="search-field" + data-test-id="search-form" +> + <button + #searchSubmitButton + type="submit" + data-test-id="search-button" + mat-icon-button + aria-label="Vorgang suchen" + > + <mat-icon matPrefix class="search-icon">search</mat-icon> + </button> + <mat-form-field floatLabel="never" subscriptSizing="dynamic"> + <input + matInput + data-test-id="search-input" + #searchInput + placeholder="Vorgang suchen" + aria-label="Vorgang suchen" + type="text" + maxlength="50" + [matAutocomplete]="searchAutoComplete" + [formControlName]="formService.SEARCH_FIELD" + name="searchString" + (focusout)="focusOut($event)" + (focusin)="focusIn()" + /> - <mat-autocomplete #searchAutoComplete="matAutocomplete" class="vorgang-search" (optionSelected)="formService.submitByPreviewList($event.option.value, searchString)"> - <ozgcloud-spinner [stateResource]="vorgangSearchPreviewList" [class.autocomplete-spinner]="vorgangSearchPreviewList.loading"></ozgcloud-spinner> + <mat-autocomplete + #searchAutoComplete="matAutocomplete" + class="vorgang-search" + (optionSelected)="formService.submitByPreviewList($event.option.value, searchString)" + > + <ozgcloud-spinner + [stateResource]="vorgangSearchPreviewList" + [class.autocomplete-spinner]="vorgangSearchPreviewList.loading" + ></ozgcloud-spinner> - <ng-container *ngIf="vorgangSearchPreviewList.resource" data-test-id="search-preview-list"> - <mat-option *ngFor="let vorgang of (vorgangSearchPreviewList.resource | toEmbeddedResources: vorgangListLinkRel.VORGANG_HEADER_LIST)" [value]="vorgang"> - <ng-container *ngIf="vorgang | hasLink: vorgangHeaderLinkRel.VORGANG_WITH_EINGANG"> - <alfa-vorgang-search-autocomplete-options-content [vorgang]="vorgang" [attr.data-test-id]="'search-preview-list-item-' + vorgang.name | convertForDataTest"> - </alfa-vorgang-search-autocomplete-options-content> - </ng-container> - </mat-option> - </ng-container> - </mat-autocomplete> + <ng-container *ngIf="vorgangSearchPreviewList.resource" data-test-id="search-preview-list"> + <mat-option + *ngFor=" + let vorgang of vorgangSearchPreviewList.resource + | toEmbeddedResources: vorgangListLinkRel.VORGANG_HEADER_LIST + " + [value]="vorgang" + > + <ng-container *ngIf="vorgang | hasLink: vorgangHeaderLinkRel.VORGANG_WITH_EINGANG"> + <alfa-vorgang-search-autocomplete-options-content + [vorgang]="vorgang" + [attr.data-test-id]="'search-preview-list-item-' + vorgang.name | convertForDataTest" + > + </alfa-vorgang-search-autocomplete-options-content> + </ng-container> + </mat-option> + </ng-container> + </mat-autocomplete> + </mat-form-field> - </mat-form-field> - - <alfa-vorgang-search-clear-button *ngIf="formService.hasSearchString" (clear)="handleSearchClearButton();" data-test-id="vorgang-search-clear-button"></alfa-vorgang-search-clear-button> - -</form> \ No newline at end of file + <alfa-vorgang-search-clear-button + *ngIf="formService.hasSearchString" + (clear)="handleSearchClearButton()" + data-test-id="vorgang-search-clear-button" + ></alfa-vorgang-search-clear-button> +</form> diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.scss b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.scss index 074edac131a01f41476756748682caed62f313c4..006026859a6c1c9552ccbb9928f909d9d447078d 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.scss +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.scss @@ -24,41 +24,41 @@ @import 'variables'; mat-form-field { - flex-grow: 1; + flex-grow: 1; } input { - border: 0; - background-color: transparent; - outline: 0; - font-size: 18px !important; - color: inherit; - min-width: 0; // Firefox workaround for close icon - width: calc(100% - 40px); + border: 0; + background-color: transparent; + outline: 0; + font-size: 18px !important; + color: inherit; + min-width: 0; // Firefox workaround for close icon + width: calc(100% - 40px); - &::placeholder { - color: rgba(#000, 0.2); - } + &::placeholder { + color: rgba(#000, 0.2); + } } .search-field { - border-radius: 20px; - width: 100%; - max-width: 600px; - display: flex; - position: relative; + border-radius: 20px; + width: 100%; + max-width: 600px; + display: flex; + position: relative; - &--open { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } + &--open { + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } } .autocomplete-spinner { - position: absolute; - width: 100%; - height: 100%; - background-color: #ffffffaa; - z-index: 1; - transition: background-color ease-in-out 200ms; + position: absolute; + width: 100%; + height: 100%; + background-color: #ffffffaa; + z-index: 1; + transition: background-color ease-in-out 200ms; } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts index 7c0add312edfcb5f5741e63bdefbad61c160a0f3..4544ff07bbd8a19741c55ccd326b04b64f03fa0c 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.spec.ts @@ -22,12 +22,29 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { NavigationService } from '@alfa-client/navigation-shared'; -import { ConvertForDataTestPipe, EMPTY_STRING, HasLinkPipe, ToEmbeddedResourcesPipe, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; -import { dispatchEventFromFixture, getElementFromFixture, mock, useFromMock } from '@alfa-client/test-utils'; +import { + ConvertForDataTestPipe, + EMPTY_STRING, + HasLinkPipe, + ToEmbeddedResourcesPipe, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; +import { + dispatchEventFromFixture, + getElementFromFixture, + mock, + useFromMock, +} from '@alfa-client/test-utils'; import { SpinnerComponent } from '@alfa-client/ui'; import { VorgangHeaderLinkRel, VorgangListService } from '@alfa-client/vorgang-shared'; import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { ReactiveFormsModule, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; +import { + ReactiveFormsModule, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, +} from '@angular/forms'; import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatButton } from '@angular/material/button'; import { MatFormFieldModule } from '@angular/material/form-field'; @@ -45,226 +62,227 @@ import { VorgangSearchComponent } from './vorgang-search.component'; import { VorgangSearchFormService } from './vorgang-search.formservice'; describe('VorgangSearchComponent', () => { - let component: VorgangSearchComponent; - let fixture: ComponentFixture<VorgangSearchComponent>; - let searchFormService: VorgangSearchFormService; - - const vorgangListService = mock(VorgangListService); - const navigationService = mock(NavigationService); - - const searchStringSubj: Subject<string> = new BehaviorSubject(EMPTY_STRING); - - const searchPreviewOption: string = getDataTestClassOf('search-preview-option'); - const searchClearButton: string = getDataTestIdOf('vorgang-search-clear-button'); - - beforeEach(async () => { - vorgangListService.getSearchString.mockReturnValue(searchStringSubj); - - searchFormService = new VorgangSearchFormService(new UntypedFormBuilder, useFromMock(navigationService), useFromMock(vorgangListService)); - - await TestBed.configureTestingModule({ - declarations: [ - VorgangSearchComponent, - MatIcon, - ToEmbeddedResourcesPipe, - HasLinkPipe, - ConvertForDataTestPipe, - MockComponent(VorgangSearchAutocompleteOptionsContentComponent), - MockComponent(VorgangSearchClearButtonComponent), - MockComponent(SpinnerComponent) - ], - imports: [ - MatFormFieldModule, - MatInputModule, - ReactiveFormsModule, - NoopAnimationsModule, - RouterTestingModule, - MatAutocompleteModule - ], - providers: [ - UntypedFormBuilder, - { - provide: VorgangSearchFormService, - useValue: searchFormService - }, - { - provide: VorgangListService, - useValue: vorgangListService - }, - { - provide: NavigationService, - useValue: navigationService - } - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(VorgangSearchComponent); - component = fixture.componentInstance; - component.vorgangSearchPreviewList = createEmptyStateResource(); - navigationService.urlChanged.mockReturnValue(of({})); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe.skip('FIXME: search preview option', () => { - - it('should hide on non existing link', () => { - component.vorgangSearchPreviewList = createStateResource(createVorgangListResource()); - - fixture.detectChanges(); - const button = getElementFromFixture(fixture, searchPreviewOption); - - expect(button).not.toBeInstanceOf(HTMLElement); - }) + let component: VorgangSearchComponent; + let fixture: ComponentFixture<VorgangSearchComponent>; + let searchFormService: VorgangSearchFormService; + + const vorgangListService = mock(VorgangListService); + const navigationService = mock(NavigationService); + + const searchStringSubj: Subject<string> = new BehaviorSubject(EMPTY_STRING); + + const searchPreviewOption: string = getDataTestClassOf('search-preview-option'); + const searchClearButton: string = getDataTestIdOf('vorgang-search-clear-button'); + + beforeEach(async () => { + vorgangListService.getSearchString.mockReturnValue(searchStringSubj); + + searchFormService = new VorgangSearchFormService( + new UntypedFormBuilder(), + useFromMock(navigationService), + useFromMock(vorgangListService), + ); + + await TestBed.configureTestingModule({ + declarations: [ + VorgangSearchComponent, + MatIcon, + ToEmbeddedResourcesPipe, + HasLinkPipe, + ConvertForDataTestPipe, + MockComponent(VorgangSearchAutocompleteOptionsContentComponent), + MockComponent(VorgangSearchClearButtonComponent), + MockComponent(SpinnerComponent), + ], + imports: [ + MatFormFieldModule, + MatInputModule, + ReactiveFormsModule, + NoopAnimationsModule, + RouterTestingModule, + MatAutocompleteModule, + ], + providers: [ + UntypedFormBuilder, + { + provide: VorgangSearchFormService, + useValue: searchFormService, + }, + { + provide: VorgangListService, + useValue: vorgangListService, + }, + { + provide: NavigationService, + useValue: navigationService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangSearchComponent); + component = fixture.componentInstance; + component.vorgangSearchPreviewList = createEmptyStateResource(); + navigationService.urlChanged.mockReturnValue(of({})); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe.skip('FIXME: search preview option', () => { + it('should hide on non existing link', () => { + component.vorgangSearchPreviewList = createStateResource(createVorgangListResource()); + + fixture.detectChanges(); + const button = getElementFromFixture(fixture, searchPreviewOption); + + expect(button).not.toBeInstanceOf(HTMLElement); + }); + + it('should shown on existing link', () => { + component.vorgangSearchPreviewList = createStateResource( + createVorgangListResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]), + ); + + fixture.detectChanges(); + const button = getElementFromFixture(fixture, searchPreviewOption); + + expect(button).toBeInstanceOf(HTMLElement); + }); + }); + + describe('search clear button', () => { + beforeEach(() => { + searchStringSubj.next('test'); + fixture.detectChanges(); + }); + + it('should emit clearVorgangSearchPreviewList event', () => { + jest.spyOn(component.clearVorgangSearchPreviewList, 'emit'); + + // Workaround: Timingprobleme entfernen den Clear-Button zu früh, + // seit debounceTime() in VorgangSearchFormService::subscribeToValueChanges() vor setHasSearchString() kommt. + // dispatchEventFromFixture(fixture, searchClearButton, 'clear'); + component.handleSearchClearButton(); + + expect(component.clearVorgangSearchPreviewList.emit).toHaveBeenCalled(); + }); + + it.skip('FIXME: should call searchFormService.clearSearchField', () => { + searchFormService.clearSearchField = jest.fn(); + + dispatchEventFromFixture(fixture, searchClearButton, 'clear'); + + expect(searchFormService.clearSearchField).toHaveBeenCalled(); + }); + + it('should set focus to input', () => { + jest.spyOn(component.searchInput.nativeElement, 'focus'); + + // Workaround: Timingprobleme entfernen den Clear-Button zu früh, + // seit debounceTime() in VorgangSearchFormService::subscribeToValueChanges() vor setHasSearchString() kommt. + // dispatchEventFromFixture(fixture, searchClearButton, 'clear'); + component.handleSearchClearButton(); + + expect(component.searchInput.nativeElement.focus).toHaveBeenCalled(); + }); + + it('should call handleSearchClearButton', () => { + component.handleSearchClearButton = jest.fn(); + + // Workaround: Timingprobleme entfernen den Clear-Button zu früh, + // seit debounceTime() in VorgangSearchFormService::subscribeToValueChanges() vor setHasSearchString() kommt. + // dispatchEventFromFixture(fixture, searchClearButton, 'clear'); + component.handleSearchClearButton(); + + expect(component.handleSearchClearButton).toHaveBeenCalled(); + }); + }); + + describe('submit', () => { + it('should not navigate to search if search field is empty', () => { + const submitSpy = jest.spyOn(NavigationService.prototype, 'search'); + + fixture.detectChanges(); + component.submit(); - it('should shown on existing link', () => { - component.vorgangSearchPreviewList = createStateResource(createVorgangListResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG])); - - fixture.detectChanges(); - const button = getElementFromFixture(fixture, searchPreviewOption); + expect(submitSpy).not.toHaveBeenCalled(); + }); - expect(button).toBeInstanceOf(HTMLElement); - }) - }) + it('should store entered search value', () => { + jest.spyOn(VorgangSearchFormService.prototype, 'getValue').mockReturnValue('Gewerbe'); - describe('search clear button', () => { - beforeEach(() => { - searchStringSubj.next('test'); - fixture.detectChanges(); - }) - - it('should emit clearVorgangSearchPreviewList event', () => { - jest.spyOn(component.clearVorgangSearchPreviewList, 'emit'); - - // Workaround: Timingprobleme entfernen den Clear-Button zu früh, - // seit debounceTime() in VorgangSearchFormService::subscribeToValueChanges() vor setHasSearchString() kommt. - // dispatchEventFromFixture(fixture, searchClearButton, 'clear'); - component.handleSearchClearButton(); - - expect(component.clearVorgangSearchPreviewList.emit).toHaveBeenCalled(); - }) - - it.skip('FIXME: should call searchFormService.clearSearchField', () => { - searchFormService.clearSearchField = jest.fn(); - - dispatchEventFromFixture(fixture, searchClearButton, 'clear'); - - expect(searchFormService.clearSearchField).toHaveBeenCalled(); - }) - - it('should set focus to input', () => { - jest.spyOn(component.searchInput.nativeElement, 'focus'); - - // Workaround: Timingprobleme entfernen den Clear-Button zu früh, - // seit debounceTime() in VorgangSearchFormService::subscribeToValueChanges() vor setHasSearchString() kommt. - // dispatchEventFromFixture(fixture, searchClearButton, 'clear'); - component.handleSearchClearButton(); - - expect(component.searchInput.nativeElement.focus).toHaveBeenCalled(); - }) - - it('should call handleSearchClearButton', () => { - component.handleSearchClearButton = jest.fn(); + component.submit(); - // Workaround: Timingprobleme entfernen den Clear-Button zu früh, - // seit debounceTime() in VorgangSearchFormService::subscribeToValueChanges() vor setHasSearchString() kommt. - // dispatchEventFromFixture(fixture, searchClearButton, 'clear'); - component.handleSearchClearButton(); + expect(component.previouslyEnteredSearchValue).toEqual('Gewerbe'); + }); - expect(component.handleSearchClearButton).toHaveBeenCalled(); - }) - }); + it('should submit form', () => { + const submitSpy = jest.spyOn(VorgangSearchFormService.prototype, 'submit'); - describe('submit', () => { - it('should not navigate to search if search field is empty', () => { - const submitSpy = jest.spyOn(NavigationService.prototype, 'search'); + component.submit(); - fixture.detectChanges(); - component.submit(); + expect(submitSpy).toHaveBeenCalled(); + }); - expect(submitSpy).not.toHaveBeenCalled(); - }) + it('should remove focus from search INPUT', () => { + component.blur = jest.fn(); - it('should store entered search value', () => { - jest.spyOn(VorgangSearchFormService.prototype, 'getValue').mockReturnValue('Gewerbe'); + component.submit(); - component.submit(); + expect(component.blur).toHaveBeenCalled(); + }); + }); - expect(component.previouslyEnteredSearchValue).toEqual('Gewerbe'); - }); + describe('focusIn', () => { + it('should store current form value', () => { + jest.spyOn(VorgangSearchFormService.prototype, 'getValue').mockReturnValue('Gewerbe'); - it('should submit form', () => { - const submitSpy = jest.spyOn(VorgangSearchFormService.prototype, 'submit'); + component.focusIn(); - component.submit(); + expect(component.previouslyEnteredSearchValue).toEqual('Gewerbe'); + }); + }); - expect(submitSpy).toHaveBeenCalled(); - }); + describe('focusOut', () => { + function createSearchSubmitMockButton(nativeElement: any): MatButton { + return { + _elementRef: { + nativeElement: nativeElement, + }, + } as MatButton; + } - it('should remove focus from search INPUT', () => { - component.blur = jest.fn(); + function createMockFormGroup(searchFieldFormControl: UntypedFormControl): UntypedFormGroup { + return new UntypedFormGroup({ + search: searchFieldFormControl, + }); + } - component.submit(); + it('should set new form value when focus out to search button (Lupe)', () => { + const lupeElement = {}; + component.previouslyEnteredSearchValue = 'Gewerbe'; + component.searchSubmitButton = createSearchSubmitMockButton(lupeElement); + const searchFieldFormControl = new UntypedFormControl('Gewe'); + component.formService.form = createMockFormGroup(searchFieldFormControl); - expect(component.blur).toHaveBeenCalled(); - }) - }); + component.focusOut({ relatedTarget: lupeElement } as FocusEvent); - describe('focusIn', () => { + expect(searchFieldFormControl.value).toEqual('Gewe'); + }); - it('should store current form value', () => { - jest.spyOn(VorgangSearchFormService.prototype, 'getValue').mockReturnValue('Gewerbe'); + it('should set previous value', () => { + component.previouslyEnteredSearchValue = 'Gewe'; + component.searchSubmitButton = createSearchSubmitMockButton(null); + const searchFieldFormControl = new UntypedFormControl('Gewerbe'); + component.formService.form = createMockFormGroup(searchFieldFormControl); - component.focusIn(); + component.focusOut({ relatedTarget: {} } as FocusEvent); - expect(component.previouslyEnteredSearchValue).toEqual('Gewerbe'); - }); - }); - - describe('focusOut', () => { - - function createSearchSubmitMockButton(nativeElement: any): MatButton { - return { - _elementRef: { - nativeElement: nativeElement - } - } as MatButton; - } - - function createMockFormGroup(searchFieldFormControl: UntypedFormControl): UntypedFormGroup { - return new UntypedFormGroup({ - search: searchFieldFormControl - }); - } - - it('should set new form value when focus out to search button (Lupe)', () => { - const lupeElement = {}; - component.previouslyEnteredSearchValue = 'Gewerbe'; - component.searchSubmitButton = createSearchSubmitMockButton(lupeElement); - const searchFieldFormControl = new UntypedFormControl('Gewe'); - component.formService.form = createMockFormGroup(searchFieldFormControl); - - component.focusOut({ relatedTarget: lupeElement } as FocusEvent); - - expect(searchFieldFormControl.value).toEqual('Gewe'); - }); - - - it('should set previous value', () => { - component.previouslyEnteredSearchValue = 'Gewe'; - component.searchSubmitButton = createSearchSubmitMockButton(null); - const searchFieldFormControl = new UntypedFormControl('Gewerbe'); - component.formService.form = createMockFormGroup(searchFieldFormControl); - - component.focusOut({ relatedTarget: {} } as FocusEvent); - - expect(searchFieldFormControl.value).toEqual('Gewe'); - }); - }); - -}); \ No newline at end of file + expect(searchFieldFormControl.value).toEqual('Gewe'); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.ts index aeb851da2b38dabe2c85afa2a38891c9d27d008a..cccfbaf8d41ff25b10b39d5643c5e1dfc29c057f 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.component.ts @@ -25,69 +25,72 @@ import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@ import { MatAutocomplete } from '@angular/material/autocomplete'; import { MatButton } from '@angular/material/button'; import { StateResource, isNotNil } from '@alfa-client/tech-shared'; -import { VorgangHeaderLinkRel, VorgangListLinkRel, VorgangListResource } from '@alfa-client/vorgang-shared'; +import { + VorgangHeaderLinkRel, + VorgangListLinkRel, + VorgangListResource, +} from '@alfa-client/vorgang-shared'; import { VorgangSearchFormService } from './vorgang-search.formservice'; @Component({ - selector: 'alfa-vorgang-search', - templateUrl: './vorgang-search.component.html', - styleUrls: ['./vorgang-search.component.scss'], - providers: [VorgangSearchFormService] + selector: 'alfa-vorgang-search', + templateUrl: './vorgang-search.component.html', + styleUrls: ['./vorgang-search.component.scss'], + providers: [VorgangSearchFormService], }) export class VorgangSearchComponent { + @Input() vorgangSearchPreviewList: StateResource<VorgangListResource>; + @Input() searchString: string; - @Input() vorgangSearchPreviewList: StateResource<VorgangListResource>; - @Input() searchString: string; + @Output() public clearVorgangSearchPreviewList: EventEmitter<void> = new EventEmitter<void>(); - @Output() public clearVorgangSearchPreviewList: EventEmitter<void> = new EventEmitter<void>(); + @ViewChild('searchInput') searchInput: ElementRef; + @ViewChild('searchSubmitButton') searchSubmitButton: MatButton; + @ViewChild('searchAutoComplete') searchAutoComplete: MatAutocomplete; - @ViewChild('searchInput') searchInput: ElementRef; - @ViewChild('searchSubmitButton') searchSubmitButton: MatButton; - @ViewChild('searchAutoComplete') searchAutoComplete: MatAutocomplete; + previouslyEnteredSearchValue: string; - previouslyEnteredSearchValue: string; + readonly vorgangHeaderLinkRel = VorgangHeaderLinkRel; + readonly vorgangListLinkRel = VorgangListLinkRel; - readonly vorgangHeaderLinkRel = VorgangHeaderLinkRel; - readonly vorgangListLinkRel = VorgangListLinkRel; + constructor(public formService: VorgangSearchFormService) {} - constructor(public formService: VorgangSearchFormService) { } + submit(): void { + this.previouslyEnteredSearchValue = this.formService.getValue(); + this.formService.submit(); + this.blur(); + } - submit(): void { - this.previouslyEnteredSearchValue = this.formService.getValue(); - this.formService.submit(); - this.blur(); - } + blur(): void { + this.searchInput.nativeElement.blur(); + } - blur(): void { - this.searchInput.nativeElement.blur(); - } + focusIn(): void { + this.previouslyEnteredSearchValue = this.formService.getValue(); + } - focusIn(): void { - this.previouslyEnteredSearchValue = this.formService.getValue(); - } + focusOut(event: FocusEvent): void { + if (!this.isRelatedTargetSearchButton(event) && !this.isMatOption(event.relatedTarget)) { + this.formService.setSearchValue(this.previouslyEnteredSearchValue); + } + } - focusOut(event: FocusEvent): void { - if (!this.isRelatedTargetSearchButton(event) && !this.isMatOption(event.relatedTarget)) { - this.formService.setSearchValue(this.previouslyEnteredSearchValue); - } - } + private isRelatedTargetSearchButton(event: FocusEvent): boolean { + return event.relatedTarget === this.searchSubmitButton._elementRef.nativeElement; + } - private isRelatedTargetSearchButton(event: FocusEvent): boolean { - return event.relatedTarget === this.searchSubmitButton._elementRef.nativeElement; - } + //Hack|Workaround -> schnellstmoeglich wieder ausbauen! + private isMatOption(eventTarget: EventTarget) { + return isNotNil(eventTarget) && (<any>eventTarget).nodeName + '' === 'MAT_OPTION'; + } - //Hack|Workaround -> schnellstmoeglich wieder ausbauen! - private isMatOption(eventTarget: EventTarget){ - return isNotNil(eventTarget) && ((<any>eventTarget).nodeName) + '' === 'MAT_OPTION'; - } + public handleSearchClearButton(): void { + this.clearVorgangSearchPreviewList.emit(); + this.formService.clearSearchField(); + this.focus(); + } - public handleSearchClearButton(): void { - this.clearVorgangSearchPreviewList.emit(); - this.formService.clearSearchField(); - this.focus(); - } - - focus(): void { - this.searchInput.nativeElement.focus(); - } -} \ No newline at end of file + focus(): void { + this.searchInput.nativeElement.focus(); + } +} diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.spec.ts index c5c9eb3b8e640c59f5c754f65c5b7f20915881c3..f84d501a719fb4fe3a75a86a22a2ed92757f2850 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.spec.ts @@ -27,285 +27,283 @@ import { faker } from '@faker-js/faker'; import { NavigationService } from '@alfa-client/navigation-shared'; import { EMPTY_STRING, encodeUrlForEmbedding } from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; -import { VorgangHeaderLinkRel, VorgangListService, VorgangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangHeaderLinkRel, + VorgangListService, + VorgangResource, +} from '@alfa-client/vorgang-shared'; import { ResourceUri, getUrl } from '@ngxp/rest'; import { createVorgangResource } from 'libs/vorgang-shared/test/vorgang'; import { Observable, of } from 'rxjs'; import { VorgangSearchFormService } from './vorgang-search.formservice'; describe('VorgangSearchFormService', () => { - let formService: VorgangSearchFormService;; - let navigationService: Mock<NavigationService>; - let vorgangListService: Mock<VorgangListService> + let formService: VorgangSearchFormService; + let navigationService: Mock<NavigationService>; + let vorgangListService: Mock<VorgangListService>; - const SEARCH_STRING = faker.word.noun(); + const SEARCH_STRING = faker.word.noun(); - beforeEach(() => { - vorgangListService = mock(VorgangListService); - navigationService = mock(NavigationService); - vorgangListService.getSearchString.mockReturnValue(of({})); + beforeEach(() => { + vorgangListService = mock(VorgangListService); + navigationService = mock(NavigationService); + vorgangListService.getSearchString.mockReturnValue(of({})); - formService = new VorgangSearchFormService(new UntypedFormBuilder(), useFromMock(navigationService), useFromMock(vorgangListService)); - }) + formService = new VorgangSearchFormService( + new UntypedFormBuilder(), + useFromMock(navigationService), + useFromMock(vorgangListService), + ); + }); - it('should create', () => { - expect(formService).toBeTruthy(); - }); + it('should create', () => { + expect(formService).toBeTruthy(); + }); - describe('setHasSearchString', () => { - it('should set hasSearchString to true', () => { - formService.setHasSearchString(faker.word.adverb()); + describe('setHasSearchString', () => { + it('should set hasSearchString to true', () => { + formService.setHasSearchString(faker.word.adverb()); - expect(formService.hasSearchString).toBeTruthy(); - }) + expect(formService.hasSearchString).toBeTruthy(); + }); - it('should set hasSearchString to false', () => { - formService.setHasSearchString(EMPTY_STRING); + it('should set hasSearchString to false', () => { + formService.setHasSearchString(EMPTY_STRING); - expect(formService.hasSearchString).toBeFalsy(); - }) - }) + expect(formService.hasSearchString).toBeFalsy(); + }); + }); - describe('handleValueChanges', () => { + describe('handleValueChanges', () => { + describe('on should search for preview', () => { + beforeEach(() => { + formService.shouldSearchForPreview = jest.fn().mockReturnValue(true); + }); - describe('on should search for preview', () => { + it('should set searchString on at least 3 characters', () => { + formService.handleValueChanges(SEARCH_STRING); - beforeEach(() => { - formService.shouldSearchForPreview = jest.fn().mockReturnValue(true); - }) + expect(vorgangListService.setSearchString).toHaveBeenCalledWith(SEARCH_STRING); + }); - it('should set searchString on at least 3 characters', () => { - formService.handleValueChanges(SEARCH_STRING); + it('should do search for preview list on at least 3 characters', () => { + formService.handleValueChanges(SEARCH_STRING); - expect(vorgangListService.setSearchString).toHaveBeenCalledWith(SEARCH_STRING); - }) + expect(vorgangListService.searchForPreview).toHaveBeenCalledWith(SEARCH_STRING); + }); + }); - it('should do search for preview list on at least 3 characters', () => { - formService.handleValueChanges(SEARCH_STRING); + describe('on should NOT search for preview', () => { + beforeEach(() => { + formService.shouldSearchForPreview = jest.fn().mockReturnValue(false); + }); - expect(vorgangListService.searchForPreview).toHaveBeenCalledWith(SEARCH_STRING); - }) - }) + it('should call vorgangListService.clearSearchPreviewList if search string is lesser than 3', () => { + const searchString: string = faker.word.verb(2); - describe('on should NOT search for preview', () => { + formService.handleValueChanges(searchString); - beforeEach(() => { - formService.shouldSearchForPreview = jest.fn().mockReturnValue(false); - }) + expect(vorgangListService.clearSearchPreviewList).toHaveBeenCalled(); + }); + }); + }); - it('should call vorgangListService.clearSearchPreviewList if search string is lesser than 3', () => { - const searchString: string = faker.word.verb(2); + describe('shouldSearchForPreview', () => { + const VALID_SEARCH_STRING: string = 'minLengthSearchString'; - formService.handleValueChanges(searchString); + describe('should return false', () => { + beforeEach(() => { + formService.lastSearchString = 'quatsch'; + }); - expect(vorgangListService.clearSearchPreviewList).toHaveBeenCalled(); - }) - }) - }) + it('on searchInput is pristine', () => { + formService.isSearchInputNotPristine = jest.fn().mockReturnValue(false); - describe('shouldSearchForPreview', () => { + const shouldSearch: boolean = formService.shouldSearchForPreview(VALID_SEARCH_STRING); - const VALID_SEARCH_STRING: string = 'minLengthSearchString'; + expect(shouldSearch).toBeFalsy(); + }); - describe('should return false', () => { + it('on searchString length is lower than 3', () => { + formService.isSearchInputNotPristine = jest.fn().mockReturnValue(true); - beforeEach(() => { - formService.lastSearchString = 'quatsch'; - }) + const shouldSearch: boolean = formService.shouldSearchForPreview('ab'); - it('on searchInput is pristine', () => { - formService.isSearchInputNotPristine = jest.fn().mockReturnValue(false) + expect(shouldSearch).toBeFalsy(); + }); - const shouldSearch: boolean = formService.shouldSearchForPreview(VALID_SEARCH_STRING); + it('on searchString is equals lastsearchString', () => { + formService.lastSearchString = VALID_SEARCH_STRING; + formService.isSearchInputNotPristine = jest.fn().mockReturnValue(true); - expect(shouldSearch).toBeFalsy(); - }) + const shouldSearch: boolean = formService.shouldSearchForPreview(VALID_SEARCH_STRING); - it('on searchString length is lower than 3', () => { - formService.isSearchInputNotPristine = jest.fn().mockReturnValue(true) + expect(shouldSearch).toBeFalsy(); + }); + }); - const shouldSearch: boolean = formService.shouldSearchForPreview('ab'); + describe('should return true', () => { + beforeEach(() => { + formService.lastSearchString = 'quatsch'; + formService.isSearchInputNotPristine = jest.fn().mockReturnValue(true); + }); - expect(shouldSearch).toBeFalsy(); - }) + it('on searchInput is NOT pristine, has minLength and is not lastSearchString', () => { + const shouldSearch: boolean = formService.shouldSearchForPreview(VALID_SEARCH_STRING); - it('on searchString is equals lastsearchString', () => { - formService.lastSearchString = VALID_SEARCH_STRING; - formService.isSearchInputNotPristine = jest.fn().mockReturnValue(true) + expect(shouldSearch).toBeTruthy(); + }); + }); + }); - const shouldSearch: boolean = formService.shouldSearchForPreview(VALID_SEARCH_STRING); + describe('getValue', () => { + it('should return null on empty search string', () => { + getSearchFormControl().patchValue(EMPTY_STRING); - expect(shouldSearch).toBeFalsy(); - }) - }) + const value: string = formService.getValue(); - describe('should return true', () => { + expect(value).toBeNull(); + }); - beforeEach(() => { - formService.lastSearchString = 'quatsch'; - formService.isSearchInputNotPristine = jest.fn().mockReturnValue(true) - }) + it('should return value of search string if not nil', () => { + getSearchFormControl().patchValue(SEARCH_STRING); - it('on searchInput is NOT pristine, has minLength and is not lastSearchString', () => { - const shouldSearch: boolean = formService.shouldSearchForPreview(VALID_SEARCH_STRING); + const result: string = formService.getValue(); - expect(shouldSearch).toBeTruthy(); - }) - }) - }) + expect(result).toEqual(SEARCH_STRING); + }); + }); - describe('getValue', () => { + describe('patchSearchString', () => { + it('should patch search string field if its different', () => { + const newSearchString: string = 'i search for something other...'; + getSearchFormControl().patchValue(SEARCH_STRING); - it('should return null on empty search string', () => { - getSearchFormControl().patchValue(EMPTY_STRING); + formService.patchSearchString(newSearchString); - const value: string = formService.getValue(); + expect(getSearchFormControl().value).toEqual(newSearchString); + }); - expect(value).toBeNull(); - }) + it('should set lastSearchString', () => { + formService.patchSearchString(SEARCH_STRING); - it('should return value of search string if not nil', () => { - getSearchFormControl().patchValue(SEARCH_STRING); + expect(formService.lastSearchString).toEqual(SEARCH_STRING); + }); + }); - const result: string = formService.getValue(); + describe('navigateToVorgangListOnSearch', () => { + it('should call navigateToVorgangList when at search page', () => { + const params: Params = { search: faker.random.word() }; - expect(result).toEqual(SEARCH_STRING); - }) - }) + formService.navigateToVorgangListOnSearch(params); - describe('patchSearchString', () => { + expect(navigationService.navigateToVorgangList).toHaveBeenCalled(); + }); - it('should patch search string field if its different', () => { - const newSearchString: string = 'i search for something other...'; - getSearchFormControl().patchValue(SEARCH_STRING); + it('should not call navigateToVorgangList when at non-search page', () => { + const params: Params = {}; - formService.patchSearchString(newSearchString); + formService.navigateToVorgangListOnSearch(params); - expect(getSearchFormControl().value).toEqual(newSearchString); - }) + expect(navigationService.navigateToVorgangList).not.toHaveBeenCalled(); + }); + }); - it('should set lastSearchString', () => { - formService.patchSearchString(SEARCH_STRING); + describe('submit', () => { + it('should navigate to itself with search param', () => { + formService.hasSearchString = true; + getSearchFormControl().patchValue(SEARCH_STRING); - expect(formService.lastSearchString).toEqual(SEARCH_STRING); - }) - }) + formService.submit(); - describe('navigateToVorgangListOnSearch', () => { + expect(navigationService.search).toHaveBeenCalledWith(SEARCH_STRING); + }); + }); - it('should call navigateToVorgangList when at search page', () => { - const params: Params = { search: faker.random.word() } + describe('clear button', () => { + beforeEach(() => { + navigationService.urlChanged.mockReturnValue(of({})); + }); - formService.navigateToVorgangListOnSearch(params); + it('should clear field', () => { + getSearchFormControl().patchValue(SEARCH_STRING); - expect(navigationService.navigateToVorgangList).toHaveBeenCalled(); - }) + formService.clearSearchField(); - it('should not call navigateToVorgangList when at non-search page', () => { - const params: Params = {} + expect(getSearchFormControl().value).toBe(EMPTY_STRING); + }); - formService.navigateToVorgangListOnSearch(params); + it('should call navigateToVorgangListOnSearch()', () => { + formService.navigateToVorgangListOnSearch = jest.fn(); - expect(navigationService.navigateToVorgangList).not.toHaveBeenCalled(); - }) - }) + formService.clearSearchField(); - describe('submit', () => { + expect(formService.navigateToVorgangListOnSearch).toHaveBeenCalled(); + }); + }); - it('should navigate to itself with search param', () => { - formService.hasSearchString = true; - getSearchFormControl().patchValue(SEARCH_STRING); + describe('submitByPreviewList', () => { + const vorgang: VorgangResource = createVorgangResource([ + VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, + ]); + const searchString: string = faker.name.firstName(); - formService.submit(); + it('should clear searchString', () => { + formService.submitByPreviewList(vorgang, searchString); - expect(navigationService.search).toHaveBeenCalledWith(SEARCH_STRING); - }) - }) + expect(getSearchFormControl().value).toBe(searchString); + }); - describe('clear button', () => { + it('should navigate', () => { + const uri: ResourceUri = getUrl(vorgang, VorgangHeaderLinkRel.VORGANG_WITH_EINGANG); - beforeEach(() => { - navigationService.urlChanged.mockReturnValue(of({})); - }); + formService.submitByPreviewList(vorgang, searchString); - it('should clear field', () => { - getSearchFormControl().patchValue(SEARCH_STRING); + expect(navigationService.navigateToVorgang).toHaveBeenCalledWith(encodeUrlForEmbedding(uri)); + }); + }); - formService.clearSearchField(); + describe('isSearchInputNotPristine', () => { + it('should return false if search INPUT is pristine', () => { + getSearchFormControl().markAsPristine(); - expect(getSearchFormControl().value).toBe(EMPTY_STRING); - }) + expect(formService.isSearchInputNotPristine()).toBeFalsy(); + }); + it('should return true if search INPUT is not pristine', () => { + getSearchFormControl().markAsDirty(); - it('should call navigateToVorgangListOnSearch()', () => { - formService.navigateToVorgangListOnSearch = jest.fn(); + expect(formService.isSearchInputNotPristine()).toBeTruthy(); + }); + }); - formService.clearSearchField(); + describe('isSameSearchString', () => { + beforeEach(() => { + formService.getValue = jest.fn().mockReturnValue(SEARCH_STRING); + }); - expect(formService.navigateToVorgangListOnSearch).toHaveBeenCalled(); - }); - }) + it('should return false if search string has changed', () => { + formService.lastSearchString = faker.word.noun(); - describe('submitByPreviewList', () => { + expect(formService.isSameSearchString()).toBeFalsy(); + }); + it('should return true if search string has NOT changed', () => { + formService.lastSearchString = SEARCH_STRING; - const vorgang: VorgangResource = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]); - const searchString: string = faker.name.firstName(); + expect(formService.isSameSearchString()).toBeTruthy(); + }); + }); - it('should clear searchString', () => { - formService.submitByPreviewList(vorgang, searchString); + describe('getValueChanges', () => { + it.skip('should return observable for search string', () => { + getSearchFormControl().patchValue(SEARCH_STRING); - expect(getSearchFormControl().value).toBe(searchString); - }) + const result: Observable<string> = formService.getValueChanges(); - it('should navigate', () => { - const uri: ResourceUri = getUrl(vorgang, VorgangHeaderLinkRel.VORGANG_WITH_EINGANG); + expect(result).toBe(SEARCH_STRING); + }); + }); - formService.submitByPreviewList(vorgang, searchString); - - expect(navigationService.navigateToVorgang).toHaveBeenCalledWith(encodeUrlForEmbedding(uri)); - }) - }) - - describe('isSearchInputNotPristine', () => { - it('should return false if search INPUT is pristine', () => { - getSearchFormControl().markAsPristine(); - - expect(formService.isSearchInputNotPristine()).toBeFalsy(); - }) - it('should return true if search INPUT is not pristine', () => { - getSearchFormControl().markAsDirty(); - - expect(formService.isSearchInputNotPristine()).toBeTruthy(); - }) - }) - - describe('isSameSearchString', () => { - beforeEach(() => { - formService.getValue = jest.fn().mockReturnValue(SEARCH_STRING); - }) - - it('should return false if search string has changed', () => { - formService.lastSearchString = faker.word.noun(); - - expect(formService.isSameSearchString()).toBeFalsy(); - }) - it('should return true if search string has NOT changed', () => { - formService.lastSearchString = SEARCH_STRING; - - expect(formService.isSameSearchString()).toBeTruthy(); - }) - }) - - describe('getValueChanges', () => { - it.skip('should return observable for search string', () => { - getSearchFormControl().patchValue(SEARCH_STRING); - - const result: Observable<string> = formService.getValueChanges(); - - expect(result).toBe(SEARCH_STRING); - }) - }) - - function getSearchFormControl(): FormControl { - return <FormControl>formService.form.controls[formService.SEARCH_FIELD]; - } -}) \ No newline at end of file + function getSearchFormControl(): FormControl { + return <FormControl>formService.form.controls[formService.SEARCH_FIELD]; + } +}); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.ts index db6415b64642a6c71fe223352d4f05583f5e8e07..3a65e9250ae11831cf30e208f7898e93a78ffeaf 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-search-container/vorgang-search/vorgang-search.formservice.ts @@ -25,137 +25,159 @@ import { Injectable, OnDestroy } from '@angular/core'; import { FormGroup, UntypedFormBuilder, UntypedFormControl } from '@angular/forms'; import { Params } from '@angular/router'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { EMPTY_STRING, hasMinLength, isNotEmpty, isNotNil, toResourceUri } from '@alfa-client/tech-shared'; -import { VorgangHeaderLinkRel, VorgangListService, VorgangResource } from '@alfa-client/vorgang-shared'; +import { + EMPTY_STRING, + hasMinLength, + isNotEmpty, + isNotNil, + toResourceUri, +} from '@alfa-client/tech-shared'; +import { + VorgangHeaderLinkRel, + VorgangListService, + VorgangResource, +} from '@alfa-client/vorgang-shared'; import { isEmpty, isEqual } from 'lodash-es'; import { Observable, Subscription } from 'rxjs'; import { debounceTime, distinctUntilChanged, first, tap } from 'rxjs/operators'; @Injectable() export class VorgangSearchFormService implements OnDestroy { - - form: FormGroup; - - readonly SEARCH_FIELD: string = 'search'; - readonly PREVIEW_SEARCH_STRING_MIN_LENGTH = 3; - - private searchStringSubscription: Subscription; - private fromControlSubscription: Subscription; - - public lastSearchString: string; - public hasSearchString: boolean = false; - - constructor( - private formBuilder: UntypedFormBuilder, - private navigationService: NavigationService, - private vorgangListService: VorgangListService - ) { - this.init(); - } - - private init(): void { - this.initForm(); - - this.subscribeToValueChanges(); - this.subscribeToSearchString(); - } - - private initForm(): void { - this.form = this.formBuilder.group({ - [this.SEARCH_FIELD]: new UntypedFormControl(null) - }) - } - - subscribeToValueChanges(): void { - this.fromControlSubscription = this.getSearchFormControl().valueChanges.pipe( - debounceTime(300), - tap(value => this.setHasSearchString(value)), - distinctUntilChanged() - ).subscribe(value => this.handleValueChanges(value)); - } - - setHasSearchString(value: string): void { - this.hasSearchString = isNotEmpty(value); - } - - handleValueChanges(value: string): void { - if (this.shouldSearchForPreview(value)) { - this.vorgangListService.setSearchString(value); - this.vorgangListService.searchForPreview(value); - } else { - this.vorgangListService.clearSearchPreviewList(); - } - } - - shouldSearchForPreview(value: string): boolean { - return this.isSearchInputNotPristine() && hasMinLength(value, this.PREVIEW_SEARCH_STRING_MIN_LENGTH) && !isEqual(this.lastSearchString, value); - } - - isSearchInputNotPristine(): boolean { - return ! this.getSearchFormControl().pristine; - } - - private subscribeToSearchString(): void { - this.searchStringSubscription = this.vorgangListService.getSearchString().subscribe((searchString: string) => this.patchSearchString(searchString)); - } - - patchSearchString(searchString: string): void { - const searchStringInputValue: string = this.getSearchFormControl().value; - if (searchString != searchStringInputValue) { - this.getSearchFormControl().patchValue(searchString); - } - this.lastSearchString = searchString; - } - - submit(): void { - if (this.hasSearchString) { - this.navigationService.search(this.getValue()); - } - } - - isSameSearchString(): boolean { - return this.getValue() === this.lastSearchString - } - - submitByPreviewList(resource: VorgangResource, searchString: string): void { - this.getSearchFormControl().patchValue(searchString); - this.navigateToVorgang(resource); - } - - public clearSearchField(): void { - this.patchSearchString(EMPTY_STRING); - this.navigationService.urlChanged().pipe(first()).subscribe(params => this.navigateToVorgangListOnSearch(params)); - } - - private getSearchFormControl(): UntypedFormControl { - return <UntypedFormControl>this.form.controls[this.SEARCH_FIELD]; - } - - private navigateToVorgang(resource: VorgangResource): void { - this.navigationService.navigateToVorgang(toResourceUri(resource, VorgangHeaderLinkRel.VORGANG_WITH_EINGANG)); - } - - navigateToVorgangListOnSearch(params: Params) { - if (NavigationService.isSearch(params)) { - this.navigationService.navigateToVorgangList(); - } - } - - getValue(): string { - const value: string = this.getSearchFormControl().value; - return isEmpty(value) ? null : value; - } - - public setSearchValue(value: string): void { - this.getSearchFormControl().setValue(value); - } - - ngOnDestroy(): void { - if (isNotNil(this.searchStringSubscription)) this.searchStringSubscription.unsubscribe(); - if (isNotNil(this.fromControlSubscription)) this.fromControlSubscription.unsubscribe(); - } - - public getValueChanges(): Observable<string> { - return this.getSearchFormControl().valueChanges; - } + form: FormGroup; + + readonly SEARCH_FIELD: string = 'search'; + readonly PREVIEW_SEARCH_STRING_MIN_LENGTH = 3; + + private searchStringSubscription: Subscription; + private fromControlSubscription: Subscription; + + public lastSearchString: string; + public hasSearchString: boolean = false; + + constructor( + private formBuilder: UntypedFormBuilder, + private navigationService: NavigationService, + private vorgangListService: VorgangListService, + ) { + this.init(); + } + + private init(): void { + this.initForm(); + + this.subscribeToValueChanges(); + this.subscribeToSearchString(); + } + + private initForm(): void { + this.form = this.formBuilder.group({ + [this.SEARCH_FIELD]: new UntypedFormControl(null), + }); + } + + subscribeToValueChanges(): void { + this.fromControlSubscription = this.getSearchFormControl() + .valueChanges.pipe( + debounceTime(300), + tap((value) => this.setHasSearchString(value)), + distinctUntilChanged(), + ) + .subscribe((value) => this.handleValueChanges(value)); + } + + setHasSearchString(value: string): void { + this.hasSearchString = isNotEmpty(value); + } + + handleValueChanges(value: string): void { + if (this.shouldSearchForPreview(value)) { + this.vorgangListService.setSearchString(value); + this.vorgangListService.searchForPreview(value); + } else { + this.vorgangListService.clearSearchPreviewList(); + } + } + + shouldSearchForPreview(value: string): boolean { + return ( + this.isSearchInputNotPristine() && + hasMinLength(value, this.PREVIEW_SEARCH_STRING_MIN_LENGTH) && + !isEqual(this.lastSearchString, value) + ); + } + + isSearchInputNotPristine(): boolean { + return !this.getSearchFormControl().pristine; + } + + private subscribeToSearchString(): void { + this.searchStringSubscription = this.vorgangListService + .getSearchString() + .subscribe((searchString: string) => this.patchSearchString(searchString)); + } + + patchSearchString(searchString: string): void { + const searchStringInputValue: string = this.getSearchFormControl().value; + if (searchString != searchStringInputValue) { + this.getSearchFormControl().patchValue(searchString); + } + this.lastSearchString = searchString; + } + + submit(): void { + if (this.hasSearchString) { + this.navigationService.search(this.getValue()); + } + } + + isSameSearchString(): boolean { + return this.getValue() === this.lastSearchString; + } + + submitByPreviewList(resource: VorgangResource, searchString: string): void { + this.getSearchFormControl().patchValue(searchString); + this.navigateToVorgang(resource); + } + + public clearSearchField(): void { + this.patchSearchString(EMPTY_STRING); + this.navigationService + .urlChanged() + .pipe(first()) + .subscribe((params) => this.navigateToVorgangListOnSearch(params)); + } + + private getSearchFormControl(): UntypedFormControl { + return <UntypedFormControl>this.form.controls[this.SEARCH_FIELD]; + } + + private navigateToVorgang(resource: VorgangResource): void { + this.navigationService.navigateToVorgang( + toResourceUri(resource, VorgangHeaderLinkRel.VORGANG_WITH_EINGANG), + ); + } + + navigateToVorgangListOnSearch(params: Params) { + if (NavigationService.isSearch(params)) { + this.navigationService.navigateToVorgangList(); + } + } + + getValue(): string { + const value: string = this.getSearchFormControl().value; + return isEmpty(value) ? null : value; + } + + public setSearchValue(value: string): void { + this.getSearchFormControl().setValue(value); + } + + ngOnDestroy(): void { + if (isNotNil(this.searchStringSubscription)) this.searchStringSubscription.unsubscribe(); + if (isNotNil(this.fromControlSubscription)) this.fromControlSubscription.unsubscribe(); + } + + public getValueChanges(): Observable<string> { + return this.getSearchFormControl().valueChanges; + } } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.spec.ts index 0f0a1b10791d5d5eb3fff1a90e3181325bc5da98..ae3941d79a4bf5e64ecae6fa5545072281787b39 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { VorgangSharedUiModule } from './vorgang-shared-ui.module'; describe('VorgangSharedUiModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [VorgangSharedUiModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [VorgangSharedUiModule], + }).compileComponents(); + }); - it('should create', () => { - expect(VorgangSharedUiModule).toBeDefined(); - }); + it('should create', () => { + expect(VorgangSharedUiModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.ts index 1d18b0f819e9763b4c1dd9f153171abc05791d2e..542c39b469e4eff2171701519b31a5950e68ed18 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-shared-ui.module.ts @@ -40,35 +40,29 @@ import { VorgangStatusTextComponent } from './vorgang-status-text/vorgang-status import { WiedervorlageIconComponent } from './wiedervorlage-icon/wiedervorlage-icon.component'; @NgModule({ - imports: [ - CommonModule, - VorgangSharedModule, - UiModule, - RouterModule, - TechSharedModule, - ], - declarations: [ - VorgangSearchContainerComponent, - VorgangSearchComponent, - AktenzeichenComponent, - VorgangStatusDotComponent, - VorgangInPostfachBreadcrumbContainerComponent, - VorgangInPostfachBreadcrumbComponent, - VorgangSearchAutocompleteOptionsContentComponent, - VorgangSearchClearButtonComponent, - VorgangNummerComponent, - VorgangStatusTextComponent, - WiedervorlageIconComponent, - ], - exports: [ - VorgangSearchContainerComponent, - AktenzeichenComponent, - VorgangStatusDotComponent, - VorgangInPostfachBreadcrumbContainerComponent, - VorgangSearchAutocompleteOptionsContentComponent, - VorgangNummerComponent, - VorgangStatusTextComponent, - WiedervorlageIconComponent, - ], + imports: [CommonModule, VorgangSharedModule, UiModule, RouterModule, TechSharedModule], + declarations: [ + VorgangSearchContainerComponent, + VorgangSearchComponent, + AktenzeichenComponent, + VorgangStatusDotComponent, + VorgangInPostfachBreadcrumbContainerComponent, + VorgangInPostfachBreadcrumbComponent, + VorgangSearchAutocompleteOptionsContentComponent, + VorgangSearchClearButtonComponent, + VorgangNummerComponent, + VorgangStatusTextComponent, + WiedervorlageIconComponent, + ], + exports: [ + VorgangSearchContainerComponent, + AktenzeichenComponent, + VorgangStatusDotComponent, + VorgangInPostfachBreadcrumbContainerComponent, + VorgangSearchAutocompleteOptionsContentComponent, + VorgangNummerComponent, + VorgangStatusTextComponent, + WiedervorlageIconComponent, + ], }) export class VorgangSharedUiModule {} diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.html index 7ee6729b333918537101344c2ab6c94002345863..abad421d16e9b40d65a600e1d3e2d4119821226b 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.html +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.html @@ -23,5 +23,11 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<div class="dot" aria-hidden="true" [style.width]="diameter + 'px'" - [style.height]="diameter + 'px'" [ngClass]="status | lowercase" data-test-id="vorgang-status-dot"></div> \ No newline at end of file +<div + class="dot" + aria-hidden="true" + [style.width]="diameter + 'px'" + [style.height]="diameter + 'px'" + [ngClass]="status | lowercase" + data-test-id="vorgang-status-dot" +></div> diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.scss b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.scss index 31d3a555ee22587580982771d98cc034405fe659..9f8c5f293497911e1cd80b8ef1dc290718c7d4b5 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.scss +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.scss @@ -26,29 +26,29 @@ @import 'variables'; .dot { - border-radius: 50%; - background-color: mat.get-color-from-palette($primaryPalette); - margin: 0 1.75rem 0 0; - flex-shrink: 0; + border-radius: 50%; + background-color: mat.get-color-from-palette($primaryPalette); + margin: 0 1.75rem 0 0; + flex-shrink: 0; - &.angenommen, - &.in_bearbeitung, - &.weiterleiten { - background-color: mat.get-color-from-palette($accentPalette, darker); - } + &.angenommen, + &.in_bearbeitung, + &.weiterleiten { + background-color: mat.get-color-from-palette($accentPalette, darker); + } - &.verworfen { - background-color: #999; - } + &.verworfen { + background-color: #999; + } - &.zu_loeschen { - border: 1px solid #bbb; - background-color: #fff; - } + &.zu_loeschen { + border: 1px solid #bbb; + background-color: #fff; + } - &.beschieden, - &.abgeschlossen, - &.weitergeleitet { - background-color: #7BCB2B; - } + &.beschieden, + &.abgeschlossen, + &.weitergeleitet { + background-color: #7bcb2b; + } } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.spec.ts index 9d023e70d65a4e3c4a158f7c525202f581830d50..b24a36b291266092b1beb7bedb0b6e3f9d30b964 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.spec.ts @@ -29,38 +29,35 @@ import { createVorgangResource } from 'libs/vorgang-shared/test/vorgang'; import { VorgangStatusDotComponent } from './vorgang-status-dot.component'; describe('VorgangStatusDotComponent', () => { - let component: VorgangStatusDotComponent; - let fixture: ComponentFixture<VorgangStatusDotComponent>; + let component: VorgangStatusDotComponent; + let fixture: ComponentFixture<VorgangStatusDotComponent>; - const vorgang: VorgangResource = createVorgangResource(); - const statusDotTestId: string = getDataTestIdOf('vorgang-status-dot'); + const vorgang: VorgangResource = createVorgangResource(); + const statusDotTestId: string = getDataTestIdOf('vorgang-status-dot'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangStatusDotComponent, - EnumToLabelPipe - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VorgangStatusDotComponent, EnumToLabelPipe], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangStatusDotComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangStatusDotComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should show status dot', () => { - component.status = vorgang.status; + it('should show status dot', () => { + component.status = vorgang.status; - fixture.detectChanges(); - const statusDotElement: HTMLElement = fixture.nativeElement.querySelector(statusDotTestId); - const statusClassName: string = vorgang.status.toLowerCase(); + fixture.detectChanges(); + const statusDotElement: HTMLElement = fixture.nativeElement.querySelector(statusDotTestId); + const statusClassName: string = vorgang.status.toLowerCase(); - expect(statusDotElement.classList.contains(statusClassName)).toBe(true); - }) + expect(statusDotElement.classList.contains(statusClassName)).toBe(true); + }); }); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.ts index 98db42d4b2e2e7ed576885fb0feb0bf604ff291f..684519d11dc8c352efd78ec4d525730ece160e3b 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-dot/vorgang-status-dot.component.ts @@ -25,14 +25,13 @@ import { Component, Input } from '@angular/core'; import { VorgangStatus, VorgangStatusLabel } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-vorgang-status-dot', - templateUrl: './vorgang-status-dot.component.html', - styleUrls: ['./vorgang-status-dot.component.scss'] + selector: 'alfa-vorgang-status-dot', + templateUrl: './vorgang-status-dot.component.html', + styleUrls: ['./vorgang-status-dot.component.scss'], }) export class VorgangStatusDotComponent { + @Input() status: VorgangStatus; + @Input() diameter: number = 14; - @Input() status: VorgangStatus; - @Input() diameter: number = 14; - - readonly vorgangStatusLabel = VorgangStatusLabel; + readonly vorgangStatusLabel = VorgangStatusLabel; } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.html index 3ee53d1d5d1cd691cabed5b7a89da80bc4d5c19b..49696ce3d838c9e0190c52e1a2e380e12864af4d 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.html +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.html @@ -23,4 +23,6 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<div class="status-name" data-test-id="vorgang-status-text">{{ status | enumToLabel: vorgangStatusLabel }}</div> +<div class="status-name" data-test-id="vorgang-status-text"> + {{ status | enumToLabel: vorgangStatusLabel }} +</div> diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.spec.ts index f79848745c23d1d7a1a6f8517351b59d901ef91e..4c85845d2178b7a2faadd81cc18a0ee8371f092a 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.spec.ts @@ -29,38 +29,35 @@ import { createVorgangResource } from 'libs/vorgang-shared/test/vorgang'; import { VorgangStatusTextComponent } from './vorgang-status-text.component'; describe('VorgangStatusTextComponent', () => { - let component: VorgangStatusTextComponent; - let fixture: ComponentFixture<VorgangStatusTextComponent>; + let component: VorgangStatusTextComponent; + let fixture: ComponentFixture<VorgangStatusTextComponent>; - const vorgang: VorgangResource = createVorgangResource(); - const statusTextTestId: string = getDataTestIdOf('vorgang-status-text'); + const vorgang: VorgangResource = createVorgangResource(); + const statusTextTestId: string = getDataTestIdOf('vorgang-status-text'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - EnumToLabelPipe, - VorgangStatusTextComponent - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [EnumToLabelPipe, VorgangStatusTextComponent], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangStatusTextComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangStatusTextComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should show status dot', () => { - component.status = vorgang.status; - const statusText: string = VorgangStatusLabel[vorgang.status]; + it('should show status dot', () => { + component.status = vorgang.status; + const statusText: string = VorgangStatusLabel[vorgang.status]; - fixture.detectChanges(); - const statusTextElement: HTMLElement = fixture.nativeElement.querySelector(statusTextTestId); + fixture.detectChanges(); + const statusTextElement: HTMLElement = fixture.nativeElement.querySelector(statusTextTestId); - expect(statusTextElement.innerHTML).toContain(statusText); - }); + expect(statusTextElement.innerHTML).toContain(statusText); + }); }); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.ts index 81b67353f02773e54e2f54e6ba5cc46ceafbee6f..4a46a08223176794182bf46222f0f8fe829de4fb 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-status-text/vorgang-status-text.component.ts @@ -27,9 +27,9 @@ import { VorgangStatus, VorgangStatusLabel } from '@alfa-client/vorgang-shared'; @Component({ selector: 'alfa-vorgang-status-text', templateUrl: './vorgang-status-text.component.html', - styleUrls: ['./vorgang-status-text.component.scss'] + styleUrls: ['./vorgang-status-text.component.scss'], }) export class VorgangStatusTextComponent { - @Input() status: VorgangStatus; - readonly vorgangStatusLabel = VorgangStatusLabel; + @Input() status: VorgangStatus; + readonly vorgangStatusLabel = VorgangStatusLabel; } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-util.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-util.spec.ts index 82c9ed413c39ab989f955396a65ae1261a76528b..4501f9dd24a6281055e309eb04f5c211161f2e8e 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-util.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-util.spec.ts @@ -21,26 +21,26 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Vorgang } from "@alfa-client/vorgang-shared"; -import { createVorgangResource } from "libs/vorgang-shared/test/vorgang"; +import { Vorgang } from '@alfa-client/vorgang-shared'; +import { createVorgangResource } from 'libs/vorgang-shared/test/vorgang'; import { getAktenzeichenText, VORGANG_KEIN_AKTENZEICHEN_ZUGEWIESEN } from './vorgang-util'; describe('Vorgang Util', () => { - describe('getAktenzeichenText', () => { - it('should return Aktenzeichen if Vorgang does contain one', () => { - const vorgang: Vorgang = createVorgangResource(); + describe('getAktenzeichenText', () => { + it('should return Aktenzeichen if Vorgang does contain one', () => { + const vorgang: Vorgang = createVorgangResource(); - const result: string = getAktenzeichenText(vorgang); + const result: string = getAktenzeichenText(vorgang); - expect(result).toEqual(vorgang.aktenzeichen); - }) + expect(result).toEqual(vorgang.aktenzeichen); + }); - it('should return default text if Vorgang does not contain a Aktenzeichen', () => { - const vorgang: Vorgang = { ...createVorgangResource(), aktenzeichen: null } + it('should return default text if Vorgang does not contain a Aktenzeichen', () => { + const vorgang: Vorgang = { ...createVorgangResource(), aktenzeichen: null }; - const result: string = getAktenzeichenText(vorgang); + const result: string = getAktenzeichenText(vorgang); - expect(result).toEqual(VORGANG_KEIN_AKTENZEICHEN_ZUGEWIESEN); - }) - }) + expect(result).toEqual(VORGANG_KEIN_AKTENZEICHEN_ZUGEWIESEN); + }); + }); }); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-util.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-util.ts index 3f6d94d69827013b000156f8996e06e24b324439..97b7913c19a9f5b76b209c105dcb9934a797ff52 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-util.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/vorgang-util.ts @@ -21,10 +21,10 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { Vorgang } from "@alfa-client/vorgang-shared"; +import { Vorgang } from '@alfa-client/vorgang-shared'; export const VORGANG_KEIN_AKTENZEICHEN_ZUGEWIESEN = 'kein Aktenzeichen'; export function getAktenzeichenText(vorgang: Vorgang): string { - return vorgang.aktenzeichen || VORGANG_KEIN_AKTENZEICHEN_ZUGEWIESEN; + return vorgang.aktenzeichen || VORGANG_KEIN_AKTENZEICHEN_ZUGEWIESEN; } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.html b/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.html index 9a24c31d3907979c0dcf2f266d2d274ebc2bcae1..5e95367c03a46c38103869483604b2442dc0fa7b 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.html +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.html @@ -1,8 +1,11 @@ <div [class.red]="isOverdue" data-test-class="wiedervorlage-icon"> - <ng-container *ngIf="isOverdue; else defaultFrist"> - <ozgcloud-svgicon svgIcon="resubmission_expired" data-test-class="wiedervorlage-icon-is-overdue"></ozgcloud-svgicon> - </ng-container> - <ng-template #defaultFrist> - <ozgcloud-icon icon="update" data-test-class="wiedervorlage-icon-default"></ozgcloud-icon> - </ng-template> + <ng-container *ngIf="isOverdue; else defaultFrist"> + <ozgcloud-svgicon + svgIcon="resubmission_expired" + data-test-class="wiedervorlage-icon-is-overdue" + ></ozgcloud-svgicon> + </ng-container> + <ng-template #defaultFrist> + <ozgcloud-icon icon="update" data-test-class="wiedervorlage-icon-default"></ozgcloud-icon> + </ng-template> </div> diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.scss b/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.scss index e9b32dfa21a07253e91681e70396dd7c94d2e2ca..9315d4d7758a4c1fcfe23122a58d1d7059d8b257 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.scss +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.scss @@ -3,14 +3,14 @@ @import 'variables'; :host { - margin-right: 6px; - height: $iconHeight; + margin-right: 6px; + height: $iconHeight; } .red { - color: mat.get-color-from-palette($warnPalette, darker); + color: mat.get-color-from-palette($warnPalette, darker); } body.dark :host .red { - color: red; + color: red; } diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.spec.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.spec.ts index efd24b921483da9f0cac19ea83931cc1c1753e26..c1dba5f8827ad6ed7dbf45c573db6e07eb205d21 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.spec.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.spec.ts @@ -8,71 +8,68 @@ import { MockComponents } from 'ng-mocks'; import { WiedervorlageIconComponent } from './wiedervorlage-icon.component'; describe('WiedervorlageIconComponent', () => { - let component: WiedervorlageIconComponent; - let fixture: ComponentFixture<WiedervorlageIconComponent>; + let component: WiedervorlageIconComponent; + let fixture: ComponentFixture<WiedervorlageIconComponent>; - const wiedervorlageIconIsOverdue: string = getDataTestClassOf('wiedervorlage-icon-is-overdue'); - const wiedervorlageIconDefault: string = getDataTestClassOf('wiedervorlage-icon-default'); + const wiedervorlageIconIsOverdue: string = getDataTestClassOf('wiedervorlage-icon-is-overdue'); + const wiedervorlageIconDefault: string = getDataTestClassOf('wiedervorlage-icon-default'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageIconComponent, - MatIcon, - MockComponents(OzgcloudIconComponent), - MockComponents(OzgcloudSvgIconComponent), - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageIconComponent, + MatIcon, + MockComponents(OzgcloudIconComponent), + MockComponents(OzgcloudSvgIconComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(WiedervorlageIconComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(WiedervorlageIconComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('Create default Wiedervorlage Icon', () => { + describe('Create default Wiedervorlage Icon', () => { + it('should show icon', () => { + component.isOverdue = false; - it('should show icon', () => { - component.isOverdue = false; + fixture.detectChanges(); + const element = getElementFromFixture(fixture, wiedervorlageIconDefault); - fixture.detectChanges(); - const element = getElementFromFixture(fixture, wiedervorlageIconDefault); + expect(element).toBeInstanceOf(HTMLElement); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) + it('should not show icon', () => { + component.isOverdue = true; - it('should not show icon', () => { - component.isOverdue = true; + fixture.detectChanges(); + const element = getElementFromFixture(fixture, wiedervorlageIconDefault); - fixture.detectChanges(); - const element = getElementFromFixture(fixture, wiedervorlageIconDefault); + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) + describe('Create overdue Wiedervorlage Icon', () => { + it('should show icon', () => { + component.isOverdue = true; - describe('Create overdue Wiedervorlage Icon', () => { + fixture.detectChanges(); + const element = getElementFromFixture(fixture, wiedervorlageIconIsOverdue); - it('should show icon', () => { - component.isOverdue = true; + expect(element).toBeInstanceOf(HTMLElement); + }); - fixture.detectChanges(); - const element = getElementFromFixture(fixture, wiedervorlageIconIsOverdue); + it('should not show icon', () => { + component.isOverdue = false; - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should not show icon', () => { - component.isOverdue = false; - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, wiedervorlageIconIsOverdue); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) + fixture.detectChanges(); + const element = getElementFromFixture(fixture, wiedervorlageIconIsOverdue); + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.ts b/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.ts index 54397d8d60a725f74f29ed80503b6639fca52638..0296815dae93170b5f862ea6cfbb586ed7df3ba6 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component.ts @@ -1,12 +1,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'alfa-wiedervorlage-icon', - templateUrl: './wiedervorlage-icon.component.html', - styleUrls: ['./wiedervorlage-icon.component.scss'], + selector: 'alfa-wiedervorlage-icon', + templateUrl: './wiedervorlage-icon.component.html', + styleUrls: ['./wiedervorlage-icon.component.scss'], }) export class WiedervorlageIconComponent { - - @Input() isOverdue: boolean; - + @Input() isOverdue: boolean; } diff --git a/alfa-client/libs/vorgang-shared-ui/src/test-setup.ts b/alfa-client/libs/vorgang-shared-ui/src/test-setup.ts index 5870fdabb6470fd0f6f3f63be3d4f6b8041b4dd2..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/vorgang-shared-ui/src/test-setup.ts +++ b/alfa-client/libs/vorgang-shared-ui/src/test-setup.ts @@ -26,17 +26,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/vorgang-shared-ui/tsconfig.json b/alfa-client/libs/vorgang-shared-ui/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/vorgang-shared-ui/tsconfig.json +++ b/alfa-client/libs/vorgang-shared-ui/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/vorgang-shared-ui/tsconfig.lib.json b/alfa-client/libs/vorgang-shared-ui/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/vorgang-shared-ui/tsconfig.lib.json +++ b/alfa-client/libs/vorgang-shared-ui/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/vorgang-shared-ui/tsconfig.spec.json b/alfa-client/libs/vorgang-shared-ui/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/vorgang-shared-ui/tsconfig.spec.json +++ b/alfa-client/libs/vorgang-shared-ui/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/vorgang-shared/.eslintrc.json b/alfa-client/libs/vorgang-shared/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/vorgang-shared/.eslintrc.json +++ b/alfa-client/libs/vorgang-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/vorgang-shared/jest.config.ts b/alfa-client/libs/vorgang-shared/jest.config.ts index 6b23df5d549e6339b61b5de670f5fbf957c9230c..8ab3257e896ddd85d192f979bce18e61169da5e0 100644 --- a/alfa-client/libs/vorgang-shared/jest.config.ts +++ b/alfa-client/libs/vorgang-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'vorgang-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/vorgang-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'vorgang-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/vorgang-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/vorgang-shared/project.json b/alfa-client/libs/vorgang-shared/project.json index 92486f05589488dd331e49ef8ae63992ca0dd7e5..7bd62acdb0b35f72d63f76ee0af3a4af6e8829e0 100644 --- a/alfa-client/libs/vorgang-shared/project.json +++ b/alfa-client/libs/vorgang-shared/project.json @@ -1,34 +1,31 @@ { - "name": "vorgang-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/vorgang-shared/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/vorgang-shared/src/**/*.ts", - "libs/vorgang-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/vorgang-shared/tsconfig.spec.json", - "jestConfig": "libs/vorgang-shared/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/vorgang-shared"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "vorgang-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/vorgang-shared/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/vorgang-shared/src/**/*.ts", "libs/vorgang-shared/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/vorgang-shared/tsconfig.spec.json", + "jestConfig": "libs/vorgang-shared/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/vorgang-shared"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/vorgang-shared/src/index.ts b/alfa-client/libs/vorgang-shared/src/index.ts index c5f2dabe2b15a65268f0cc1582fea45d7768af8d..1e66ab91caa7a1bc847e66c603d75d14c993ef42 100644 --- a/alfa-client/libs/vorgang-shared/src/index.ts +++ b/alfa-client/libs/vorgang-shared/src/index.ts @@ -31,4 +31,3 @@ export * from './lib/vorgang.messages'; export * from './lib/vorgang.model'; export * from './lib/vorgang.service'; export * from './lib/vorgang.util'; - diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.actions.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.actions.ts index 12b5b07fb57f3e856c396867ed4b60ce243e6836..7943943ea5374f6901e8ed07c2631af3f23f90c6 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.actions.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.actions.ts @@ -24,97 +24,180 @@ import { HttpErrorResponse } from '@angular/common/http'; import { ApiRootResource } from '@alfa-client/api-root-shared'; import { LoadBinaryFileListSuccessProps } from '@alfa-client/binary-file-shared'; -import { CommandStateResourceProps, LoadCommandListSuccessProps } from '@alfa-client/command-shared'; -import { ApiErrorAction, ResourceUriProps, TypedActionCreator, TypedActionCreatorWithProps } from '@alfa-client/tech-shared'; +import { + CommandStateResourceProps, + LoadCommandListSuccessProps, +} from '@alfa-client/command-shared'; +import { + ApiErrorAction, + ResourceUriProps, + TypedActionCreator, + TypedActionCreatorWithProps, +} from '@alfa-client/tech-shared'; import { createAction, props } from '@ngrx/store'; -import { AdditionalActions, VorgangListResource, VorgangWithEingangResource } from '../vorgang.model'; +import { + AdditionalActions, + VorgangListResource, + VorgangWithEingangResource, +} from '../vorgang.model'; export interface SearchVorgaengeByProps { - apiRoot: ApiRootResource, - searchString: string, - linkRel: string + apiRoot: ApiRootResource; + searchString: string; + linkRel: string; } export interface StringBasedProps { - string: string + string: string; } export interface ApiRootAction { - apiRoot: ApiRootResource, + apiRoot: ApiRootResource; } export interface ApiRootWithLinkRelProps { - apiRoot: ApiRootResource, - linkRel: string + apiRoot: ApiRootResource; + linkRel: string; } export interface HttpErrorAction { - httpErrorResponse: HttpErrorResponse + httpErrorResponse: HttpErrorResponse; } export interface VorgangListAction { - vorgangList: VorgangListResource + vorgangList: VorgangListResource; } export interface VorgangWithEingangAction { - vorgangWithEingang: VorgangWithEingangResource + vorgangWithEingang: VorgangWithEingangResource; } export interface VorgangUriWithContextProps extends ResourceUriProps { - additionalActions?: AdditionalActions + additionalActions?: AdditionalActions; } //VorgangList export const noOperation: TypedActionCreator = createAction('[Vorgang-Routing] No Operation'); -export const loadVorgangList: TypedActionCreatorWithProps<ApiRootWithLinkRelProps> = createAction('[Vorgang] Load VorgangList', props<ApiRootWithLinkRelProps>()); -export const loadVorgangListSuccess: TypedActionCreatorWithProps<VorgangListAction> = createAction('[Vorgang] Load VorgangList Success', props<VorgangListAction>()); -export const loadVorgangListFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Vorgang] Load VorgangList Failure', props<ApiErrorAction>()); - -export const searchVorgaengeBy: TypedActionCreatorWithProps<SearchVorgaengeByProps> = createAction('[Vorgang] Search VorgangList', props<SearchVorgaengeByProps>()); -export const searchVorgaengeBySuccess: TypedActionCreatorWithProps<VorgangListAction> = createAction('[Vorgang] Search VorgangList Success', props<VorgangListAction>()); -export const searchVorgaengeByFailure: TypedActionCreatorWithProps<HttpErrorAction> = createAction('[Vorgang] Search VorgangList Failure', props<HttpErrorAction>()); - -export const loadNextPage: TypedActionCreator = createAction('[Vorgang] Load next VorgangList page'); -export const loadNextPageSuccess: TypedActionCreatorWithProps<VorgangListAction> = createAction('[Vorgang] Load next VorgangList page Success', props<VorgangListAction>()); +export const loadVorgangList: TypedActionCreatorWithProps<ApiRootWithLinkRelProps> = createAction( + '[Vorgang] Load VorgangList', + props<ApiRootWithLinkRelProps>(), +); +export const loadVorgangListSuccess: TypedActionCreatorWithProps<VorgangListAction> = createAction( + '[Vorgang] Load VorgangList Success', + props<VorgangListAction>(), +); +export const loadVorgangListFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[Vorgang] Load VorgangList Failure', + props<ApiErrorAction>(), +); + +export const searchVorgaengeBy: TypedActionCreatorWithProps<SearchVorgaengeByProps> = createAction( + '[Vorgang] Search VorgangList', + props<SearchVorgaengeByProps>(), +); +export const searchVorgaengeBySuccess: TypedActionCreatorWithProps<VorgangListAction> = + createAction('[Vorgang] Search VorgangList Success', props<VorgangListAction>()); +export const searchVorgaengeByFailure: TypedActionCreatorWithProps<HttpErrorAction> = createAction( + '[Vorgang] Search VorgangList Failure', + props<HttpErrorAction>(), +); + +export const loadNextPage: TypedActionCreator = createAction( + '[Vorgang] Load next VorgangList page', +); +export const loadNextPageSuccess: TypedActionCreatorWithProps<VorgangListAction> = createAction( + '[Vorgang] Load next VorgangList page Success', + props<VorgangListAction>(), +); //Search -export const searchForPreview: TypedActionCreatorWithProps<StringBasedProps> = createAction('[Vorgang] Search for preview', props<StringBasedProps>()); -export const searchForPreviewSuccess: TypedActionCreatorWithProps<VorgangListAction> = createAction('[Vorgang] Search for preview Success', props<VorgangListAction>()); -export const searchForPreviewFailure: TypedActionCreatorWithProps<HttpErrorAction> = createAction('[Vorgang] Search for preview Failure', props<HttpErrorAction>()); - -export const clearSearchPreviewList: TypedActionCreator = createAction('[Vorgang] Clear search preview list'); +export const searchForPreview: TypedActionCreatorWithProps<StringBasedProps> = createAction( + '[Vorgang] Search for preview', + props<StringBasedProps>(), +); +export const searchForPreviewSuccess: TypedActionCreatorWithProps<VorgangListAction> = createAction( + '[Vorgang] Search for preview Success', + props<VorgangListAction>(), +); +export const searchForPreviewFailure: TypedActionCreatorWithProps<HttpErrorAction> = createAction( + '[Vorgang] Search for preview Failure', + props<HttpErrorAction>(), +); + +export const clearSearchPreviewList: TypedActionCreator = createAction( + '[Vorgang] Clear search preview list', +); export const clearSearchString: TypedActionCreator = createAction('[Vorgang] Clear search string'); -export const setSearchString: TypedActionCreatorWithProps<StringBasedProps> = createAction('[Vorgang] Set search string', props<StringBasedProps>()); +export const setSearchString: TypedActionCreatorWithProps<StringBasedProps> = createAction( + '[Vorgang] Set search string', + props<StringBasedProps>(), +); //VorgangWithEingang -export const loadVorgangWithEingang: TypedActionCreatorWithProps<VorgangUriWithContextProps> = createAction('[Vorgang] Load VorgangWithEingang', props<VorgangUriWithContextProps>()); -export const loadVorgangWithEingangSuccess: TypedActionCreatorWithProps<VorgangWithEingangAction> = createAction('[Vorgang] Load VorgangWithEingang Success', props<VorgangWithEingangAction>()); -export const loadVorgangWithEingangFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Vorgang] Load VorgangWithEingang Failure', props<ApiErrorAction>()); - -export const clearVorgangWithEingang: TypedActionCreator = createAction('[Vorgang] Clear VorgangWithEingang'); -export const setReloadVorgangWithEingang: TypedActionCreator = createAction('[Vorgang] Set reload at VorgangWithEingang'); - -export const loadPendingCommandList: TypedActionCreatorWithProps<VorgangWithEingangAction> = createAction('[Vorgang] Load pending command list', props<VorgangWithEingangAction>()); -export const loadPendingCommandListSuccess: TypedActionCreatorWithProps<LoadCommandListSuccessProps> = createAction('[Vorgang/API] Load pending command list Success', props<LoadCommandListSuccessProps>()); -export const loadPendingCommandListFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Vorgang/API] Load pending command list Failure', props<ApiErrorAction>()); - -export const loadAttachmentList: TypedActionCreatorWithProps<VorgangWithEingangAction> = createAction('[Vorgang] Load AttachmentList', props<VorgangWithEingangAction>()); -export const loadAttachmentListSuccess: TypedActionCreatorWithProps<LoadBinaryFileListSuccessProps> = createAction('[Vorgang] Load AttachmentList Success', props<LoadBinaryFileListSuccessProps>()); -export const loadAttachmentListFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Vorgang] Load AttachmentList Failure', props<ApiErrorAction>()); - -export const loadRepresentationList: TypedActionCreatorWithProps<VorgangWithEingangAction> = createAction('[Vorgang] Load RepresentationList', props<VorgangWithEingangAction>()); -export const loadRepresentationListSuccess: TypedActionCreatorWithProps<LoadBinaryFileListSuccessProps> = createAction('[Vorgang] Load RepresentationList Success', props<LoadBinaryFileListSuccessProps>()); -export const loadRepresentationListFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Vorgang] Load RepresentationList Failure', props<ApiErrorAction>()); - -export const setForwardingSingleCommand: TypedActionCreatorWithProps<CommandStateResourceProps> = createAction('[Vorgang] Set forward command', props<CommandStateResourceProps>()); -export const setForwardingSingleCommandLoading: TypedActionCreator = createAction('[Vorgang] Set forward command loading'); -export const setSendPostfachNachrichtSingleCommand: TypedActionCreatorWithProps<CommandStateResourceProps> = createAction('[Vorgang] Set send postfach nachricht command', props<CommandStateResourceProps>()); -export const setSendPostfachNachrichtSingleCommandLoading: TypedActionCreator = createAction('[Vorgang] Set send postfach nachricht command loading'); +export const loadVorgangWithEingang: TypedActionCreatorWithProps<VorgangUriWithContextProps> = + createAction('[Vorgang] Load VorgangWithEingang', props<VorgangUriWithContextProps>()); +export const loadVorgangWithEingangSuccess: TypedActionCreatorWithProps<VorgangWithEingangAction> = + createAction('[Vorgang] Load VorgangWithEingang Success', props<VorgangWithEingangAction>()); +export const loadVorgangWithEingangFailure: TypedActionCreatorWithProps<ApiErrorAction> = + createAction('[Vorgang] Load VorgangWithEingang Failure', props<ApiErrorAction>()); + +export const clearVorgangWithEingang: TypedActionCreator = createAction( + '[Vorgang] Clear VorgangWithEingang', +); +export const setReloadVorgangWithEingang: TypedActionCreator = createAction( + '[Vorgang] Set reload at VorgangWithEingang', +); + +export const loadPendingCommandList: TypedActionCreatorWithProps<VorgangWithEingangAction> = + createAction('[Vorgang] Load pending command list', props<VorgangWithEingangAction>()); +export const loadPendingCommandListSuccess: TypedActionCreatorWithProps<LoadCommandListSuccessProps> = + createAction( + '[Vorgang/API] Load pending command list Success', + props<LoadCommandListSuccessProps>(), + ); +export const loadPendingCommandListFailure: TypedActionCreatorWithProps<ApiErrorAction> = + createAction('[Vorgang/API] Load pending command list Failure', props<ApiErrorAction>()); + +export const loadAttachmentList: TypedActionCreatorWithProps<VorgangWithEingangAction> = + createAction('[Vorgang] Load AttachmentList', props<VorgangWithEingangAction>()); +export const loadAttachmentListSuccess: TypedActionCreatorWithProps<LoadBinaryFileListSuccessProps> = + createAction('[Vorgang] Load AttachmentList Success', props<LoadBinaryFileListSuccessProps>()); +export const loadAttachmentListFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[Vorgang] Load AttachmentList Failure', + props<ApiErrorAction>(), +); + +export const loadRepresentationList: TypedActionCreatorWithProps<VorgangWithEingangAction> = + createAction('[Vorgang] Load RepresentationList', props<VorgangWithEingangAction>()); +export const loadRepresentationListSuccess: TypedActionCreatorWithProps<LoadBinaryFileListSuccessProps> = + createAction( + '[Vorgang] Load RepresentationList Success', + props<LoadBinaryFileListSuccessProps>(), + ); +export const loadRepresentationListFailure: TypedActionCreatorWithProps<ApiErrorAction> = + createAction('[Vorgang] Load RepresentationList Failure', props<ApiErrorAction>()); + +export const setForwardingSingleCommand: TypedActionCreatorWithProps<CommandStateResourceProps> = + createAction('[Vorgang] Set forward command', props<CommandStateResourceProps>()); +export const setForwardingSingleCommandLoading: TypedActionCreator = createAction( + '[Vorgang] Set forward command loading', +); +export const setSendPostfachNachrichtSingleCommand: TypedActionCreatorWithProps<CommandStateResourceProps> = + createAction('[Vorgang] Set send postfach nachricht command', props<CommandStateResourceProps>()); +export const setSendPostfachNachrichtSingleCommandLoading: TypedActionCreator = createAction( + '[Vorgang] Set send postfach nachricht command loading', +); export const initAssignUser: TypedActionCreator = createAction('[Vorgang] Init Assign user'); -export const exportVorgang: TypedActionCreatorWithProps<VorgangWithEingangAction> = createAction('[Vorgang] Export', props<VorgangWithEingangAction>()); +export const exportVorgang: TypedActionCreatorWithProps<VorgangWithEingangAction> = createAction( + '[Vorgang] Export', + props<VorgangWithEingangAction>(), +); export const exportVorgangSuccess: TypedActionCreator = createAction('[Vorgang] Export Success'); -export const exportVorgangFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction('[Vorgang] Export Failure', props<ApiErrorAction>()); \ No newline at end of file +export const exportVorgangFailure: TypedActionCreatorWithProps<ApiErrorAction> = createAction( + '[Vorgang] Export Failure', + props<ApiErrorAction>(), +); diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.spec.ts index 72a73a1e338e2ddea2aef7f82cd97a8aa769b731..1dd8d8cca1a93bdf31b319e22724246209d6a166 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.spec.ts @@ -24,8 +24,16 @@ import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; import { ApiRootFacade, ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; -import { BinaryFileListResource, LoadBinaryFileListProps, loadBinaryFileList } from '@alfa-client/binary-file-shared'; -import { CommandListResource, LoadCommandListProps, loadCommandList } from '@alfa-client/command-shared'; +import { + BinaryFileListResource, + LoadBinaryFileListProps, + loadBinaryFileList, +} from '@alfa-client/binary-file-shared'; +import { + CommandListResource, + LoadCommandListProps, + loadCommandList, +} from '@alfa-client/command-shared'; import { ApiError, BlobWithFileName, createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; import { SnackBarService } from '@alfa-client/ui'; @@ -40,11 +48,19 @@ import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { createBinaryFileListResource } from 'libs/binary-file-shared/test/binary-file'; import { createCommandListResource } from 'libs/command-shared/test/command'; import { createApiError, createHttpErrorResponse } from 'libs/tech-shared/test/error'; -import { createVorgangListResource, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; +import { + createVorgangListResource, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; import { Observable, of } from 'rxjs'; import { DUMMY_ACTION } from '../../../../tech-shared/test/ngrx'; import { VorgangWithEingangLinkRel } from '../vorgang.linkrel'; -import { AdditionalActions, VorgangFilter, VorgangListResource, VorgangWithEingangResource } from '../vorgang.model'; +import { + AdditionalActions, + VorgangFilter, + VorgangListResource, + VorgangWithEingangResource, +} from '../vorgang.model'; import { VorgangEffects } from './vorgang.effects'; import { VorgangFacade } from './vorgang.facade'; import { VorgangRepository } from './vorgang.repository'; @@ -56,539 +72,576 @@ import * as VorgangActions from './vorgang.actions'; import * as VorgangSelectors from './vorgang.selectors'; describe('VorgangEffects', () => { - let actions: Observable<Action>; - let effects: VorgangEffects; - let store: MockStore; - - const apiRootFacade = mock(ApiRootFacade); - const vorgangRepository = mock(VorgangRepository); - const vorgangFacade = mock(VorgangFacade); - const snackbarService = mock(SnackBarService); - - const vorgangList: VorgangListResource = createVorgangListResource(); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - VorgangEffects, - provideMockActions(() => actions), - provideMockStore(), - { - provide: ApiRootFacade, - useValue: apiRootFacade - }, - { - provide: VorgangRepository, - useValue: vorgangRepository - }, - { - provide: VorgangFacade, - useValue: vorgangFacade - }, - { - provide: SnackBarService, - useValue: snackbarService - } - ] - }); + let actions: Observable<Action>; + let effects: VorgangEffects; + let store: MockStore; + + const apiRootFacade = mock(ApiRootFacade); + const vorgangRepository = mock(VorgangRepository); + const vorgangFacade = mock(VorgangFacade); + const snackbarService = mock(SnackBarService); + + const vorgangList: VorgangListResource = createVorgangListResource(); + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + VorgangEffects, + provideMockActions(() => actions), + provideMockStore(), + { + provide: ApiRootFacade, + useValue: apiRootFacade, + }, + { + provide: VorgangRepository, + useValue: vorgangRepository, + }, + { + provide: VorgangFacade, + useValue: vorgangFacade, + }, + { + provide: SnackBarService, + useValue: snackbarService, + }, + ], + }); + + effects = TestBed.inject(VorgangEffects); + + store = TestBed.inject(MockStore); + store.overrideSelector(VorgangSelectors.vorgangList, createStateResource(vorgangList)); + }); + + describe('loadVorgangList', () => { + const vorgangList: VorgangListResource = createVorgangListResource(); + const apiRoot: ApiRootResource = createApiRootResource(); + const linkRel: string = 'dummyLinkRel'; + const action = VorgangActions.loadVorgangList({ apiRoot, linkRel }); + + it('should call repository', () => { + actions = of(action); + + effects.loadVorgangList$.subscribe(); + + expect(vorgangRepository.loadVorgangList).toHaveBeenCalledWith(apiRoot, linkRel); + }); + + it('should dispatch loadVorgangListSuccess action', () => { + vorgangRepository.loadVorgangList.mockReturnValue(of(vorgangList)); + + actions = hot('-a-|', { a: action }); + + const expected = hot('-a-|', { a: VorgangActions.loadVorgangListSuccess({ vorgangList }) }); + expect(effects.loadVorgangList$).toBeObservable(expected); + }); + + it('should dispatch loadVorgangListFailure action', () => { + const apiError: ApiError = createApiError(); + const error = { error: { error: apiError } }; + const errorResponse = cold('-#', {}, error); + vorgangRepository.loadVorgangList = jest.fn(() => errorResponse); + + const expected = cold('--b', { b: VorgangActions.loadVorgangListFailure({ apiError }) }); + actions = hot('-a', { a: action }); + + expect(effects.loadVorgangList$).toBeObservable(expected); + }); + }); + + describe('searchVorgaengeBy', () => { + const apiRoot: ApiRootResource = createApiRootResource(); + const searchString: string = 'search like me'; + const linkRel: string = 'linkRelationName'; + const action = VorgangActions.searchVorgaengeBy({ apiRoot, searchString, linkRel }); + + it('should call repository', () => { + actions = of(action); + + effects.searchVorgaengeBy$.subscribe(); + + expect(vorgangRepository.searchVorgaengeBy).toHaveBeenCalledWith( + apiRoot, + searchString, + linkRel, + ); + }); + + it('should dispatch searchVorgaengeBySuccess action', () => { + vorgangRepository.searchVorgaengeBy.mockReturnValue(of(vorgangList)); + + actions = hot('-a-|', { a: action }); + + const expected = hot('-a-|', { a: VorgangActions.searchVorgaengeBySuccess({ vorgangList }) }); + expect(effects.searchVorgaengeBy$).toBeObservable(expected); + }); + + it('should dispatch searchVorgaengeByFailure action', () => { + const error: HttpErrorResponse = createHttpErrorResponse(); + const errorResponse = cold('-#', {}, error); + vorgangRepository.searchVorgaengeBy = jest.fn(() => errorResponse); - effects = TestBed.inject(VorgangEffects); + const expected = cold('--b', { + b: VorgangActions.searchVorgaengeByFailure({ httpErrorResponse: error }), + }); + actions = hot('-a', { a: action }); - store = TestBed.inject(MockStore); - store.overrideSelector(VorgangSelectors.vorgangList, createStateResource(vorgangList)); - }); + expect(effects.searchVorgaengeBy$).toBeObservable(expected); + }); + }); - describe('loadVorgangList', () => { + describe('loadNextPage', () => { + const action = VorgangActions.loadNextPage(); - const vorgangList: VorgangListResource = createVorgangListResource(); - const apiRoot: ApiRootResource = createApiRootResource(); - const linkRel: string = 'dummyLinkRel'; - const action = VorgangActions.loadVorgangList({ apiRoot, linkRel }); + it('should select vorgangList from store', () => { + store.select = jest.fn(); + actions = of(action); - it('should call repository', () => { - actions = of(action); + effects.loadNextPage$.subscribe(); - effects.loadVorgangList$.subscribe(); + expect(store.select).toHaveBeenCalledWith(VorgangSelectors.vorgangList); + }); - expect(vorgangRepository.loadVorgangList).toHaveBeenCalledWith(apiRoot, linkRel); - }) + it('should call vorgang repository', () => { + actions = of(action); - it('should dispatch loadVorgangListSuccess action', () => { - vorgangRepository.loadVorgangList.mockReturnValue(of(vorgangList)); + effects.loadNextPage$.subscribe(); - actions = hot('-a-|', { a: action }); + expect(vorgangRepository.getNextVorgangListPage).toHaveBeenCalledWith(vorgangList); + }); - const expected = hot('-a-|', { a: VorgangActions.loadVorgangListSuccess({ vorgangList }) }); - expect(effects.loadVorgangList$).toBeObservable(expected); - }) + it('should dispatch loadNextPageSuccess action', () => { + vorgangRepository.getNextVorgangListPage.mockReturnValue(of(vorgangList)); - it('should dispatch loadVorgangListFailure action', () => { - const apiError: ApiError = createApiError() - const error = { error: { error: apiError } }; - const errorResponse = cold('-#', {}, error); - vorgangRepository.loadVorgangList = jest.fn(() => errorResponse); + actions = hot('-a-|', { a: action }); - const expected = cold('--b', { b: VorgangActions.loadVorgangListFailure({ apiError }) }); - actions = hot('-a', { a: action }); + const expected = hot('-a-|', { a: VorgangActions.loadNextPageSuccess({ vorgangList }) }); + expect(effects.loadNextPage$).toBeObservable(expected); + }); - expect(effects.loadVorgangList$).toBeObservable(expected); - }) - }) + it('should dispatch loadVorgangListFailure action', () => { + const apiError: ApiError = createApiError(); + const error = { error: { error: apiError } }; + const errorResponse = cold('-#', {}, error); + vorgangRepository.getNextVorgangListPage = jest.fn(() => errorResponse); - describe('searchVorgaengeBy', () => { + const expected = cold('--c', { c: VorgangActions.loadVorgangListFailure({ apiError }) }); + actions = hot('-a', { a: action }); - const apiRoot: ApiRootResource = createApiRootResource(); - const searchString: string = 'search like me'; - const linkRel: string = 'linkRelationName'; - const action = VorgangActions.searchVorgaengeBy({ apiRoot, searchString, linkRel }); + expect(effects.loadNextPage$).toBeObservable(expected); + }); + }); - it('should call repository', () => { - actions = of(action); + describe('searchForPreview', () => { + const vorgangList: VorgangListResource = createVorgangListResource(); + const apiRoot: ApiRootResource = createApiRootResource(); + const searchString: string = 'searchThisForMe'; + const linkRel: string = ApiRootLinkRel.SEARCH_ALLE; + const limit: number = 7; + const action = VorgangActions.searchForPreview({ string: searchString }); - effects.searchVorgaengeBy$.subscribe(); + beforeEach(() => { + vorgangFacade.getVorgangFilter.mockReturnValue(of(VorgangFilter.ALLE)); + apiRootFacade.getApiRoot.mockReturnValue(of(createStateResource(apiRoot))); + }); - expect(vorgangRepository.searchVorgaengeBy).toHaveBeenCalledWith(apiRoot, searchString, linkRel); - }) + it('should call vorgang repository', () => { + actions = of(action); - it('should dispatch searchVorgaengeBySuccess action', () => { - vorgangRepository.searchVorgaengeBy.mockReturnValue(of(vorgangList)); + effects.searchForPreview$.subscribe(); - actions = hot('-a-|', { a: action }); + expect(vorgangRepository.searchVorgaengeBy).toHaveBeenCalledWith( + apiRoot, + searchString, + linkRel, + limit, + ); + }); - const expected = hot('-a-|', { a: VorgangActions.searchVorgaengeBySuccess({ vorgangList }) }); - expect(effects.searchVorgaengeBy$).toBeObservable(expected); - }) + it('should call apiRootFacade getApiRoot', () => { + actions = of(action); - it('should dispatch searchVorgaengeByFailure action', () => { - const error: HttpErrorResponse = createHttpErrorResponse(); - const errorResponse = cold('-#', {}, error); - vorgangRepository.searchVorgaengeBy = jest.fn(() => errorResponse); + effects.searchForPreview$.subscribe(); - const expected = cold('--b', { b: VorgangActions.searchVorgaengeByFailure({ httpErrorResponse: error }) }); - actions = hot('-a', { a: action }); + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }); - expect(effects.searchVorgaengeBy$).toBeObservable(expected); - }) - }) + it('should call vorgangFacade getVorgangFilter', () => { + actions = of(action); - describe('loadNextPage', () => { + effects.searchForPreview$.subscribe(); - const action = VorgangActions.loadNextPage(); + expect(vorgangFacade.getVorgangFilter).toHaveBeenCalled(); + }); - it('should select vorgangList from store', () => { - store.select = jest.fn(); - actions = of(action); + it('should dispatch searchForPreviewSuccess action', () => { + vorgangRepository.searchVorgaengeBy.mockReturnValue(of(vorgangList)); - effects.loadNextPage$.subscribe(); + actions = hot('-a-|', { a: action }); - expect(store.select).toHaveBeenCalledWith(VorgangSelectors.vorgangList); - }) + const expected = hot('-a-|', { a: VorgangActions.searchForPreviewSuccess({ vorgangList }) }); + expect(effects.searchForPreview$).toBeObservable(expected); + }); - it('should call vorgang repository', () => { - actions = of(action); + it('should dispatch searchForPreviewFailure action', () => { + const error: HttpErrorResponse = createHttpErrorResponse(); + const errorResponse = cold('-#', {}, error); + vorgangRepository.searchVorgaengeBy = jest.fn(() => errorResponse); - effects.loadNextPage$.subscribe(); + const expected = cold('--c', { + c: VorgangActions.searchForPreviewFailure({ httpErrorResponse: error }), + }); + actions = hot('-a', { a: action }); - expect(vorgangRepository.getNextVorgangListPage).toHaveBeenCalledWith(vorgangList); - }) + expect(effects.searchForPreview$).toBeObservable(expected); + }); + }); - it('should dispatch loadNextPageSuccess action', () => { - vorgangRepository.getNextVorgangListPage.mockReturnValue(of(vorgangList)); + describe('search error', () => { + const action = VorgangActions.searchForPreviewFailure({ httpErrorResponse: null }); + const error: HttpErrorResponse = createHttpErrorResponse(); - actions = hot('-a-|', { a: action }); + it('should trigger showSearchError$', () => { + actions = of(action); + effects.showSearchError = jest.fn(); - const expected = hot('-a-|', { a: VorgangActions.loadNextPageSuccess({ vorgangList }) }); - expect(effects.loadNextPage$).toBeObservable(expected); - }) + effects.showSearchError$.subscribe(); - it('should dispatch loadVorgangListFailure action', () => { - const apiError: ApiError = createApiError() - const error = { error: { error: apiError } }; - const errorResponse = cold('-#', {}, error); - vorgangRepository.getNextVorgangListPage = jest.fn(() => errorResponse); + expect(effects.showSearchError).toHaveBeenCalled(); + }); + + it('should call snackbarService.showError if HTTP status code is NOT 503 ', () => { + error.error.status = HttpStatusCode.ExpectationFailed; - const expected = cold('--c', { c: VorgangActions.loadVorgangListFailure({ apiError }) }); - actions = hot('-a', { a: action }); + effects.showSearchError(error); + + expect(snackbarService.showError).not.toHaveBeenCalled(); + }); + + it('should call snackbarService.showError if HTTP status code is 503 ', () => { + error.error.status = HttpStatusCode.ServiceUnavailable; + + effects.showSearchError(error); + + expect(snackbarService.showError).toHaveBeenCalled(); + }); + }); + + //VorgangWithEingang + describe('loadVorgangWithEingang', () => { + const resourceUri: ResourceUri = faker.internet.url(); + const additionalSuccessAction = () => DUMMY_ACTION; + const additionalFailureAction = (error: HttpErrorResponse) => DUMMY_ACTION; + const additionalActions: AdditionalActions = { + additionalSuccessAction, + additionalFailureAction, + }; - expect(effects.loadNextPage$).toBeObservable(expected); - }) - }) + const action: TypedAction<string> = VorgangActions.loadVorgangWithEingang({ resourceUri }); - describe('searchForPreview', () => { + describe('on success', () => { + beforeEach(() => { + vorgangRepository.getVorgang.mockReturnValue(of(vorgangWithEingang)); + }); - const vorgangList: VorgangListResource = createVorgangListResource(); - const apiRoot: ApiRootResource = createApiRootResource(); - const searchString: string = 'searchThisForMe'; - const linkRel: string = ApiRootLinkRel.SEARCH_ALLE; - const limit: number = 7; - const action = VorgangActions.searchForPreview({ string: searchString }); + it('should dispatch action', () => { + actions = hot('-a-|', { a: action }); - beforeEach(() => { - vorgangFacade.getVorgangFilter.mockReturnValue(of(VorgangFilter.ALLE)); - apiRootFacade.getApiRoot.mockReturnValue(of(createStateResource(apiRoot))); - }) + const expected = hot('-a-|', { + a: VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }), + }); + expect(effects.loadVorgangWithEingang$).toBeObservable(expected); + }); - it('should call vorgang repository', () => { - actions = of(action); + it('should handle additional action', () => { + const action: TypedAction<string> = VorgangActions.loadVorgangWithEingang({ + resourceUri, + additionalActions, + }); - effects.searchForPreview$.subscribe(); + actions = hot('-a', { a: action }); - expect(vorgangRepository.searchVorgaengeBy).toHaveBeenCalledWith(apiRoot, searchString, linkRel, limit); - }) + const expected = cold('-(bc)', { + b: VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }), + c: additionalSuccessAction(), + }); + expect(effects.loadVorgangWithEingang$).toBeObservable(expected); + }); + }); - it('should call apiRootFacade getApiRoot', () => { - actions = of(action); + describe('on failure', () => { + const apiError: ApiError = createApiError(); + const error = { error: { error: apiError } }; - effects.searchForPreview$.subscribe(); + beforeEach(() => { + const errorResponse = cold('-#', {}, error); + vorgangRepository.getVorgang = jest.fn(() => errorResponse); + }); + + it('should dispatch action', () => { + actions = hot('-a', { a: action }); + + const expected = cold('--c', { + c: VorgangActions.loadVorgangWithEingangFailure({ apiError }), + }); + expect(effects.loadVorgangWithEingang$).toBeObservable(expected); + }); + + it('should handle additional action', () => { + const action: TypedAction<string> = VorgangActions.loadVorgangWithEingang({ + resourceUri, + additionalActions, + }); + + actions = hot('-a', { a: action }); + + const expected = cold('--(bc)', { + b: VorgangActions.loadVorgangWithEingangFailure({ apiError }), + c: additionalFailureAction(<HttpErrorResponse>error), + }); + expect(effects.loadVorgangWithEingang$).toBeObservable(expected); + }); + }); + }); - expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); - }) + describe('loadVorgangWithEingangSuccess', () => { + it('should dispatch "loadPendingCommandList" action if link exists', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.PENDING_COMMANDS, + ]); + const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); + + actions = hot('-a-|', { a: action }); + + const expected = hot('-a-|', { + a: VorgangActions.loadPendingCommandList({ vorgangWithEingang }), + }); + expect(effects.loadVorgangWithEingangSuccess$).toBeObservable(expected); + }); + + it('should dispatch empty if link not exists', () => { + const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); + + actions = hot('a', { a: action }); + + expect(effects.loadVorgangWithEingangSuccess$).toBeObservable(cold('-')); + }); + }); + + describe('loadPendingCommandList', () => { + const action = VorgangActions.loadPendingCommandList({ vorgangWithEingang }); + const props: LoadCommandListProps = <any>{}; + + it('should dispatch "loadPendingCommandList" action', () => { + effects.createLoadPendingCommandListProps = jest.fn().mockReturnValue(props); + + actions = hot('-a-|', { a: action }); + + const expected = hot('-a-|', { a: loadCommandList(props) }); + expect(effects.loadPendingCommandList$).toBeObservable(expected); + }); + + it('should create props', () => { + effects.createLoadPendingCommandListProps = jest.fn(); + actions = of(action); + + effects.loadPendingCommandList$.subscribe(); + + expect(effects.createLoadPendingCommandListProps).toHaveBeenCalledWith(vorgangWithEingang); + }); + + describe('createLoadPendingCommandListProps', () => { + it('should have uri', () => { + const props: LoadCommandListProps = + effects.createLoadPendingCommandListProps(vorgangWithEingang); + + expect(props.resource).toBe(vorgangWithEingang); + }); + + it('should have fileName', () => { + const props: LoadCommandListProps = + effects.createLoadPendingCommandListProps(vorgangWithEingang); + + expect(props.linkRel).toBe(VorgangWithEingangLinkRel.PENDING_COMMANDS); + }); - it('should call vorgangFacade getVorgangFilter', () => { - actions = of(action); + it('should have as success action', () => { + const props: LoadCommandListProps = + effects.createLoadPendingCommandListProps(vorgangWithEingang); - effects.searchForPreview$.subscribe(); + const commandList: CommandListResource = createCommandListResource(); + expect(props.successAction(commandList).type).toEqual( + '[Vorgang/API] Load pending command list Success', + ); + }); - expect(vorgangFacade.getVorgangFilter).toHaveBeenCalled(); - }) + it('should have as failure action', () => { + const props: LoadCommandListProps = + effects.createLoadPendingCommandListProps(vorgangWithEingang); - it('should dispatch searchForPreviewSuccess action', () => { - vorgangRepository.searchVorgaengeBy.mockReturnValue(of(vorgangList)); + const apiError: ApiError = createApiError(); + expect(props.failureAction(apiError).type).toEqual( + '[Vorgang/API] Load pending command list Failure', + ); + }); + }); + }); - actions = hot('-a-|', { a: action }); + describe('loadRepresentationList', () => { + const action = VorgangActions.loadRepresentationList({ vorgangWithEingang }); + const props: LoadBinaryFileListProps = <any>{}; - const expected = hot('-a-|', { a: VorgangActions.searchForPreviewSuccess({ vorgangList }) }); - expect(effects.searchForPreview$).toBeObservable(expected); - }) + it('should dispatch "loadRepresentationList" action', () => { + effects.createLoadRepresentationListProps = jest.fn().mockReturnValue(props); - it('should dispatch searchForPreviewFailure action', () => { - const error: HttpErrorResponse = createHttpErrorResponse(); - const errorResponse = cold('-#', {}, error); - vorgangRepository.searchVorgaengeBy = jest.fn(() => errorResponse); + actions = hot('-a-|', { a: action }); - const expected = cold('--c', { c: VorgangActions.searchForPreviewFailure({ httpErrorResponse: error }) }); - actions = hot('-a', { a: action }); + const expected = hot('-a-|', { a: loadBinaryFileList(props) }); + expect(effects.loadRepresentationList$).toBeObservable(expected); + }); - expect(effects.searchForPreview$).toBeObservable(expected); - }) - }) + it('should create props', () => { + effects.createLoadRepresentationListProps = jest.fn(); + actions = of(action); - describe('search error', () => { - const action = VorgangActions.searchForPreviewFailure({ httpErrorResponse: null }); - const error: HttpErrorResponse = createHttpErrorResponse(); + effects.loadRepresentationList$.subscribe(); - it('should trigger showSearchError$', () => { - actions = of(action); - effects.showSearchError = jest.fn(); + expect(effects.createLoadRepresentationListProps).toHaveBeenCalledWith(vorgangWithEingang); + }); - effects.showSearchError$.subscribe(); + describe('createLoadRepresentationListProps', () => { + it('should have resource', () => { + const props: LoadBinaryFileListProps = + effects.createLoadRepresentationListProps(vorgangWithEingang); - expect(effects.showSearchError).toHaveBeenCalled(); - }) + expect(props.resource).toBe(vorgangWithEingang); + }); - it('should call snackbarService.showError if HTTP status code is NOT 503 ', () => { - error.error.status = HttpStatusCode.ExpectationFailed; + it('should have linkRel', () => { + const props: LoadBinaryFileListProps = + effects.createLoadRepresentationListProps(vorgangWithEingang); - effects.showSearchError(error); + expect(props.linkRel).toBe(VorgangWithEingangLinkRel.REPRESENTATIONS); + }); - expect(snackbarService.showError).not.toHaveBeenCalled(); - }) + it('should have success action', () => { + const props: LoadBinaryFileListProps = + effects.createLoadRepresentationListProps(vorgangWithEingang); - it('should call snackbarService.showError if HTTP status code is 503 ', () => { - error.error.status = HttpStatusCode.ServiceUnavailable; + const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); + expect(props.successAction(binaryFileList).type).toEqual( + '[Vorgang] Load RepresentationList Success', + ); + }); - effects.showSearchError(error); + it('should have failure action', () => { + const props: LoadBinaryFileListProps = + effects.createLoadRepresentationListProps(vorgangWithEingang); - expect(snackbarService.showError).toHaveBeenCalled(); - }) - }) + const apiError: ApiError = createApiError(); + expect(props.failureAction(apiError).type).toEqual( + '[Vorgang] Load RepresentationList Failure', + ); + }); + }); + }); - //VorgangWithEingang - describe('loadVorgangWithEingang', () => { + describe('loadAttachmentList', () => { + const action = VorgangActions.loadAttachmentList({ vorgangWithEingang }); + const props: LoadBinaryFileListProps = <any>{}; - const resourceUri: ResourceUri = faker.internet.url(); - const additionalSuccessAction = () => DUMMY_ACTION; - const additionalFailureAction = (error: HttpErrorResponse) => DUMMY_ACTION; - const additionalActions: AdditionalActions = { additionalSuccessAction, additionalFailureAction }; + it('should dispatch "loadAttachmentList" action', () => { + effects.createLoadAttachmentListProps = jest.fn().mockReturnValue(props); - const action: TypedAction<string> = VorgangActions.loadVorgangWithEingang({ resourceUri }); + actions = hot('-a-|', { a: action }); - describe('on success', () => { + const expected = hot('-a-|', { a: loadBinaryFileList(props) }); + expect(effects.loadAttachmentList$).toBeObservable(expected); + }); + + it('should create props', () => { + effects.createLoadAttachmentListProps = jest.fn(); + actions = of(action); + + effects.loadAttachmentList$.subscribe(); - beforeEach(() => { - vorgangRepository.getVorgang.mockReturnValue(of(vorgangWithEingang)); - }) + expect(effects.createLoadAttachmentListProps).toHaveBeenCalledWith(vorgangWithEingang); + }); + + describe('createLoadAttachmentListProps', () => { + it('should have resource', () => { + const props: LoadBinaryFileListProps = + effects.createLoadAttachmentListProps(vorgangWithEingang); - it('should dispatch action', () => { - actions = hot('-a-|', { a: action }); + expect(props.resource).toBe(vorgangWithEingang); + }); + + it('should have linkRel', () => { + const props: LoadBinaryFileListProps = + effects.createLoadAttachmentListProps(vorgangWithEingang); + + expect(props.linkRel).toBe(VorgangWithEingangLinkRel.ATTACHMENTS); + }); - const expected = hot('-a-|', { a: VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }) }); - expect(effects.loadVorgangWithEingang$).toBeObservable(expected); - }) + it('should have success action', () => { + const props: LoadBinaryFileListProps = + effects.createLoadAttachmentListProps(vorgangWithEingang); - it('should handle additional action', () => { - const action: TypedAction<string> = VorgangActions.loadVorgangWithEingang({ resourceUri, additionalActions }); + const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); + expect(props.successAction(binaryFileList).type).toEqual( + '[Vorgang] Load AttachmentList Success', + ); + }); - actions = hot('-a', { a: action }); + it('should have failure action', () => { + const props: LoadBinaryFileListProps = + effects.createLoadAttachmentListProps(vorgangWithEingang); - const expected = cold('-(bc)', { - b: VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }), - c: additionalSuccessAction() - }); - expect(effects.loadVorgangWithEingang$).toBeObservable(expected); - }) - }) + const apiError: ApiError = createApiError(); + expect(props.failureAction(apiError).type).toEqual('[Vorgang] Load AttachmentList Failure'); + }); + }); + }); - describe('on failure', () => { + describe('exportVorgang', () => { + const blob: Blob = new Blob(); + const fileName: string = faker.random.alphaNumeric(); + const blobWithFileName: BlobWithFileName = { blob, fileName }; + + const action = VorgangActions.exportVorgang({ vorgangWithEingang }); + + it('should call repository', () => { + actions = hot('-a', { a: action }); - const apiError: ApiError = createApiError() - const error = { error: { error: apiError } }; + effects.exportVorgang$.subscribe(() => { + expect(vorgangRepository.export).toHaveBeenCalledWith(vorgangWithEingang); + }); + }); + + it('should dispatch success action on no error', () => { + vorgangRepository.export.mockReturnValue(of(blobWithFileName)); - beforeEach(() => { - const errorResponse = cold('-#', {}, error); - vorgangRepository.getVorgang = jest.fn(() => errorResponse); - }) - - it('should dispatch action', () => { - actions = hot('-a', { a: action }); - - const expected = cold('--c', { c: VorgangActions.loadVorgangWithEingangFailure({ apiError }) }); - expect(effects.loadVorgangWithEingang$).toBeObservable(expected); - }) - - it('should handle additional action', () => { - const action: TypedAction<string> = VorgangActions.loadVorgangWithEingang({ resourceUri, additionalActions }); - - actions = hot('-a', { a: action }); - - const expected = cold('--(bc)', { - b: VorgangActions.loadVorgangWithEingangFailure({ apiError }), - c: additionalFailureAction(<HttpErrorResponse>error) - }); - expect(effects.loadVorgangWithEingang$).toBeObservable(expected); - }) - }) - }) - - describe('loadVorgangWithEingangSuccess', () => { - - it('should dispatch "loadPendingCommandList" action if link exists', () => { - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.PENDING_COMMANDS]); - const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); - - actions = hot('-a-|', { a: action }); - - const expected = hot('-a-|', { a: VorgangActions.loadPendingCommandList({ vorgangWithEingang }) }); - expect(effects.loadVorgangWithEingangSuccess$).toBeObservable(expected); - }) - - it('should dispatch empty if link not exists', () => { - const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); - - actions = hot('a', { a: action }); - - expect(effects.loadVorgangWithEingangSuccess$).toBeObservable(cold('-')); - }) - }) - - describe('loadPendingCommandList', () => { - - const action = VorgangActions.loadPendingCommandList({ vorgangWithEingang }); - const props: LoadCommandListProps = <any>{}; - - it('should dispatch "loadPendingCommandList" action', () => { - effects.createLoadPendingCommandListProps = jest.fn().mockReturnValue(props); - - actions = hot('-a-|', { a: action }); - - const expected = hot('-a-|', { a: loadCommandList(props) }); - expect(effects.loadPendingCommandList$).toBeObservable(expected); - }) - - it('should create props', () => { - effects.createLoadPendingCommandListProps = jest.fn() - actions = of(action); - - effects.loadPendingCommandList$.subscribe(); - - expect(effects.createLoadPendingCommandListProps).toHaveBeenCalledWith(vorgangWithEingang); - }) - - describe('createLoadPendingCommandListProps', () => { - - it('should have uri', () => { - const props: LoadCommandListProps = effects.createLoadPendingCommandListProps(vorgangWithEingang); - - expect(props.resource).toBe(vorgangWithEingang); - }) - - it('should have fileName', () => { - const props: LoadCommandListProps = effects.createLoadPendingCommandListProps(vorgangWithEingang); - - expect(props.linkRel).toBe(VorgangWithEingangLinkRel.PENDING_COMMANDS); - }) - - it('should have as success action', () => { - const props: LoadCommandListProps = effects.createLoadPendingCommandListProps(vorgangWithEingang); - - const commandList: CommandListResource = createCommandListResource(); - expect(props.successAction(commandList).type).toEqual('[Vorgang/API] Load pending command list Success'); - }) - - it('should have as failure action', () => { - const props: LoadCommandListProps = effects.createLoadPendingCommandListProps(vorgangWithEingang); - - const apiError: ApiError = createApiError(); - expect(props.failureAction(apiError).type).toEqual('[Vorgang/API] Load pending command list Failure'); - }) - }) - }) - - describe('loadRepresentationList', () => { - - const action = VorgangActions.loadRepresentationList({ vorgangWithEingang }); - const props: LoadBinaryFileListProps = <any>{}; - - it('should dispatch "loadRepresentationList" action', () => { - effects.createLoadRepresentationListProps = jest.fn().mockReturnValue(props); - - actions = hot('-a-|', { a: action }); - - const expected = hot('-a-|', { a: loadBinaryFileList(props) }); - expect(effects.loadRepresentationList$).toBeObservable(expected); - }) - - it('should create props', () => { - effects.createLoadRepresentationListProps = jest.fn() - actions = of(action); - - effects.loadRepresentationList$.subscribe(); - - expect(effects.createLoadRepresentationListProps).toHaveBeenCalledWith(vorgangWithEingang); - }) - - describe('createLoadRepresentationListProps', () => { - - it('should have resource', () => { - const props: LoadBinaryFileListProps = effects.createLoadRepresentationListProps(vorgangWithEingang); - - expect(props.resource).toBe(vorgangWithEingang); - }) - - it('should have linkRel', () => { - const props: LoadBinaryFileListProps = effects.createLoadRepresentationListProps(vorgangWithEingang); - - expect(props.linkRel).toBe(VorgangWithEingangLinkRel.REPRESENTATIONS); - }) - - it('should have success action', () => { - const props: LoadBinaryFileListProps = effects.createLoadRepresentationListProps(vorgangWithEingang); - - const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); - expect(props.successAction(binaryFileList).type).toEqual('[Vorgang] Load RepresentationList Success'); - }) - - it('should have failure action', () => { - const props: LoadBinaryFileListProps = effects.createLoadRepresentationListProps(vorgangWithEingang); - - const apiError: ApiError = createApiError(); - expect(props.failureAction(apiError).type).toEqual('[Vorgang] Load RepresentationList Failure'); - }) - }) - }) - - describe('loadAttachmentList', () => { - - const action = VorgangActions.loadAttachmentList({ vorgangWithEingang }); - const props: LoadBinaryFileListProps = <any>{}; - - it('should dispatch "loadAttachmentList" action', () => { - effects.createLoadAttachmentListProps = jest.fn().mockReturnValue(props); - - actions = hot('-a-|', { a: action }); - - const expected = hot('-a-|', { a: loadBinaryFileList(props) }); - expect(effects.loadAttachmentList$).toBeObservable(expected); - }) - - it('should create props', () => { - effects.createLoadAttachmentListProps = jest.fn() - actions = of(action); - - effects.loadAttachmentList$.subscribe(); - - expect(effects.createLoadAttachmentListProps).toHaveBeenCalledWith(vorgangWithEingang); - }) - - describe('createLoadAttachmentListProps', () => { - - it('should have resource', () => { - const props: LoadBinaryFileListProps = effects.createLoadAttachmentListProps(vorgangWithEingang); - - expect(props.resource).toBe(vorgangWithEingang); - }) - - it('should have linkRel', () => { - const props: LoadBinaryFileListProps = effects.createLoadAttachmentListProps(vorgangWithEingang); - - expect(props.linkRel).toBe(VorgangWithEingangLinkRel.ATTACHMENTS); - }) - - it('should have success action', () => { - const props: LoadBinaryFileListProps = effects.createLoadAttachmentListProps(vorgangWithEingang); - - const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); - expect(props.successAction(binaryFileList).type).toEqual('[Vorgang] Load AttachmentList Success'); - }) - - it('should have failure action', () => { - const props: LoadBinaryFileListProps = effects.createLoadAttachmentListProps(vorgangWithEingang); - - const apiError: ApiError = createApiError(); - expect(props.failureAction(apiError).type).toEqual('[Vorgang] Load AttachmentList Failure'); - }) - }) - }) - - describe('exportVorgang', () => { - - const blob: Blob = new Blob(); - const fileName: string = faker.random.alphaNumeric(); - const blobWithFileName: BlobWithFileName = { blob, fileName }; - - const action = VorgangActions.exportVorgang({ vorgangWithEingang }); - - it('should call repository', () => { - actions = hot('-a', { a: action }); - - effects.exportVorgang$.subscribe(() => { - expect(vorgangRepository.export).toHaveBeenCalledWith(vorgangWithEingang); - }); - }); - - it('should dispatch success action on no error', () => { - vorgangRepository.export.mockReturnValue(of(blobWithFileName)); - - actions = hot('-a', { a: action }); - - const expected: ColdObservable = cold('-(bc)', { - b: BinaryFileActions.saveFile({ fileData: blob, fileName }), - c: VorgangActions.exportVorgangSuccess() - }); - expect(effects.exportVorgang$).toBeObservable(expected); - }); - - it('should dispatch failure action', () => { - const apiError: ApiError = createApiError() - const error = { error: { error: apiError } }; - const errorResponse = cold('-#', {}, error); - vorgangRepository.export = jest.fn(() => errorResponse); - - const expected = cold('--c', { c: VorgangActions.exportVorgangFailure({ apiError }) }); - actions = hot('-a', { a: action }); - - expect(effects.exportVorgang$).toBeObservable(expected); - }) - }); -}); \ No newline at end of file + actions = hot('-a', { a: action }); + + const expected: ColdObservable = cold('-(bc)', { + b: BinaryFileActions.saveFile({ fileData: blob, fileName }), + c: VorgangActions.exportVorgangSuccess(), + }); + expect(effects.exportVorgang$).toBeObservable(expected); + }); + + it('should dispatch failure action', () => { + const apiError: ApiError = createApiError(); + const error = { error: { error: apiError } }; + const errorResponse = cold('-#', {}, error); + vorgangRepository.export = jest.fn(() => errorResponse); + + const expected = cold('--c', { c: VorgangActions.exportVorgangFailure({ apiError }) }); + actions = hot('-a', { a: action }); + + expect(effects.exportVorgang$).toBeObservable(expected); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.ts index 6e40b5f91eb583e20f19c5d54f9c55e1c0b155b9..9c6741b545e6aebf8a12fbbfe73a39be7b74b381 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.ts @@ -24,9 +24,23 @@ import { HttpErrorResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { ApiRootFacade } from '@alfa-client/api-root-shared'; -import { BinaryFileListResource, LoadBinaryFileListProps, loadBinaryFileList } from '@alfa-client/binary-file-shared'; -import { CommandListResource, LoadCommandListProps, loadCommandList } from '@alfa-client/command-shared'; -import { ApiError, BlobWithFileName, getApiErrorFromHttpErrorResponse, isNotUndefined, isServiceUnavailable } from '@alfa-client/tech-shared'; +import { + BinaryFileListResource, + LoadBinaryFileListProps, + loadBinaryFileList, +} from '@alfa-client/binary-file-shared'; +import { + CommandListResource, + LoadCommandListProps, + loadCommandList, +} from '@alfa-client/command-shared'; +import { + ApiError, + BlobWithFileName, + getApiErrorFromHttpErrorResponse, + isNotUndefined, + isServiceUnavailable, +} from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects'; import { Store } from '@ngrx/store'; @@ -39,7 +53,13 @@ import { getSearchLinkRel } from '../vorgang-navigation.util'; import { VorgangWithEingangLinkRel } from '../vorgang.linkrel'; import { VorgangMessages } from '../vorgang.messages'; import { AdditionalActions, VorgangWithEingangResource } from '../vorgang.model'; -import { ApiRootWithLinkRelProps, HttpErrorAction, SearchVorgaengeByProps, VorgangUriWithContextProps, VorgangWithEingangAction } from './vorgang.actions'; +import { + ApiRootWithLinkRelProps, + HttpErrorAction, + SearchVorgaengeByProps, + VorgangUriWithContextProps, + VorgangWithEingangAction, +} from './vorgang.actions'; import { VorgangFacade } from './vorgang.facade'; import { VorgangRepository } from './vorgang.repository'; @@ -49,128 +69,260 @@ import * as VorgangSelectors from './vorgang.selectors'; @Injectable() export class VorgangEffects { + constructor( + private readonly actions$: Actions, + private store: Store, + private repository: VorgangRepository, + private apiRootFacade: ApiRootFacade, + private vorgangFacade: VorgangFacade, + private snackbarService: SnackBarService, + ) {} - constructor(private readonly actions$: Actions, private store: Store, private repository: VorgangRepository, private apiRootFacade: ApiRootFacade, private vorgangFacade: VorgangFacade, private snackbarService: SnackBarService) { } - - //VorgangList - loadVorgangList$ = createEffect(() => this.actions$.pipe( - ofType(VorgangActions.loadVorgangList), - switchMap((props: ApiRootWithLinkRelProps) => this.repository.loadVorgangList(props.apiRoot, props.linkRel).pipe( - map(loadedVorgangList => VorgangActions.loadVorgangListSuccess({ vorgangList: loadedVorgangList })), - catchError(error => of(VorgangActions.loadVorgangListFailure({ apiError: getApiErrorFromHttpErrorResponse(error) }))) - ))) - ) - - loadNextPage$ = createEffect(() => this.actions$.pipe( - ofType(VorgangActions.loadNextPage), - concatLatestFrom(() => this.store.select(VorgangSelectors.vorgangList)), - switchMap(([, vorgangList]) => this.repository.getNextVorgangListPage(vorgangList.resource).pipe( - map(loadedVorgangList => VorgangActions.loadNextPageSuccess({ vorgangList: loadedVorgangList })), - catchError(error => of(VorgangActions.loadVorgangListFailure({ apiError: getApiErrorFromHttpErrorResponse(error) }))) - )) - )) - - searchVorgaengeBy$ = createEffect(() => this.actions$.pipe( - ofType(VorgangActions.searchVorgaengeBy), - switchMap((props: SearchVorgaengeByProps) => this.repository.searchVorgaengeBy(props.apiRoot, props.searchString, props.linkRel).pipe( - map(loadedVorgangList => VorgangActions.searchVorgaengeBySuccess({ vorgangList: loadedVorgangList })), - catchError(error => of(VorgangActions.searchVorgaengeByFailure({ httpErrorResponse: error }))) - )) - )) - - searchForPreview$ = createEffect(() => this.actions$.pipe( - ofType(VorgangActions.searchForPreview), - concatLatestFrom(() => [this.apiRootFacade.getApiRoot(), this.vorgangFacade.getVorgangFilter()]), - switchMap(([stringBasedProps, apiRoot, vorgangFilter]) => this.repository.searchVorgaengeBy(apiRoot.resource, stringBasedProps.string, getSearchLinkRel(vorgangFilter), VorgangListService.SEARCH_PREVIEW_LIST_LIMIT).pipe( - map(loadedVorgangList => VorgangActions.searchForPreviewSuccess({ vorgangList: loadedVorgangList })), - catchError(error => of(VorgangActions.searchForPreviewFailure({ httpErrorResponse: error }))) - )) - )) - - showSearchError$ = createEffect(() => this.actions$.pipe( - ofType( - VorgangActions.searchForPreviewFailure, - VorgangActions.searchVorgaengeByFailure - ), - map((action: HttpErrorAction) => this.showSearchError(action.httpErrorResponse)), - ), { dispatch: false }); - - showSearchError(error: HttpErrorResponse): void { - if (isServiceUnavailable(error.error.status)) { - this.snackbarService.showError(VorgangMessages.SEARCH_UNAVAILABLE); - } - } - - //VorgangWithEingang - loadVorgangWithEingang$ = createEffect(() => this.actions$.pipe( - ofType(VorgangActions.loadVorgangWithEingang), - switchMap((props: VorgangUriWithContextProps) => this.repository.getVorgang(props.resourceUri).pipe( - mergeMap(vorgangWithEingang => this.handleSuccessActions(vorgangWithEingang, props.additionalActions)), - catchError(error => this.handleFailureActions(error, props.additionalActions))) - ) - )) - - private handleSuccessActions(vorgangWithEingang: VorgangWithEingangResource, additionalActions: AdditionalActions): TypedAction<string>[] { - if(isNotUndefined(additionalActions?.additionalSuccessAction)){ - return [VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }), additionalActions.additionalSuccessAction()]; - } - return [VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang })]; - } - - private handleFailureActions(error: HttpErrorResponse, additionalActions: AdditionalActions): Observable<TypedAction<string>> { - if(isNotUndefined(additionalActions?.additionalFailureAction)){ - return of(VorgangActions.loadVorgangWithEingangFailure({ apiError: getApiErrorFromHttpErrorResponse(error) }), additionalActions.additionalFailureAction(error)); - } - return of(VorgangActions.loadVorgangWithEingangFailure({ apiError: getApiErrorFromHttpErrorResponse(error) })); - } - - loadVorgangWithEingangSuccess$ = createEffect(() => this.actions$.pipe( - ofType(VorgangActions.loadVorgangWithEingangSuccess), - filter((props: VorgangWithEingangAction) => hasLink(props.vorgangWithEingang, VorgangWithEingangLinkRel.PENDING_COMMANDS)), - switchMap((props: VorgangWithEingangAction) => of(VorgangActions.loadPendingCommandList({ vorgangWithEingang: props.vorgangWithEingang }))) - )) - - loadPendingCommandList$ = createEffect(() => this.actions$.pipe( - ofType(VorgangActions.loadPendingCommandList), - switchMap((props: VorgangWithEingangAction) => of(loadCommandList(this.createLoadPendingCommandListProps(props.vorgangWithEingang)))) - )) - - createLoadPendingCommandListProps(vorgangWithEingang: VorgangWithEingangResource): LoadCommandListProps { - return { resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.PENDING_COMMANDS, - successAction: (commandList: CommandListResource) => VorgangActions.loadPendingCommandListSuccess({ commandList }), - failureAction: (apiError: ApiError) => VorgangActions.loadPendingCommandListFailure({ apiError }) - } - } - - loadRepresentationList$ = createEffect(() => this.actions$.pipe( - ofType(VorgangActions.loadRepresentationList), - switchMap((props: VorgangWithEingangAction) => of(loadBinaryFileList(this.createLoadRepresentationListProps(props.vorgangWithEingang)))) - )) - - createLoadRepresentationListProps(vorgangWithEingang: VorgangWithEingangResource): LoadBinaryFileListProps { - return { resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.REPRESENTATIONS, - successAction: (binaryFileList: BinaryFileListResource) => VorgangActions.loadRepresentationListSuccess({ binaryFileList }), - failureAction: (apiError: ApiError) => VorgangActions.loadRepresentationListFailure({ apiError }) - } - } - - loadAttachmentList$ = createEffect(() => this.actions$.pipe( - ofType(VorgangActions.loadAttachmentList), - switchMap((props: VorgangWithEingangAction) => of(loadBinaryFileList(this.createLoadAttachmentListProps(props.vorgangWithEingang)))) - )) - - createLoadAttachmentListProps(vorgangWithEingang: VorgangWithEingangResource): LoadBinaryFileListProps { - return { resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.ATTACHMENTS, - successAction: (binaryFileList: BinaryFileListResource) => VorgangActions.loadAttachmentListSuccess({ binaryFileList }), - failureAction: (apiError: ApiError) => VorgangActions.loadAttachmentListFailure({ apiError }) - } - } - - exportVorgang$ = createEffect(() => this.actions$.pipe( - ofType(VorgangActions.exportVorgang), - switchMap((props: VorgangWithEingangAction) => this.repository.export(props.vorgangWithEingang).pipe( - mergeMap((blobWithFileName: BlobWithFileName) => [BinaryFileActions.saveFile({ fileData: blobWithFileName.blob, fileName: blobWithFileName.fileName }), VorgangActions.exportVorgangSuccess()]), - catchError(error => of(VorgangActions.exportVorgangFailure({ apiError: getApiErrorFromHttpErrorResponse(error) })))) - ) - )) -} \ No newline at end of file + //VorgangList + loadVorgangList$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.loadVorgangList), + switchMap((props: ApiRootWithLinkRelProps) => + this.repository.loadVorgangList(props.apiRoot, props.linkRel).pipe( + map((loadedVorgangList) => + VorgangActions.loadVorgangListSuccess({ vorgangList: loadedVorgangList }), + ), + catchError((error) => + of( + VorgangActions.loadVorgangListFailure({ + apiError: getApiErrorFromHttpErrorResponse(error), + }), + ), + ), + ), + ), + ), + ); + + loadNextPage$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.loadNextPage), + concatLatestFrom(() => this.store.select(VorgangSelectors.vorgangList)), + switchMap(([, vorgangList]) => + this.repository.getNextVorgangListPage(vorgangList.resource).pipe( + map((loadedVorgangList) => + VorgangActions.loadNextPageSuccess({ vorgangList: loadedVorgangList }), + ), + catchError((error) => + of( + VorgangActions.loadVorgangListFailure({ + apiError: getApiErrorFromHttpErrorResponse(error), + }), + ), + ), + ), + ), + ), + ); + + searchVorgaengeBy$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.searchVorgaengeBy), + switchMap((props: SearchVorgaengeByProps) => + this.repository.searchVorgaengeBy(props.apiRoot, props.searchString, props.linkRel).pipe( + map((loadedVorgangList) => + VorgangActions.searchVorgaengeBySuccess({ vorgangList: loadedVorgangList }), + ), + catchError((error) => + of(VorgangActions.searchVorgaengeByFailure({ httpErrorResponse: error })), + ), + ), + ), + ), + ); + + searchForPreview$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.searchForPreview), + concatLatestFrom(() => [ + this.apiRootFacade.getApiRoot(), + this.vorgangFacade.getVorgangFilter(), + ]), + switchMap(([stringBasedProps, apiRoot, vorgangFilter]) => + this.repository + .searchVorgaengeBy( + apiRoot.resource, + stringBasedProps.string, + getSearchLinkRel(vorgangFilter), + VorgangListService.SEARCH_PREVIEW_LIST_LIMIT, + ) + .pipe( + map((loadedVorgangList) => + VorgangActions.searchForPreviewSuccess({ vorgangList: loadedVorgangList }), + ), + catchError((error) => + of(VorgangActions.searchForPreviewFailure({ httpErrorResponse: error })), + ), + ), + ), + ), + ); + + showSearchError$ = createEffect( + () => + this.actions$.pipe( + ofType(VorgangActions.searchForPreviewFailure, VorgangActions.searchVorgaengeByFailure), + map((action: HttpErrorAction) => this.showSearchError(action.httpErrorResponse)), + ), + { dispatch: false }, + ); + + showSearchError(error: HttpErrorResponse): void { + if (isServiceUnavailable(error.error.status)) { + this.snackbarService.showError(VorgangMessages.SEARCH_UNAVAILABLE); + } + } + + //VorgangWithEingang + loadVorgangWithEingang$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.loadVorgangWithEingang), + switchMap((props: VorgangUriWithContextProps) => + this.repository.getVorgang(props.resourceUri).pipe( + mergeMap((vorgangWithEingang) => + this.handleSuccessActions(vorgangWithEingang, props.additionalActions), + ), + catchError((error) => this.handleFailureActions(error, props.additionalActions)), + ), + ), + ), + ); + + private handleSuccessActions( + vorgangWithEingang: VorgangWithEingangResource, + additionalActions: AdditionalActions, + ): TypedAction<string>[] { + if (isNotUndefined(additionalActions?.additionalSuccessAction)) { + return [ + VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }), + additionalActions.additionalSuccessAction(), + ]; + } + return [VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang })]; + } + + private handleFailureActions( + error: HttpErrorResponse, + additionalActions: AdditionalActions, + ): Observable<TypedAction<string>> { + if (isNotUndefined(additionalActions?.additionalFailureAction)) { + return of( + VorgangActions.loadVorgangWithEingangFailure({ + apiError: getApiErrorFromHttpErrorResponse(error), + }), + additionalActions.additionalFailureAction(error), + ); + } + return of( + VorgangActions.loadVorgangWithEingangFailure({ + apiError: getApiErrorFromHttpErrorResponse(error), + }), + ); + } + + loadVorgangWithEingangSuccess$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.loadVorgangWithEingangSuccess), + filter((props: VorgangWithEingangAction) => + hasLink(props.vorgangWithEingang, VorgangWithEingangLinkRel.PENDING_COMMANDS), + ), + switchMap((props: VorgangWithEingangAction) => + of(VorgangActions.loadPendingCommandList({ vorgangWithEingang: props.vorgangWithEingang })), + ), + ), + ); + + loadPendingCommandList$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.loadPendingCommandList), + switchMap((props: VorgangWithEingangAction) => + of(loadCommandList(this.createLoadPendingCommandListProps(props.vorgangWithEingang))), + ), + ), + ); + + createLoadPendingCommandListProps( + vorgangWithEingang: VorgangWithEingangResource, + ): LoadCommandListProps { + return { + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.PENDING_COMMANDS, + successAction: (commandList: CommandListResource) => + VorgangActions.loadPendingCommandListSuccess({ commandList }), + failureAction: (apiError: ApiError) => + VorgangActions.loadPendingCommandListFailure({ apiError }), + }; + } + + loadRepresentationList$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.loadRepresentationList), + switchMap((props: VorgangWithEingangAction) => + of(loadBinaryFileList(this.createLoadRepresentationListProps(props.vorgangWithEingang))), + ), + ), + ); + + createLoadRepresentationListProps( + vorgangWithEingang: VorgangWithEingangResource, + ): LoadBinaryFileListProps { + return { + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.REPRESENTATIONS, + successAction: (binaryFileList: BinaryFileListResource) => + VorgangActions.loadRepresentationListSuccess({ binaryFileList }), + failureAction: (apiError: ApiError) => + VorgangActions.loadRepresentationListFailure({ apiError }), + }; + } + + loadAttachmentList$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.loadAttachmentList), + switchMap((props: VorgangWithEingangAction) => + of(loadBinaryFileList(this.createLoadAttachmentListProps(props.vorgangWithEingang))), + ), + ), + ); + + createLoadAttachmentListProps( + vorgangWithEingang: VorgangWithEingangResource, + ): LoadBinaryFileListProps { + return { + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.ATTACHMENTS, + successAction: (binaryFileList: BinaryFileListResource) => + VorgangActions.loadAttachmentListSuccess({ binaryFileList }), + failureAction: (apiError: ApiError) => VorgangActions.loadAttachmentListFailure({ apiError }), + }; + } + + exportVorgang$ = createEffect(() => + this.actions$.pipe( + ofType(VorgangActions.exportVorgang), + switchMap((props: VorgangWithEingangAction) => + this.repository.export(props.vorgangWithEingang).pipe( + mergeMap((blobWithFileName: BlobWithFileName) => [ + BinaryFileActions.saveFile({ + fileData: blobWithFileName.blob, + fileName: blobWithFileName.fileName, + }), + VorgangActions.exportVorgangSuccess(), + ]), + catchError((error) => + of( + VorgangActions.exportVorgangFailure({ + apiError: getApiErrorFromHttpErrorResponse(error), + }), + ), + ), + ), + ), + ), + ); +} diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.spec.ts index ce35c5e693ae155b31b82d28067527148ebd471f..4868dc3fca2f4dff90e929c8a1f62f76f6c20318 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.spec.ts @@ -30,10 +30,24 @@ import { Store } from '@ngrx/store'; import { ResourceUri } from '@ngxp/rest'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { createCommand, createCommandResource } from 'libs/command-shared/test/command'; -import { createVorgangListResource, createVorgangResources, createVorgangStatistic, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; +import { + createVorgangListResource, + createVorgangResources, + createVorgangStatistic, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; import { Subject } from 'rxjs'; import { VorgangWithEingangLinkRel } from '../vorgang.linkrel'; -import { AdditionalActions, CreateAssignUserCommand, VorgangFilter, VorgangListResource, VorgangResource, VorgangStatistic, VorgangView, VorgangWithEingangResource } from '../vorgang.model'; +import { + AdditionalActions, + CreateAssignUserCommand, + VorgangFilter, + VorgangListResource, + VorgangResource, + VorgangStatistic, + VorgangView, + VorgangWithEingangResource, +} from '../vorgang.model'; import { VorgangFacade } from './vorgang.facade'; import faker from '@faker-js/faker'; @@ -43,605 +57,653 @@ import * as VorgangActions from './vorgang.actions'; import * as VorgangSelectors from './vorgang.selectors'; describe('VorgangFacade', () => { - let facade: VorgangFacade; - let store: Mock<Store>; + let facade: VorgangFacade; + let store: Mock<Store>; - let selectionSubject: Subject<any>; + let selectionSubject: Subject<any>; - const SEARCH_STRING = faker.word.noun(); + const SEARCH_STRING = faker.word.noun(); - beforeEach(() => { - store = mock(Store); + beforeEach(() => { + store = mock(Store); - selectionSubject = new Subject(); + selectionSubject = new Subject(); - store.select.mockReturnValue(selectionSubject); - store.dispatch = jest.fn(); + store.select.mockReturnValue(selectionSubject); + store.dispatch = jest.fn(); - facade = new VorgangFacade(useFromMock(<any>store)); - }) + facade = new VorgangFacade(useFromMock(<any>store)); + }); - it('is initialized', () => { - expect(facade).toBeTruthy(); - }) + it('is initialized', () => { + expect(facade).toBeTruthy(); + }); - //VorgangList - describe('getVorgangList', () => { + //VorgangList + describe('getVorgangList', () => { + it('should return selected value', (done) => { + const vorgaengeStateResource: StateResource<VorgangResource[]> = + createStateResource(createVorgangResources()); - it('should return selected value', (done) => { - const vorgaengeStateResource: StateResource<VorgangResource[]> = createStateResource(createVorgangResources()); + facade.getVorgangList().subscribe((vorgaenge) => { + expect(vorgaenge).toBe(vorgaengeStateResource); + done(); + }); - facade.getVorgangList().subscribe(vorgaenge => { - expect(vorgaenge).toBe(vorgaengeStateResource); - done(); - }); + selectionSubject.next(vorgaengeStateResource); + }); + }); - selectionSubject.next(vorgaengeStateResource); - }); - }) + describe('loadVorgangList', () => { + it('should dispatch "loadVorgangList" action', () => { + const apiRoot: ApiRootResource = createApiRootResource(); - describe('loadVorgangList', () => { + facade.loadVorgangList(apiRoot, 'dummyLinkRel'); - it('should dispatch "loadVorgangList" action', () => { - const apiRoot: ApiRootResource = createApiRootResource(); + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.loadVorgangList({ apiRoot, linkRel: 'dummyLinkRel' }), + ); + }); + }); - facade.loadVorgangList(apiRoot, 'dummyLinkRel'); + describe('getVorgaenge', () => { + it('should return selected value', (done) => { + const vorgaengeStateResource: StateResource<VorgangResource[]> = + createStateResource(createVorgangResources()); - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.loadVorgangList({ apiRoot, linkRel: 'dummyLinkRel' })); - }); - }) + facade.getVorgaenge().subscribe((vorgaenge) => { + expect(vorgaenge).toBe(vorgaengeStateResource); + done(); + }); - describe('getVorgaenge', () => { + selectionSubject.next(vorgaengeStateResource); + }); + }); - it('should return selected value', (done) => { - const vorgaengeStateResource: StateResource<VorgangResource[]> = createStateResource(createVorgangResources()); + describe('getVorgangStatistic', () => { + it('should return selected value', (done) => { + const vorgangStatisticStateResource: StateResource<VorgangStatistic> = + createStateResource(createVorgangStatistic()); + + facade.getVorgangStatistic().subscribe((vorgaenge) => { + expect(vorgaenge).toBe(vorgangStatisticStateResource); + done(); + }); + + selectionSubject.next(vorgangStatisticStateResource); + }); + }); - facade.getVorgaenge().subscribe(vorgaenge => { - expect(vorgaenge).toBe(vorgaengeStateResource); - done(); - }); - - selectionSubject.next(vorgaengeStateResource); - }); - }) - - describe('getVorgangStatistic', () => { - - it('should return selected value', (done) => { - const vorgangStatisticStateResource: StateResource<VorgangStatistic> = createStateResource(createVorgangStatistic()); - - facade.getVorgangStatistic().subscribe(vorgaenge => { - expect(vorgaenge).toBe(vorgangStatisticStateResource); - done(); - }); - - selectionSubject.next(vorgangStatisticStateResource); - }); - }) - - describe('loadNextPage', () => { - - it('should dispatch "loadNextPage" action', () => { - facade.loadNextPage(); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.loadNextPage()); - }); - }) - - describe('getVorgangFilter', () => { - - it('should return selected value', (done) => { - const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; - - facade.getVorgangFilter().subscribe(view => { - expect(view).toBe(vorgangFilter); - done(); - }); - - selectionSubject.next(vorgangFilter); - }); - }) - - describe('isVorgangFilterSelected', () => { - - const isSelected: boolean = true; - const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; - - it('should return selected value', (done) => { - facade.isVorgangFilterSelected(vorgangFilter).subscribe(selected => { - expect(selected).toBe(isSelected); - done(); - }); - - selectionSubject.next(isSelected); - }) - - it('should call selector', (done) => { - const selectorSpy = jest.spyOn(VorgangSelectors, 'isVorgangFilterSelected'); - - facade.isVorgangFilterSelected(vorgangFilter).subscribe(() => { - expect(selectorSpy).toHaveBeenCalledWith(vorgangFilter); - done(); - }); - - selectionSubject.next(isSelected); - }) - }) - - describe('getVorgangView', () => { - - it('should return selected value', (done) => { - const vorgangView: VorgangView = VorgangView.NEU; - - facade.getVorgangView().subscribe(view => { - expect(view).toBe(vorgangView); - done(); - }); - - selectionSubject.next(vorgangView); - }); - }) - - describe('isVorgangViewSelected', () => { - - const isSelected: boolean = true; - const vorgangView: VorgangView = VorgangView.NEU; - - it('should return selected value', (done) => { - facade.isVorgangViewSelected(vorgangView).subscribe(selected => { - expect(selected).toBe(isSelected); - done(); - }); - - selectionSubject.next(isSelected); - }) - - it('should call selector', (done) => { - const selectorSpy = jest.spyOn(VorgangSelectors, 'isVorgangViewSelected'); - - facade.isVorgangViewSelected(vorgangView).subscribe(() => { - expect(selectorSpy).toHaveBeenCalledWith(vorgangView); - done(); - }); - - selectionSubject.next(isSelected); - }) - }) - - describe('getVorgangViewRoutePath', () => { - - const path: string = 'dummyPath'; - const vorgangView: VorgangView = VorgangView.NEU; - - it('should return selected value', (done) => { - facade.getVorgangViewRoutePath(vorgangView).subscribe(routePath => { - expect(routePath).toBe(path); - done(); - }) - - selectionSubject.next(path); - }) - - it('should call selector', (done) => { - const selectorSpy = jest.spyOn(VorgangSelectors, 'getVorgangViewRoutePath'); - - facade.getVorgangViewRoutePath(vorgangView).subscribe(() => { - expect(selectorSpy).toHaveBeenCalledWith(vorgangView); - done(); - }) - - selectionSubject.next(path); - }) - }) - - describe('getBackButtonUrl', () => { - - it('should return selected value', (done) => { - const path: string = 'dummyPath'; - - facade.getBackButtonUrl().subscribe(routePath => { - expect(routePath).toBe(path); - done(); - }) - - selectionSubject.next(path); - }) - }) - - //Search - describe('searchVorgaengeBy', () => { - - const apiRoot: ApiRootResource = createApiRootResource(); - const searchString: string = SEARCH_STRING; - const linkRel: string = 'LinkRelationName'; - - it('should dispatch "searchVorgaengeBy" action', () => { - facade.searchVorgaengeBy(apiRoot, searchString, linkRel); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.searchVorgaengeBy({ apiRoot, searchString, linkRel })); - }); - }) - - describe('searchForPreview', () => { - - it('should dispatch "searchForPreview" action', () => { - facade.searchForPreview(SEARCH_STRING); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.searchForPreview({ string: SEARCH_STRING })); - }); - }) - - describe('setSearchString', () => { - - it('should dispatch "setSearchString" action', () => { - const searchString: string = 'dummySearchString'; - - facade.setSearchString(searchString); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.setSearchString({ string: searchString })); - }); - }) - - describe('getSearchString', () => { - - it('should return selected value', (done) => { - const searchString: string = 'dummySearchString'; - - facade.getSearchString().subscribe(selectedSearchString => { - expect(selectedSearchString).toBe(searchString); - done(); - }); - - selectionSubject.next(searchString); - }); - }) - - describe('getSearchPreviewList', () => { - - it('should return selected value', (done) => { - const saerchPreviewListStateResource: StateResource<VorgangListResource> = createStateResource(createVorgangListResource()); - - facade.getSearchPreviewList().subscribe(searchPreviewList => { - expect(searchPreviewList).toBe(saerchPreviewListStateResource); - done(); - }); - - selectionSubject.next(saerchPreviewListStateResource); - }); - }) - - describe('clearSearchPreviewList', () => { - - it('should dispatch "clearSearchPreviewList" action', () => { - facade.clearSearchPreviewList(); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.clearSearchPreviewList()); - }); - }) - - describe('clearSearchString', () => { - - it('should dispatch "clearSearchString" action', () => { - facade.clearSearchString(); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.clearSearchString()); - }) - }) - - //VorgangWithEingang - describe('getVorgangWithEingang', () => { - - it('should return selected value', (done) => { - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - facade.getVorgangWithEingang().subscribe(selectedVorgangWithEingang => { - expect(selectedVorgangWithEingang).toBe(vorgangWithEingang); - done(); - }); - - selectionSubject.next(vorgangWithEingang); - }) - }) - - describe('loadVorgangWithEingang', () => { - - const vorgangWithEingangUri: ResourceUri = faker.internet.url(); - - it('should dispatch "loadVorgangWithEingang" action', () => { - facade.loadVorgangWithEingang(vorgangWithEingangUri); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.loadVorgangWithEingang({ resourceUri: vorgangWithEingangUri })); - }) - }) - - describe('loadVorgangWithEingangWithAdditionalActions', () => { - - const vorgangWithEingangUri: ResourceUri = faker.internet.url(); - - it('should dispatch "loadVorgangWithEingang" action', () => { - facade.loadVorgangWithEingang(vorgangWithEingangUri); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.loadVorgangWithEingang({ resourceUri: vorgangWithEingangUri })); - }) - - it('should dispatch "loadVorgangWithEingang" action with additional actions', () => { - const additionalActions: AdditionalActions = { additionalSuccessAction: () => null, additionalFailureAction: (error: HttpErrorResponse) => null }; - - facade.loadVorgangWithEingangWithAdditionalActions(vorgangWithEingangUri, additionalActions); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.loadVorgangWithEingang({ resourceUri: vorgangWithEingangUri, additionalActions })); - }) - }) - - - describe('getAttachmentList', () => { - - it('should select from store', () => { - facade.getAttachmentList(); - - expect(store.select).toHaveBeenCalledWith(VorgangSelectors.attachmentList); - }) - }) - - describe('loadAttachmentList', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - it('should dispatch "loadAttachmentList" action', () => { - facade.loadAttachmentList(vorgangWithEingang); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.loadAttachmentList({ vorgangWithEingang })); - }) - }) - - describe('getRepresentationList', () => { - - it('should select from store', () => { - facade.getRepresentationList(); - - expect(store.select).toHaveBeenCalledWith(VorgangSelectors.representationList); - }) - }) - - describe('loadRepresentationList', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - it('should dispatch "loadRepresentationList" action', () => { - facade.loadRepresentationList(vorgangWithEingang); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.loadRepresentationList({ vorgangWithEingang })); - }) - }) - - describe('clearVorgangWithEingang', () => { - - it('should dispatch "clearnVorgangWithEingang" action', () => { - facade.clearVorgangWithEingang(); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.clearVorgangWithEingang()); - }) - }) - - describe('getForwardPendingCommand', () => { - - it('should select from store', () => { - facade.getForwardPendingCommand(); - - expect(store.select).toHaveBeenCalledWith(VorgangSelectors.forwardPendingCommand); - }) - }) - - describe('setForwardSingleCommandLoading', () => { - - it('should dispatch "setForwardingSingleCommandLoading" action', () => { - facade.setForwardSingleCommandLoading(); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.setForwardingSingleCommandLoading()); - }) - }) - - describe('setForwardSingleCommand', () => { - - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); - - it('should dispatch "setForwardSingleCommand" action', () => { - facade.setForwardSingleCommand(commandStateResource); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.setForwardingSingleCommand({ commandStateResource })); - }) - }) - - describe('getSendPostfachNachrichtPendingCommand', () => { - - it('should select from store', () => { - facade.getSendPostfachNachrichtPendingCommand(); - - expect(store.select).toHaveBeenCalledWith(VorgangSelectors.sendPostfachNachrichtPendingCommand); - }) - }) - - describe('setPendingSendPostfachMailSingleCommandLoading', () => { - - it('should dispatch "setSendPostfachNachrichtSingleCommandLoading" action', () => { - facade.setPendingSendPostfachMailSingleCommandLoading(); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.setSendPostfachNachrichtSingleCommandLoading()); - }) - }) - - describe('setPendingSendPostfachMailSingleCommand', () => { - - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); - - it('should dispatch "setSendPostfachNachrichtSingleCommand" action', () => { - facade.setPendingSendPostfachMailSingleCommand(commandStateResource); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.setSendPostfachNachrichtSingleCommand({ commandStateResource })); - }) - }) - - describe('getAssignUserCommand', () => { - - it('should select from store', () => { - facade.getAssignUserCommand(); - - expect(store.select).toHaveBeenCalledWith(VorgangSelectors.assignUserCommand); - }) - }) - - describe('assignUser', () => { - - it('should dispatch createCommand action', () => { - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const linkRel: ResourceUri = faker.internet.url(); - const command : CreateAssignUserCommand = { order: CommandOrder.ASSIGN_USER, body: { assignedTo: linkRel } }; - - facade.assignUser(vorgangWithEingang, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.ASSIGN, command })); - }) - }) - - describe('initAssignUser', () => { - - it('should dispatch initAssignUser action', () => { - facade.initAssignUser(); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.initAssignUser()); - }) - }) - - describe('getAssignUserCommand', () => { - - it('should select from store', () => { - facade.getAssignUserCommand(); - - expect(store.select).toHaveBeenCalledWith(VorgangSelectors.assignUserCommand); - }) - }) - - describe('getStatusCommand', () => { - - const order: CommandOrder = CommandOrder.VORGANG_ANNEHMEN - - it('should select from store', (done) => { - const selectorSpy = jest.spyOn(VorgangSelectors, 'getStatusCommand'); - - facade.getStatusCommand(order).subscribe(() => { - expect(selectorSpy).toHaveBeenCalledWith(order); - done(); - }); - - selectionSubject.next(createStateResource(createCommandResource())); - }) - }) - - describe('status actions', () => { - - const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const command: Command = createCommand(); - - describe('annehmen', () => { - - it('should dispatch action', () => { - facade.annehmen(vorgang, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ resource: vorgang, linkRel: VorgangWithEingangLinkRel.ANNEHMEN, command })); - }) - }) - - describe('bearbeiten', () => { - - it('should dispatch action', () => { - facade.bearbeiten(vorgang, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ resource: vorgang, linkRel: VorgangWithEingangLinkRel.BEARBEITEN, command })); - }) - }) - - describe('bescheiden', () => { - - it('should dispatch action', () => { - facade.bescheiden(vorgang, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ resource: vorgang, linkRel: VorgangWithEingangLinkRel.BESCHEIDEN, command })); - }) - }) - - describe('verwerfen', () => { - - it('should dispatch action', () => { - facade.verwerfen(vorgang, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ resource: vorgang, linkRel: VorgangWithEingangLinkRel.VERWERFEN, command })); - }) - }) - - describe('wiedereroeffnen', () => { - - it('should dispatch action', () => { - facade.wiedereroeffnen(vorgang, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ resource: vorgang, linkRel: VorgangWithEingangLinkRel.WIEDEREROEFFNEN, command })); - }) - }) - - describe('zurueckholen', () => { - - it('should dispatch action', () => { - facade.zurueckholen(vorgang, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ resource: vorgang, linkRel: VorgangWithEingangLinkRel.ZURUECKHOLEN, command })); - }) - }) - - describe('zurueckstellen', () => { - - it('should dispatch action', () => { - facade.zurueckstellen(vorgang, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ resource: vorgang, linkRel: VorgangWithEingangLinkRel.ZURUECKSTELLEN, command })); - }) - }) - - describe('abschliessen', () => { - - it('should dispatch action', () => { - facade.abschliessen(vorgang, command); - - expect(store.dispatch).toHaveBeenCalledWith(CommandActions.createCommand({ resource: vorgang, linkRel: VorgangWithEingangLinkRel.ABSCHLIESSEN, command })); - }) - }) - }) - - describe('getRevokeCommand', () => { - - it('should select from store', () => { - facade.getRevokeCommand(); - - expect(store.select).toHaveBeenCalledWith(VorgangSelectors.revokeCommand); - }) - }) - - - describe('getVorgangExport', () => { - - it('should select from store', () => { - facade.getVorgangExport(); - - expect(store.select).toHaveBeenCalledWith(VorgangSelectors.vorgangExport); - }) - }) - - describe('export', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - it('should dispatch action', () => { - facade.export(vorgangWithEingang); - - expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.exportVorgang({ vorgangWithEingang })); - }) - }) -}) \ No newline at end of file + describe('loadNextPage', () => { + it('should dispatch "loadNextPage" action', () => { + facade.loadNextPage(); + + expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.loadNextPage()); + }); + }); + + describe('getVorgangFilter', () => { + it('should return selected value', (done) => { + const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + + facade.getVorgangFilter().subscribe((view) => { + expect(view).toBe(vorgangFilter); + done(); + }); + + selectionSubject.next(vorgangFilter); + }); + }); + + describe('isVorgangFilterSelected', () => { + const isSelected: boolean = true; + const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + + it('should return selected value', (done) => { + facade.isVorgangFilterSelected(vorgangFilter).subscribe((selected) => { + expect(selected).toBe(isSelected); + done(); + }); + + selectionSubject.next(isSelected); + }); + + it('should call selector', (done) => { + const selectorSpy = jest.spyOn(VorgangSelectors, 'isVorgangFilterSelected'); + + facade.isVorgangFilterSelected(vorgangFilter).subscribe(() => { + expect(selectorSpy).toHaveBeenCalledWith(vorgangFilter); + done(); + }); + + selectionSubject.next(isSelected); + }); + }); + + describe('getVorgangView', () => { + it('should return selected value', (done) => { + const vorgangView: VorgangView = VorgangView.NEU; + + facade.getVorgangView().subscribe((view) => { + expect(view).toBe(vorgangView); + done(); + }); + + selectionSubject.next(vorgangView); + }); + }); + + describe('isVorgangViewSelected', () => { + const isSelected: boolean = true; + const vorgangView: VorgangView = VorgangView.NEU; + + it('should return selected value', (done) => { + facade.isVorgangViewSelected(vorgangView).subscribe((selected) => { + expect(selected).toBe(isSelected); + done(); + }); + + selectionSubject.next(isSelected); + }); + + it('should call selector', (done) => { + const selectorSpy = jest.spyOn(VorgangSelectors, 'isVorgangViewSelected'); + + facade.isVorgangViewSelected(vorgangView).subscribe(() => { + expect(selectorSpy).toHaveBeenCalledWith(vorgangView); + done(); + }); + + selectionSubject.next(isSelected); + }); + }); + + describe('getVorgangViewRoutePath', () => { + const path: string = 'dummyPath'; + const vorgangView: VorgangView = VorgangView.NEU; + + it('should return selected value', (done) => { + facade.getVorgangViewRoutePath(vorgangView).subscribe((routePath) => { + expect(routePath).toBe(path); + done(); + }); + + selectionSubject.next(path); + }); + + it('should call selector', (done) => { + const selectorSpy = jest.spyOn(VorgangSelectors, 'getVorgangViewRoutePath'); + + facade.getVorgangViewRoutePath(vorgangView).subscribe(() => { + expect(selectorSpy).toHaveBeenCalledWith(vorgangView); + done(); + }); + + selectionSubject.next(path); + }); + }); + + describe('getBackButtonUrl', () => { + it('should return selected value', (done) => { + const path: string = 'dummyPath'; + + facade.getBackButtonUrl().subscribe((routePath) => { + expect(routePath).toBe(path); + done(); + }); + + selectionSubject.next(path); + }); + }); + + //Search + describe('searchVorgaengeBy', () => { + const apiRoot: ApiRootResource = createApiRootResource(); + const searchString: string = SEARCH_STRING; + const linkRel: string = 'LinkRelationName'; + + it('should dispatch "searchVorgaengeBy" action', () => { + facade.searchVorgaengeBy(apiRoot, searchString, linkRel); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.searchVorgaengeBy({ apiRoot, searchString, linkRel }), + ); + }); + }); + + describe('searchForPreview', () => { + it('should dispatch "searchForPreview" action', () => { + facade.searchForPreview(SEARCH_STRING); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.searchForPreview({ string: SEARCH_STRING }), + ); + }); + }); + + describe('setSearchString', () => { + it('should dispatch "setSearchString" action', () => { + const searchString: string = 'dummySearchString'; + + facade.setSearchString(searchString); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.setSearchString({ string: searchString }), + ); + }); + }); + + describe('getSearchString', () => { + it('should return selected value', (done) => { + const searchString: string = 'dummySearchString'; + + facade.getSearchString().subscribe((selectedSearchString) => { + expect(selectedSearchString).toBe(searchString); + done(); + }); + + selectionSubject.next(searchString); + }); + }); + + describe('getSearchPreviewList', () => { + it('should return selected value', (done) => { + const saerchPreviewListStateResource: StateResource<VorgangListResource> = + createStateResource(createVorgangListResource()); + + facade.getSearchPreviewList().subscribe((searchPreviewList) => { + expect(searchPreviewList).toBe(saerchPreviewListStateResource); + done(); + }); + + selectionSubject.next(saerchPreviewListStateResource); + }); + }); + + describe('clearSearchPreviewList', () => { + it('should dispatch "clearSearchPreviewList" action', () => { + facade.clearSearchPreviewList(); + + expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.clearSearchPreviewList()); + }); + }); + + describe('clearSearchString', () => { + it('should dispatch "clearSearchString" action', () => { + facade.clearSearchString(); + + expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.clearSearchString()); + }); + }); + + //VorgangWithEingang + describe('getVorgangWithEingang', () => { + it('should return selected value', (done) => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + facade.getVorgangWithEingang().subscribe((selectedVorgangWithEingang) => { + expect(selectedVorgangWithEingang).toBe(vorgangWithEingang); + done(); + }); + + selectionSubject.next(vorgangWithEingang); + }); + }); + + describe('loadVorgangWithEingang', () => { + const vorgangWithEingangUri: ResourceUri = faker.internet.url(); + + it('should dispatch "loadVorgangWithEingang" action', () => { + facade.loadVorgangWithEingang(vorgangWithEingangUri); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.loadVorgangWithEingang({ resourceUri: vorgangWithEingangUri }), + ); + }); + }); + + describe('loadVorgangWithEingangWithAdditionalActions', () => { + const vorgangWithEingangUri: ResourceUri = faker.internet.url(); + + it('should dispatch "loadVorgangWithEingang" action', () => { + facade.loadVorgangWithEingang(vorgangWithEingangUri); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.loadVorgangWithEingang({ resourceUri: vorgangWithEingangUri }), + ); + }); + + it('should dispatch "loadVorgangWithEingang" action with additional actions', () => { + const additionalActions: AdditionalActions = { + additionalSuccessAction: () => null, + additionalFailureAction: (error: HttpErrorResponse) => null, + }; + + facade.loadVorgangWithEingangWithAdditionalActions(vorgangWithEingangUri, additionalActions); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.loadVorgangWithEingang({ + resourceUri: vorgangWithEingangUri, + additionalActions, + }), + ); + }); + }); + + describe('getAttachmentList', () => { + it('should select from store', () => { + facade.getAttachmentList(); + + expect(store.select).toHaveBeenCalledWith(VorgangSelectors.attachmentList); + }); + }); + + describe('loadAttachmentList', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + it('should dispatch "loadAttachmentList" action', () => { + facade.loadAttachmentList(vorgangWithEingang); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.loadAttachmentList({ vorgangWithEingang }), + ); + }); + }); + + describe('getRepresentationList', () => { + it('should select from store', () => { + facade.getRepresentationList(); + + expect(store.select).toHaveBeenCalledWith(VorgangSelectors.representationList); + }); + }); + + describe('loadRepresentationList', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + it('should dispatch "loadRepresentationList" action', () => { + facade.loadRepresentationList(vorgangWithEingang); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.loadRepresentationList({ vorgangWithEingang }), + ); + }); + }); + + describe('clearVorgangWithEingang', () => { + it('should dispatch "clearnVorgangWithEingang" action', () => { + facade.clearVorgangWithEingang(); + + expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.clearVorgangWithEingang()); + }); + }); + + describe('getForwardPendingCommand', () => { + it('should select from store', () => { + facade.getForwardPendingCommand(); + + expect(store.select).toHaveBeenCalledWith(VorgangSelectors.forwardPendingCommand); + }); + }); + + describe('setForwardSingleCommandLoading', () => { + it('should dispatch "setForwardingSingleCommandLoading" action', () => { + facade.setForwardSingleCommandLoading(); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.setForwardingSingleCommandLoading(), + ); + }); + }); + + describe('setForwardSingleCommand', () => { + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + + it('should dispatch "setForwardSingleCommand" action', () => { + facade.setForwardSingleCommand(commandStateResource); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.setForwardingSingleCommand({ commandStateResource }), + ); + }); + }); + + describe('getSendPostfachNachrichtPendingCommand', () => { + it('should select from store', () => { + facade.getSendPostfachNachrichtPendingCommand(); + + expect(store.select).toHaveBeenCalledWith( + VorgangSelectors.sendPostfachNachrichtPendingCommand, + ); + }); + }); + + describe('setPendingSendPostfachMailSingleCommandLoading', () => { + it('should dispatch "setSendPostfachNachrichtSingleCommandLoading" action', () => { + facade.setPendingSendPostfachMailSingleCommandLoading(); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.setSendPostfachNachrichtSingleCommandLoading(), + ); + }); + }); + + describe('setPendingSendPostfachMailSingleCommand', () => { + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + + it('should dispatch "setSendPostfachNachrichtSingleCommand" action', () => { + facade.setPendingSendPostfachMailSingleCommand(commandStateResource); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.setSendPostfachNachrichtSingleCommand({ commandStateResource }), + ); + }); + }); + + describe('getAssignUserCommand', () => { + it('should select from store', () => { + facade.getAssignUserCommand(); + + expect(store.select).toHaveBeenCalledWith(VorgangSelectors.assignUserCommand); + }); + }); + + describe('assignUser', () => { + it('should dispatch createCommand action', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const linkRel: ResourceUri = faker.internet.url(); + const command: CreateAssignUserCommand = { + order: CommandOrder.ASSIGN_USER, + body: { assignedTo: linkRel }, + }; + + facade.assignUser(vorgangWithEingang, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.ASSIGN, + command, + }), + ); + }); + }); + + describe('initAssignUser', () => { + it('should dispatch initAssignUser action', () => { + facade.initAssignUser(); + + expect(store.dispatch).toHaveBeenCalledWith(VorgangActions.initAssignUser()); + }); + }); + + describe('getAssignUserCommand', () => { + it('should select from store', () => { + facade.getAssignUserCommand(); + + expect(store.select).toHaveBeenCalledWith(VorgangSelectors.assignUserCommand); + }); + }); + + describe('getStatusCommand', () => { + const order: CommandOrder = CommandOrder.VORGANG_ANNEHMEN; + + it('should select from store', (done) => { + const selectorSpy = jest.spyOn(VorgangSelectors, 'getStatusCommand'); + + facade.getStatusCommand(order).subscribe(() => { + expect(selectorSpy).toHaveBeenCalledWith(order); + done(); + }); + + selectionSubject.next(createStateResource(createCommandResource())); + }); + }); + + describe('status actions', () => { + const vorgang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const command: Command = createCommand(); + + describe('annehmen', () => { + it('should dispatch action', () => { + facade.annehmen(vorgang, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgang, + linkRel: VorgangWithEingangLinkRel.ANNEHMEN, + command, + }), + ); + }); + }); + + describe('bearbeiten', () => { + it('should dispatch action', () => { + facade.bearbeiten(vorgang, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgang, + linkRel: VorgangWithEingangLinkRel.BEARBEITEN, + command, + }), + ); + }); + }); + + describe('bescheiden', () => { + it('should dispatch action', () => { + facade.bescheiden(vorgang, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgang, + linkRel: VorgangWithEingangLinkRel.BESCHEIDEN, + command, + }), + ); + }); + }); + + describe('verwerfen', () => { + it('should dispatch action', () => { + facade.verwerfen(vorgang, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgang, + linkRel: VorgangWithEingangLinkRel.VERWERFEN, + command, + }), + ); + }); + }); + + describe('wiedereroeffnen', () => { + it('should dispatch action', () => { + facade.wiedereroeffnen(vorgang, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgang, + linkRel: VorgangWithEingangLinkRel.WIEDEREROEFFNEN, + command, + }), + ); + }); + }); + + describe('zurueckholen', () => { + it('should dispatch action', () => { + facade.zurueckholen(vorgang, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgang, + linkRel: VorgangWithEingangLinkRel.ZURUECKHOLEN, + command, + }), + ); + }); + }); + + describe('zurueckstellen', () => { + it('should dispatch action', () => { + facade.zurueckstellen(vorgang, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgang, + linkRel: VorgangWithEingangLinkRel.ZURUECKSTELLEN, + command, + }), + ); + }); + }); + + describe('abschliessen', () => { + it('should dispatch action', () => { + facade.abschliessen(vorgang, command); + + expect(store.dispatch).toHaveBeenCalledWith( + CommandActions.createCommand({ + resource: vorgang, + linkRel: VorgangWithEingangLinkRel.ABSCHLIESSEN, + command, + }), + ); + }); + }); + }); + + describe('getRevokeCommand', () => { + it('should select from store', () => { + facade.getRevokeCommand(); + + expect(store.select).toHaveBeenCalledWith(VorgangSelectors.revokeCommand); + }); + }); + + describe('getVorgangExport', () => { + it('should select from store', () => { + facade.getVorgangExport(); + + expect(store.select).toHaveBeenCalledWith(VorgangSelectors.vorgangExport); + }); + }); + + describe('export', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + it('should dispatch action', () => { + facade.export(vorgangWithEingang); + + expect(store.dispatch).toHaveBeenCalledWith( + VorgangActions.exportVorgang({ vorgangWithEingang }), + ); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.ts index 23f14b226e10ed6a517758360c69dc5d3ff6b7bf..79dd7e4bf3869222b18877599475179876ffc986 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.ts @@ -30,8 +30,22 @@ import { Store } from '@ngrx/store'; import { ResourceUri } from '@ngxp/rest'; import { Observable } from 'rxjs'; import { VorgangWithEingangLinkRel } from '../vorgang.linkrel'; -import { AdditionalActions, CreateAssignUserCommand, VorgangFilter, VorgangListResource, VorgangResource, VorgangStatistic, VorgangView, VorgangWithEingangResource } from '../vorgang.model'; -import { backButtonUrl, getStatusCommand, isVorgangFilterSelected, isVorgangViewSelected } from './vorgang.selectors'; +import { + AdditionalActions, + CreateAssignUserCommand, + VorgangFilter, + VorgangListResource, + VorgangResource, + VorgangStatistic, + VorgangView, + VorgangWithEingangResource, +} from '../vorgang.model'; +import { + backButtonUrl, + getStatusCommand, + isVorgangFilterSelected, + isVorgangViewSelected, +} from './vorgang.selectors'; import * as CommandActions from '../../../../command-shared/src/lib/+state/command.actions'; import * as VorgangActions from './vorgang.actions'; @@ -39,197 +53,275 @@ import * as VorgangSelectors from './vorgang.selectors'; @Injectable() export class VorgangFacade { - - constructor(private readonly store: Store) { } - - //VorgangList - public getVorgangList(): Observable<StateResource<VorgangListResource>> { - return this.store.select(VorgangSelectors.vorgangList); - } - - public loadVorgangList(apiRoot: ApiRootResource, linkRel: string): void { - this.store.dispatch(VorgangActions.loadVorgangList({ apiRoot, linkRel })); - } - - public getVorgangStatistic(): Observable<StateResource<VorgangStatistic>> { - return this.store.select(VorgangSelectors.vorgangStatistic); - } - - public getVorgaenge(): Observable<VorgangResource[]> { - return this.store.select(VorgangSelectors.vorgaenge); - } - - public loadNextPage(): void { - this.store.dispatch(VorgangActions.loadNextPage()); - } - - public getVorgangFilter(): Observable<VorgangFilter> { - return this.store.select(VorgangSelectors.vorgangFilter); - } - - public isVorgangFilterSelected(vorgangFilter: VorgangFilter): Observable<boolean> { - return this.store.select(isVorgangFilterSelected(vorgangFilter)); - } - - public getVorgangView(): Observable<VorgangView> { - return this.store.select(VorgangSelectors.vorgangView); - } - - public isVorgangViewSelected(vorgangView: VorgangView): Observable<boolean> { - return this.store.select(isVorgangViewSelected(vorgangView)); - } - - public getVorgangViewRoutePath(vorgangView: VorgangView): Observable<string> { - return this.store.select(VorgangSelectors.getVorgangViewRoutePath(vorgangView)); - } - - public getBackButtonUrl(): Observable<string> { - return this.store.select(backButtonUrl); - } - - //Search - public searchVorgaengeBy(apiRoot: ApiRootResource, searchString: string, linkRel: string): void { - this.store.dispatch(VorgangActions.searchVorgaengeBy({ apiRoot, searchString, linkRel })); - } - - public searchForPreview(searchString: string): void { - this.store.dispatch(VorgangActions.searchForPreview({ string: searchString })); - } - - public setSearchString(searchString: string): void { - this.store.dispatch(VorgangActions.setSearchString({ string: searchString })); - } - - public getSearchString(): Observable<string> { - return this.store.select(VorgangSelectors.searchString); - } - - public getSearchPreviewList(): Observable<StateResource<VorgangListResource>> { - return this.store.select(VorgangSelectors.searchPreviewList); - } - - public clearSearchPreviewList(): void { - this.store.dispatch(VorgangActions.clearSearchPreviewList()); - } - - public clearSearchString(): void { - this.store.dispatch(VorgangActions.clearSearchString()); - } - - //VorgangWithEingang - public getVorgangWithEingang(): Observable<StateResource<VorgangWithEingangResource>> { - return this.store.select(VorgangSelectors.vorgangWithEingang); - } - - public loadVorgangWithEingang(vorgangWithEingangUri: ResourceUri): void { - this.store.dispatch(VorgangActions.loadVorgangWithEingang({ resourceUri: vorgangWithEingangUri })); - } - - public loadVorgangWithEingangWithAdditionalActions(vorgangWithEingangUri: ResourceUri, additionalActions: AdditionalActions) { - this.store.dispatch(VorgangActions.loadVorgangWithEingang({ resourceUri: vorgangWithEingangUri, additionalActions })); - } - - public getAttachmentList(): Observable<StateResource<BinaryFileListResource>> { - return this.store.select(VorgangSelectors.attachmentList); - } - - public loadAttachmentList(vorgangWithEingang: VorgangWithEingangResource): void{ - this.store.dispatch(VorgangActions.loadAttachmentList({ vorgangWithEingang })); - } - - public getRepresentationList(): Observable<StateResource<BinaryFileListResource>> { - return this.store.select(VorgangSelectors.representationList); - } - - public loadRepresentationList(vorgangWithEingang: VorgangWithEingangResource): void { - this.store.dispatch(VorgangActions.loadRepresentationList({ vorgangWithEingang })); - } - - public clearVorgangWithEingang(): void { - this.store.dispatch(VorgangActions.clearVorgangWithEingang()); - } - - - public getForwardPendingCommand(): Observable<StateResource<CommandResource>> { - return this.store.select(VorgangSelectors.forwardPendingCommand); - } - public setForwardSingleCommandLoading(): void { - this.store.dispatch(VorgangActions.setForwardingSingleCommandLoading()) - } - public setForwardSingleCommand(commandStateResource: StateResource<CommandResource>): void { - this.store.dispatch(VorgangActions.setForwardingSingleCommand({ commandStateResource })); - } - - - public getSendPostfachNachrichtPendingCommand(): Observable<StateResource<CommandResource>> { - return this.store.select(VorgangSelectors.sendPostfachNachrichtPendingCommand); - } - public setPendingSendPostfachMailSingleCommandLoading(): void { - this.store.dispatch(VorgangActions.setSendPostfachNachrichtSingleCommandLoading()) - } - public setPendingSendPostfachMailSingleCommand(commandStateResource: StateResource<CommandResource>): void { - this.store.dispatch(VorgangActions.setSendPostfachNachrichtSingleCommand({ commandStateResource })); - } - - - public getAssignUserCommand(): Observable<StateResource<CommandResource>> { - return this.store.select(VorgangSelectors.assignUserCommand); - } - - public assignUser(vorgangWithEingang: VorgangWithEingangResource, command: CreateAssignUserCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.ASSIGN, command })) - } - - public initAssignUser(): void { - this.store.dispatch(VorgangActions.initAssignUser()); - } - - - public getStatusCommand(order: CommandOrder): Observable<StateResource<CommandResource>> { - return this.store.select(getStatusCommand(order)); - } - - public annehmen(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.ANNEHMEN, command })); - } - - public bearbeiten(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.BEARBEITEN, command })); - } - - public bescheiden(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.BESCHEIDEN, command })); - } - - public verwerfen(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.VERWERFEN, command })); - } - - public wiedereroeffnen(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.WIEDEREROEFFNEN, command })); - } - - public zurueckholen(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.ZURUECKHOLEN, command })); - } - - public zurueckstellen(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.ZURUECKSTELLEN, command })); - } - - public abschliessen(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { - this.store.dispatch(CommandActions.createCommand({ resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.ABSCHLIESSEN, command })); - } - - public getRevokeCommand(): Observable<StateResource<CommandResource>> { - return this.store.select(VorgangSelectors.revokeCommand); - } - - public getVorgangExport(): Observable<StateResource<boolean>> { - return this.store.select(VorgangSelectors.vorgangExport); - } - - public export(vorgangWithEingang: VorgangWithEingangResource): void { - this.store.dispatch(VorgangActions.exportVorgang({ vorgangWithEingang })); - } -} \ No newline at end of file + constructor(private readonly store: Store) {} + + //VorgangList + public getVorgangList(): Observable<StateResource<VorgangListResource>> { + return this.store.select(VorgangSelectors.vorgangList); + } + + public loadVorgangList(apiRoot: ApiRootResource, linkRel: string): void { + this.store.dispatch(VorgangActions.loadVorgangList({ apiRoot, linkRel })); + } + + public getVorgangStatistic(): Observable<StateResource<VorgangStatistic>> { + return this.store.select(VorgangSelectors.vorgangStatistic); + } + + public getVorgaenge(): Observable<VorgangResource[]> { + return this.store.select(VorgangSelectors.vorgaenge); + } + + public loadNextPage(): void { + this.store.dispatch(VorgangActions.loadNextPage()); + } + + public getVorgangFilter(): Observable<VorgangFilter> { + return this.store.select(VorgangSelectors.vorgangFilter); + } + + public isVorgangFilterSelected(vorgangFilter: VorgangFilter): Observable<boolean> { + return this.store.select(isVorgangFilterSelected(vorgangFilter)); + } + + public getVorgangView(): Observable<VorgangView> { + return this.store.select(VorgangSelectors.vorgangView); + } + + public isVorgangViewSelected(vorgangView: VorgangView): Observable<boolean> { + return this.store.select(isVorgangViewSelected(vorgangView)); + } + + public getVorgangViewRoutePath(vorgangView: VorgangView): Observable<string> { + return this.store.select(VorgangSelectors.getVorgangViewRoutePath(vorgangView)); + } + + public getBackButtonUrl(): Observable<string> { + return this.store.select(backButtonUrl); + } + + //Search + public searchVorgaengeBy(apiRoot: ApiRootResource, searchString: string, linkRel: string): void { + this.store.dispatch(VorgangActions.searchVorgaengeBy({ apiRoot, searchString, linkRel })); + } + + public searchForPreview(searchString: string): void { + this.store.dispatch(VorgangActions.searchForPreview({ string: searchString })); + } + + public setSearchString(searchString: string): void { + this.store.dispatch(VorgangActions.setSearchString({ string: searchString })); + } + + public getSearchString(): Observable<string> { + return this.store.select(VorgangSelectors.searchString); + } + + public getSearchPreviewList(): Observable<StateResource<VorgangListResource>> { + return this.store.select(VorgangSelectors.searchPreviewList); + } + + public clearSearchPreviewList(): void { + this.store.dispatch(VorgangActions.clearSearchPreviewList()); + } + + public clearSearchString(): void { + this.store.dispatch(VorgangActions.clearSearchString()); + } + + //VorgangWithEingang + public getVorgangWithEingang(): Observable<StateResource<VorgangWithEingangResource>> { + return this.store.select(VorgangSelectors.vorgangWithEingang); + } + + public loadVorgangWithEingang(vorgangWithEingangUri: ResourceUri): void { + this.store.dispatch( + VorgangActions.loadVorgangWithEingang({ resourceUri: vorgangWithEingangUri }), + ); + } + + public loadVorgangWithEingangWithAdditionalActions( + vorgangWithEingangUri: ResourceUri, + additionalActions: AdditionalActions, + ) { + this.store.dispatch( + VorgangActions.loadVorgangWithEingang({ + resourceUri: vorgangWithEingangUri, + additionalActions, + }), + ); + } + + public getAttachmentList(): Observable<StateResource<BinaryFileListResource>> { + return this.store.select(VorgangSelectors.attachmentList); + } + + public loadAttachmentList(vorgangWithEingang: VorgangWithEingangResource): void { + this.store.dispatch(VorgangActions.loadAttachmentList({ vorgangWithEingang })); + } + + public getRepresentationList(): Observable<StateResource<BinaryFileListResource>> { + return this.store.select(VorgangSelectors.representationList); + } + + public loadRepresentationList(vorgangWithEingang: VorgangWithEingangResource): void { + this.store.dispatch(VorgangActions.loadRepresentationList({ vorgangWithEingang })); + } + + public clearVorgangWithEingang(): void { + this.store.dispatch(VorgangActions.clearVorgangWithEingang()); + } + + public getForwardPendingCommand(): Observable<StateResource<CommandResource>> { + return this.store.select(VorgangSelectors.forwardPendingCommand); + } + public setForwardSingleCommandLoading(): void { + this.store.dispatch(VorgangActions.setForwardingSingleCommandLoading()); + } + public setForwardSingleCommand(commandStateResource: StateResource<CommandResource>): void { + this.store.dispatch(VorgangActions.setForwardingSingleCommand({ commandStateResource })); + } + + public getSendPostfachNachrichtPendingCommand(): Observable<StateResource<CommandResource>> { + return this.store.select(VorgangSelectors.sendPostfachNachrichtPendingCommand); + } + public setPendingSendPostfachMailSingleCommandLoading(): void { + this.store.dispatch(VorgangActions.setSendPostfachNachrichtSingleCommandLoading()); + } + public setPendingSendPostfachMailSingleCommand( + commandStateResource: StateResource<CommandResource>, + ): void { + this.store.dispatch( + VorgangActions.setSendPostfachNachrichtSingleCommand({ commandStateResource }), + ); + } + + public getAssignUserCommand(): Observable<StateResource<CommandResource>> { + return this.store.select(VorgangSelectors.assignUserCommand); + } + + public assignUser( + vorgangWithEingang: VorgangWithEingangResource, + command: CreateAssignUserCommand, + ): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.ASSIGN, + command, + }), + ); + } + + public initAssignUser(): void { + this.store.dispatch(VorgangActions.initAssignUser()); + } + + public getStatusCommand(order: CommandOrder): Observable<StateResource<CommandResource>> { + return this.store.select(getStatusCommand(order)); + } + + public annehmen(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.ANNEHMEN, + command, + }), + ); + } + + public bearbeiten(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.BEARBEITEN, + command, + }), + ); + } + + public bescheiden(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.BESCHEIDEN, + command, + }), + ); + } + + public verwerfen(vorgangWithEingang: VorgangWithEingangResource, command: CreateCommand): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.VERWERFEN, + command, + }), + ); + } + + public wiedereroeffnen( + vorgangWithEingang: VorgangWithEingangResource, + command: CreateCommand, + ): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.WIEDEREROEFFNEN, + command, + }), + ); + } + + public zurueckholen( + vorgangWithEingang: VorgangWithEingangResource, + command: CreateCommand, + ): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.ZURUECKHOLEN, + command, + }), + ); + } + + public zurueckstellen( + vorgangWithEingang: VorgangWithEingangResource, + command: CreateCommand, + ): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.ZURUECKSTELLEN, + command, + }), + ); + } + + public abschliessen( + vorgangWithEingang: VorgangWithEingangResource, + command: CreateCommand, + ): void { + this.store.dispatch( + CommandActions.createCommand({ + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.ABSCHLIESSEN, + command, + }), + ); + } + + public getRevokeCommand(): Observable<StateResource<CommandResource>> { + return this.store.select(VorgangSelectors.revokeCommand); + } + + public getVorgangExport(): Observable<StateResource<boolean>> { + return this.store.select(VorgangSelectors.vorgangExport); + } + + public export(vorgangWithEingang: VorgangWithEingangResource): void { + this.store.dispatch(VorgangActions.exportVorgang({ vorgangWithEingang })); + } +} diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.spec.ts index e70ab295d76c1406d39d653e0cbecf2708fd53f3..1605f0952ff8f546d8ca12a959ebe6c9ea633acf 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.spec.ts @@ -23,9 +23,22 @@ */ import { ApiRootResource } from '@alfa-client/api-root-shared'; import { BinaryFileListResource } from '@alfa-client/binary-file-shared'; -import { CommandListResource, CommandOrder, CommandResource, CreateCommand } from '@alfa-client/command-shared'; +import { + CommandListResource, + CommandOrder, + CommandResource, + CreateCommand, +} from '@alfa-client/command-shared'; import { RouteData } from '@alfa-client/navigation-shared'; -import { ApiError, ApiErrorAction, EMPTY_ARRAY, EMPTY_STRING, StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + ApiError, + ApiErrorAction, + EMPTY_ARRAY, + EMPTY_STRING, + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { HttpErrorResponse } from '@angular/common/http'; import { UrlSegment } from '@angular/router'; import { Action } from '@ngrx/store'; @@ -33,14 +46,38 @@ import { TypedAction } from '@ngrx/store/src/models'; import { Resource, ResourceUri } from '@ngxp/rest'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { createBinaryFileListResource } from 'libs/binary-file-shared/test/binary-file'; -import { createCommand, createCommandListResource, createCommandResource } from 'libs/command-shared/test/command'; +import { + createCommand, + createCommandListResource, + createCommandResource, +} from 'libs/command-shared/test/command'; import { createRouteData } from 'libs/navigation-shared/test/navigation-test-factory'; import { createDummyResource } from 'libs/tech-shared/test/resource'; -import { createVorgangListResource, createVorgangListResourceWithResource, createVorgangResource, createVorgangResources, createVorgangStatistic, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; +import { + createVorgangListResource, + createVorgangListResourceWithResource, + createVorgangResource, + createVorgangResources, + createVorgangStatistic, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; import { createApiError, createHttpErrorResponse } from '../../../../tech-shared/test/error'; -import { MEINE_ROUTE_PARAM, ROUTE_PARAM_BY_VORGANG_FILTER, ROUTE_PARAM_BY_VORGANG_VIEW, VORGANG_WITH_EINGANG_ROUTE_PARAM } from '../vorgang-navigation.util'; +import { + MEINE_ROUTE_PARAM, + ROUTE_PARAM_BY_VORGANG_FILTER, + ROUTE_PARAM_BY_VORGANG_VIEW, + VORGANG_WITH_EINGANG_ROUTE_PARAM, +} from '../vorgang-navigation.util'; import { VorgangListLinkRel } from '../vorgang.linkrel'; -import { StatusCommandMap, VorgangFilter, VorgangListResource, VorgangResource, VorgangStatistic, VorgangView, VorgangWithEingangResource } from '../vorgang.model'; +import { + StatusCommandMap, + VorgangFilter, + VorgangListResource, + VorgangResource, + VorgangStatistic, + VorgangView, + VorgangWithEingangResource, +} from '../vorgang.model'; import { VorgangListAction } from './vorgang.actions'; import { VorgangState, initialState, reducer } from './vorgang.reducer'; @@ -54,955 +91,983 @@ import * as Reducer from './vorgang.reducer'; jest.mock('@alfa-client/app-shared', () => mockAsEsModule('@alfa-client/app-shared')); - function mockAsEsModule(module: string) { - return { - __esModule: true, - ...jest.requireActual(module) - }; + return { + __esModule: true, + ...jest.requireActual(module), + }; } describe('Vorgang Reducer', () => { + describe('unknown action', () => { + it('should return current state', () => { + const action = {} as Action; + + const result = reducer(initialState, action); + + expect(result).toBe(initialState); + }); + }); + + describe('loadVorgangList', () => { + describe('on "loadVorgangList" action', () => { + it('should set loading to true', () => { + const action = VorgangActions.loadVorgangList({ + apiRoot: createApiRootResource(), + linkRel: 'dummyLinkRel', + }); + + const state: VorgangState = reducer(initialState, action); + + expect(state.vorgangList.loading).toBeTruthy(); + }); + }); + + describe('on "loadVorgangListSuccess" action', () => { + const vorgaenge: VorgangResource[] = createVorgangResources(); + const statistic: VorgangStatistic = createVorgangStatistic(); + const vorgangList: VorgangListResource = { + ...createVorgangListResourceWithResource(vorgaenge, [VorgangListLinkRel.NEXT]), + statistic, + }; + const action: VorgangListAction & TypedAction<string> = VorgangActions.loadVorgangListSuccess( + { vorgangList }, + ); + + it('should set loaded resource', () => { + const state: VorgangState = reducer(initialState, action); + + expect(state.vorgangList).toEqual(createStateResource(vorgangList)); + }); + + it('should set vorgaenge', () => { + const state: VorgangState = reducer(initialState, action); + + expect(state.vorgaenge.length).toBe(10); + expect(state.vorgaenge).toStrictEqual(vorgaenge); + }); + + it('should clear searchPreviewList', () => { + const state: VorgangState = reducer( + { ...initialState, searchPreviewList: createStateResource(createVorgangListResource()) }, + action, + ); + + expect(state.searchPreviewList).toEqual(createEmptyStateResource()); + }); + + it('should set vorgang statistic', () => { + const state: VorgangState = reducer(initialState, action); + + expect(state.vorgangStatistic).toEqual(createStateResource(statistic)); + }); + }); + + describe('on "loadVorgangListFailure" action', () => { + const apiError: ApiError = createApiError(); + const action: ApiErrorAction & TypedAction<string> = VorgangActions.loadVorgangListFailure({ + apiError, + }); + + it('should set apiError', () => { + const state: VorgangState = reducer(initialState, action); + + expect(state.vorgangList.error).toStrictEqual(apiError); + }); + + it('should clear searchPreviewList', () => { + const state: VorgangState = reducer(initialState, action); - describe('unknown action', () => { - - it('should return current state', () => { - const action = {} as Action; - - const result = reducer(initialState, action); - - expect(result).toBe(initialState); - }) - }) - - describe('loadVorgangList', () => { - - describe('on "loadVorgangList" action', () => { - - it('should set loading to true', () => { - const action = VorgangActions.loadVorgangList({ apiRoot: createApiRootResource(), linkRel: 'dummyLinkRel' }); - - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangList.loading).toBeTruthy(); - }) - }) - - describe('on "loadVorgangListSuccess" action', () => { - - const vorgaenge: VorgangResource[] = createVorgangResources(); - const statistic: VorgangStatistic = createVorgangStatistic(); - const vorgangList: VorgangListResource = { ...createVorgangListResourceWithResource(vorgaenge, [VorgangListLinkRel.NEXT]) , statistic }; - const action: VorgangListAction & TypedAction<string> = VorgangActions.loadVorgangListSuccess({ vorgangList }); - - it('should set loaded resource', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangList).toEqual(createStateResource(vorgangList)); - }) - - it('should set vorgaenge', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgaenge.length).toBe(10); - expect(state.vorgaenge).toStrictEqual(vorgaenge); - }) - - it('should clear searchPreviewList', () => { - const state: VorgangState = reducer({ ...initialState, searchPreviewList: createStateResource(createVorgangListResource()) }, action); - - expect(state.searchPreviewList).toEqual(createEmptyStateResource()); - }) - - it('should set vorgang statistic', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangStatistic).toEqual(createStateResource(statistic)); - }) - }) - - describe('on "loadVorgangListFailure" action', () => { - - const apiError: ApiError = createApiError(); - const action: ApiErrorAction & TypedAction<string> = VorgangActions.loadVorgangListFailure({ apiError }); - - it('should set apiError', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangList.error).toStrictEqual(apiError); - }) - - it('should clear searchPreviewList', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.searchPreviewList).toEqual(createEmptyStateResource()); - }) - }) - }) - - describe('loadNextPage', () => { - - describe('on "loadNextPage" action', () => { - - it('should set vorgangList loading to true', () => { - const action = VorgangActions.loadNextPage(); - - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangList.loading).toBeTruthy(); - }) - }) - - describe('on "loadNextPageSuccess" action', () => { - - const statistic: VorgangStatistic = createVorgangStatistic(); - const vorgangList: VorgangListResource = { ...createVorgangListResource() , statistic }; - const action: VorgangListAction & TypedAction<string> = VorgangActions.loadNextPageSuccess({ vorgangList }); - - it('should set vorgangList', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangList).toStrictEqual(createStateResource(vorgangList)); - }) - - it('should add vorgaenge', () => { - const state: VorgangState = reducer({ ...initialState, vorgaenge: [createVorgangResource()] }, action); - - expect(state.vorgaenge.length).toBe(11); - }) - - it('should set vorgang statistic', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangStatistic).toEqual(createStateResource(statistic)); - }) - }) - }) - - describe('searchVorgaengeBy', () => { - - describe('on "searchVorgaengeBy" action', () => { - - const apiRoot: ApiRootResource = createApiRootResource(); - const searchString: string = 'search like me'; - const linkRel: string = 'LinkRelationName'; - - const action = VorgangActions.searchVorgaengeBy({ apiRoot, searchString, linkRel }); - - it('should vorgangList loading', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangList.loading).toBeTruthy(); - }) - - it('should clear searchPreviewList', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.searchPreviewList).toStrictEqual(createEmptyStateResource()); - }) - }) - - describe('on "searchVorgaengeBySuccess" action', () => { - - const vorgaenge: VorgangResource[] = createVorgangResources(); - const statistic: VorgangStatistic = createVorgangStatistic(); - const vorgangList: VorgangListResource = { ...createVorgangListResourceWithResource(vorgaenge) , statistic }; - const action: VorgangListAction & TypedAction<string> = VorgangActions.searchVorgaengeBySuccess({ vorgangList }); - - it('should set vorgangList', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangList).toStrictEqual(createStateResource(vorgangList)); - }) - - it('should set vorgaenge', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgaenge).toBe(vorgaenge); - }) - - it('should clear searchPreviewList', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.searchPreviewList).toStrictEqual(createEmptyStateResource()); - }) - - it('should set vorgang statistic', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangStatistic).toEqual(createStateResource(statistic)); - }) - }) - - describe('on "searchVorgaengeByFailure" action', () => { - - const apiError: ApiError = createApiError(); - const httpErrorResponse: HttpErrorResponse = createHttpErrorResponse(apiError); - const action = VorgangActions.searchVorgaengeByFailure({ httpErrorResponse }); - - it('should set error', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangList.error).toStrictEqual(apiError); - }) - }) - }) - - describe('searchForPreview', () => { - - describe('on "searchForPreview" action', () => { - - const searchString: string = 'searchThisForMe'; - const action = VorgangActions.searchForPreview({ string: searchString }); - - it('should set loading to true', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.searchPreviewList.loading).toBeTruthy(); - }) - }) - - describe('on "searchForPreviewSuccess" action', () => { - - const vorgangList: VorgangListResource = createVorgangListResource(); - const action = VorgangActions.searchForPreviewSuccess({ vorgangList }); - - it('should set loading to true', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.searchPreviewList).toStrictEqual(createStateResource(vorgangList)); - }) - }) - - describe('on "searchForPreviewFailure" action', () => { - - const apiError: ApiError = createApiError(); - const httpErrorResponse: HttpErrorResponse = createHttpErrorResponse(apiError); - const action = VorgangActions.searchForPreviewFailure({ httpErrorResponse }); - - it('should set error', () => { - const state: VorgangState = reducer(initialState, action); - - expect(state.searchPreviewList.error).toStrictEqual(apiError); - }) - }) - }) - - describe('clearSearchPreviewList', () => { - - describe('on "clearSearchPreviewList" action', () => { - - it('should empty searchPreviewList', () => { - const action = VorgangActions.clearSearchPreviewList(); - - const state: VorgangState = reducer(initialState, action); - - expect(state.searchPreviewList).toStrictEqual(createEmptyStateResource()); - }) - }) - }) - - describe('on "updateCurrentRouteData" action', () => { - - it('should call updateByRouteData', () => { - - const spy = jest.spyOn(Reducer, 'updateByRouteData'); - const action = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); - - Reducer.reducer(initialState, action); - - expect(spy).toHaveBeenCalled(); - }) - }) - - describe('updateLocalStorage', () => { - - it('should update filter', () => { - const spy = jest.spyOn(Storage, 'setFilterIntoStorage'); - - Reducer.updateLocalStorage(VorgangFilter.MEINE_VORGAENGE, VorgangView.NEU); - - expect(spy).toHaveBeenCalledWith('meine'); - }) - - describe('update view', () => { - - it('should clear view if view is vorgangList', () => { - const spy = jest.spyOn(Storage, 'removeLocalStorageView'); - - Reducer.updateLocalStorage(VorgangFilter.MEINE_VORGAENGE, VorgangView.VORGANG_LIST); - - expect(spy).toHaveBeenCalled(); - }) - - it('should set to given view', () => { - const spy = jest.spyOn(Storage, 'setViewIntoStorage'); - - Reducer.updateLocalStorage(VorgangFilter.MEINE_VORGAENGE, VorgangView.ANGENOMMEN); - - expect(spy).toHaveBeenCalledWith('angenommen'); - }) - }) - }) - - describe('on "clearSearchString" action', () => { - - it('should empty searchString', () => { - const action = VorgangActions.clearSearchString(); - const emptySearchString: string = EMPTY_STRING; - - const state: VorgangState = reducer(initialState, action); - - expect(state.searchString).toStrictEqual(emptySearchString); - }) - }) - - //VorgangWithEingang - describe('vorgangWithEingang', () => { - - describe('on "loadVorgangWithEingang" action', () => { - - const resourceUri: ResourceUri = faker.internet.url(); - - it('should set loading to true', () => { - const action = VorgangActions.loadVorgangWithEingang({ resourceUri }); - - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangWithEingang.loading).toBeTruthy(); - }) - }) - - describe('on "loadVorgangWithEingangSuccess" action', () => { - - it('should set vorgangWithEingang', () => { - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); - - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangWithEingang.resource).toStrictEqual(vorgangWithEingang); - }) - - it('should set reload representationList', () => { - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); - - const state: VorgangState = reducer(initialState, action); - - expect(state.representationList.reload).toBeTruthy(); - }) - - it('should set reload attachmentList', () => { - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); - - const state: VorgangState = reducer(initialState, action); - - expect(state.attachmentList.reload).toBeTruthy(); - }) - }) - - describe('on "setReloadVorgangWithEingang" action', () => { - - it('should set vorgangWithEingang#reload to true', () => { - const action = VorgangActions.setReloadVorgangWithEingang(); - - const state: VorgangState = reducer(initialState, action); - - expect(state.vorgangWithEingang.reload).toBeTruthy(); - }) - }) - }) - - describe('attachmentList', () => { - - describe('on "loadAttachmentList" action', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - it('should set state resource loading', () => { - const action = VorgangActions.loadAttachmentList({ vorgangWithEingang }); - - const state: VorgangState = reducer(initialState, action); - - expect(state.attachmentList.loading).toBeTruthy(); - }) - }) - - describe('on "loadAttachmentListSuccess" action', () => { - - it('should set state resource', () => { - const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); - const action = VorgangActions.loadAttachmentListSuccess({ binaryFileList }); - - const state: VorgangState = reducer(initialState, action); - - expect(state.attachmentList.resource).toBe(binaryFileList); - }) - }) - }) - - describe('representationList', () => { - - describe('on "loadRepresentationList" action', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - it('should set state resource loading', () => { - const action = VorgangActions.loadRepresentationList({ vorgangWithEingang }); - - const state: VorgangState = reducer(initialState, action); - - expect(state.representationList.loading).toBeTruthy(); - }) - }) - - describe('on "loadRepresentationListSuccess" action', () => { - - it('should set state resource', () => { - const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); - const action = VorgangActions.loadRepresentationListSuccess({ binaryFileList }); - - const state: VorgangState = reducer(initialState, action); - - expect(state.representationList.resource).toBe(binaryFileList); - }) - }) - }) - - describe('pending commands', () => { - - describe('on "loadPendingCommandListSuccess" action', () => { + expect(state.searchPreviewList).toEqual(createEmptyStateResource()); + }); + }); + }); + + describe('loadNextPage', () => { + describe('on "loadNextPage" action', () => { + it('should set vorgangList loading to true', () => { + const action = VorgangActions.loadNextPage(); - it('should set forward command', () => { - const forwardCommand: CommandResource = { ...createCommandResource(), order: CommandOrder.REDIRECT_VORGANG }; - const commandList: CommandListResource = createCommandListResource([createCommandResource(), forwardCommand]); - const action = VorgangActions.loadPendingCommandListSuccess({ commandList }); + const state: VorgangState = reducer(initialState, action); - const state: VorgangState = reducer(initialState, action); + expect(state.vorgangList.loading).toBeTruthy(); + }); + }); - expect(state.forwardPendingCommand.resource).toBe(forwardCommand); - }) + describe('on "loadNextPageSuccess" action', () => { + const statistic: VorgangStatistic = createVorgangStatistic(); + const vorgangList: VorgangListResource = { ...createVorgangListResource(), statistic }; + const action: VorgangListAction & TypedAction<string> = VorgangActions.loadNextPageSuccess({ + vorgangList, + }); - it('should set send postfach nachricht command', () => { - const sendPostfachNachrichtCommand: CommandResource = { ...createCommandResource(), order: CommandOrder.SEND_POSTFACH_NACHRICHT }; - const commandList: CommandListResource = createCommandListResource([createCommandResource(), sendPostfachNachrichtCommand]); - const action = VorgangActions.loadPendingCommandListSuccess({ commandList }); + it('should set vorgangList', () => { + const state: VorgangState = reducer(initialState, action); + + expect(state.vorgangList).toStrictEqual(createStateResource(vorgangList)); + }); + + it('should add vorgaenge', () => { + const state: VorgangState = reducer( + { ...initialState, vorgaenge: [createVorgangResource()] }, + action, + ); - const state: VorgangState = reducer(initialState, action); + expect(state.vorgaenge.length).toBe(11); + }); - expect(state.sendPostfachNachrichtPendingCommand.resource).toBe(sendPostfachNachrichtCommand); - }) - }) - }) + it('should set vorgang statistic', () => { + const state: VorgangState = reducer(initialState, action); - describe('forwardPendingCommand', () => { + expect(state.vorgangStatistic).toEqual(createStateResource(statistic)); + }); + }); + }); - describe('on "setForwardingSingleCommandLoading" action', () => { + describe('searchVorgaengeBy', () => { + describe('on "searchVorgaengeBy" action', () => { + const apiRoot: ApiRootResource = createApiRootResource(); + const searchString: string = 'search like me'; + const linkRel: string = 'LinkRelationName'; - it('should set forward pending command loading', () => { - const action = VorgangActions.setForwardingSingleCommandLoading(); + const action = VorgangActions.searchVorgaengeBy({ apiRoot, searchString, linkRel }); - const state: VorgangState = reducer(initialState, action); + it('should vorgangList loading', () => { + const state: VorgangState = reducer(initialState, action); - expect(state.forwardPendingCommand.loading).toBeTruthy(); - }) - }) + expect(state.vorgangList.loading).toBeTruthy(); + }); - describe('on "setForwardingSingleCommand" action', () => { + it('should clear searchPreviewList', () => { + const state: VorgangState = reducer(initialState, action); - it('should set forward pending command', () => { - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); - const action = VorgangActions.setForwardingSingleCommand({ commandStateResource }); + expect(state.searchPreviewList).toStrictEqual(createEmptyStateResource()); + }); + }); - const state: VorgangState = reducer(initialState, action); + describe('on "searchVorgaengeBySuccess" action', () => { + const vorgaenge: VorgangResource[] = createVorgangResources(); + const statistic: VorgangStatistic = createVorgangStatistic(); + const vorgangList: VorgangListResource = { + ...createVorgangListResourceWithResource(vorgaenge), + statistic, + }; + const action: VorgangListAction & TypedAction<string> = + VorgangActions.searchVorgaengeBySuccess({ vorgangList }); - expect(state.forwardPendingCommand).toBe(commandStateResource); - }) - }) - }) + it('should set vorgangList', () => { + const state: VorgangState = reducer(initialState, action); - describe('sendPostfachNachrichtPendingCommand', () => { + expect(state.vorgangList).toStrictEqual(createStateResource(vorgangList)); + }); - describe('on "setSendPostfachNachrichtSingleCommandLoading" action', () => { + it('should set vorgaenge', () => { + const state: VorgangState = reducer(initialState, action); - it('should set send postfach nachricht pending command loading', () => { - const action = VorgangActions.setSendPostfachNachrichtSingleCommandLoading(); + expect(state.vorgaenge).toBe(vorgaenge); + }); - const state: VorgangState = reducer(initialState, action); + it('should clear searchPreviewList', () => { + const state: VorgangState = reducer(initialState, action); - expect(state.sendPostfachNachrichtPendingCommand.loading).toBeTruthy(); - }) - }) + expect(state.searchPreviewList).toStrictEqual(createEmptyStateResource()); + }); - describe('on "setSendPostfachNachrichtSingleCommand" action', () => { + it('should set vorgang statistic', () => { + const state: VorgangState = reducer(initialState, action); - it('should set forward pending command', () => { - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); - const action = VorgangActions.setSendPostfachNachrichtSingleCommand({ commandStateResource }); + expect(state.vorgangStatistic).toEqual(createStateResource(statistic)); + }); + }); - const state: VorgangState = reducer(initialState, action); + describe('on "searchVorgaengeByFailure" action', () => { + const apiError: ApiError = createApiError(); + const httpErrorResponse: HttpErrorResponse = createHttpErrorResponse(apiError); + const action = VorgangActions.searchVorgaengeByFailure({ httpErrorResponse }); - expect(state.sendPostfachNachrichtPendingCommand).toBe(commandStateResource); - }) - }) - }) + it('should set error', () => { + const state: VorgangState = reducer(initialState, action); - describe('initAssignUser', () => { + expect(state.vorgangList.error).toStrictEqual(apiError); + }); + }); + }); - it('should set reload true', () => { - const action = VorgangActions.initAssignUser(); + describe('searchForPreview', () => { + describe('on "searchForPreview" action', () => { + const searchString: string = 'searchThisForMe'; + const action = VorgangActions.searchForPreview({ string: searchString }); - const state: VorgangState = reducer(initialState, action); + it('should set loading to true', () => { + const state: VorgangState = reducer(initialState, action); - expect(state.assignUserCommand.reload).toBeTruthy(); - }) - }) + expect(state.searchPreviewList.loading).toBeTruthy(); + }); + }); + describe('on "searchForPreviewSuccess" action', () => { + const vorgangList: VorgangListResource = createVorgangListResource(); + const action = VorgangActions.searchForPreviewSuccess({ vorgangList }); - describe('publishConcurrentModificationAction', () => { + it('should set loading to true', () => { + const state: VorgangState = reducer(initialState, action); - it('should set vorgangWithEingang reload true', () => { - const action = CommandActions.publishConcurrentModificationAction(); + expect(state.searchPreviewList).toStrictEqual(createStateResource(vorgangList)); + }); + }); - const state: VorgangState = reducer(initialState, action); + describe('on "searchForPreviewFailure" action', () => { + const apiError: ApiError = createApiError(); + const httpErrorResponse: HttpErrorResponse = createHttpErrorResponse(apiError); + const action = VorgangActions.searchForPreviewFailure({ httpErrorResponse }); - expect(state.vorgangWithEingang.reload).toBeTruthy(); - }) - }) + it('should set error', () => { + const state: VorgangState = reducer(initialState, action); + expect(state.searchPreviewList.error).toStrictEqual(apiError); + }); + }); + }); - describe('createCommand', () => { + describe('clearSearchPreviewList', () => { + describe('on "clearSearchPreviewList" action', () => { + it('should empty searchPreviewList', () => { + const action = VorgangActions.clearSearchPreviewList(); - const resource: Resource = createDummyResource(); - const linkRel: ResourceUri = faker.internet.url(); - const command: CreateCommand = createCommand(); + const state: VorgangState = reducer(initialState, action); - it('should call getStatusCommandMapByCreatedCommand', () => { - const spy = jest.spyOn(Reducer, 'getStatusCommandMapByCreateCommand'); + expect(state.searchPreviewList).toStrictEqual(createEmptyStateResource()); + }); + }); + }); - const action = CommandActions.createCommand({ resource, linkRel, command }); + describe('on "updateCurrentRouteData" action', () => { + it('should call updateByRouteData', () => { + const spy = jest.spyOn(Reducer, 'updateByRouteData'); + const action = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); - reducer(initialState, action); + Reducer.reducer(initialState, action); - expect(spy).toHaveBeenCalled(); - }) + expect(spy).toHaveBeenCalled(); + }); + }); - it('should call getAssignUserCommandByCreateCommand', () => { - const spy = jest.spyOn(Reducer, 'getAssignUserCommandByCreateCommand'); + describe('updateLocalStorage', () => { + it('should update filter', () => { + const spy = jest.spyOn(Storage, 'setFilterIntoStorage'); - const action = CommandActions.createCommand({ resource, linkRel, command }); + Reducer.updateLocalStorage(VorgangFilter.MEINE_VORGAENGE, VorgangView.NEU); - reducer(initialState, action); + expect(spy).toHaveBeenCalledWith('meine'); + }); - expect(spy).toHaveBeenCalled(); - }) - }) + describe('update view', () => { + it('should clear view if view is vorgangList', () => { + const spy = jest.spyOn(Storage, 'removeLocalStorageView'); - describe('createCommandSuccess', () => { + Reducer.updateLocalStorage(VorgangFilter.MEINE_VORGAENGE, VorgangView.VORGANG_LIST); - const command: CommandResource = createCommandResource(); + expect(spy).toHaveBeenCalled(); + }); - it('should call getStatusCommandMapByCreateCommandSuccess', () => { - const spy = jest.spyOn(Reducer, 'getStatusCommandMapByCreateCommandSuccess'); + it('should set to given view', () => { + const spy = jest.spyOn(Storage, 'setViewIntoStorage'); - const action = CommandActions.createCommandSuccess({ command }); + Reducer.updateLocalStorage(VorgangFilter.MEINE_VORGAENGE, VorgangView.ANGENOMMEN); - reducer(initialState, action); + expect(spy).toHaveBeenCalledWith('angenommen'); + }); + }); + }); - expect(spy).toHaveBeenCalled(); - }) + describe('on "clearSearchString" action', () => { + it('should empty searchString', () => { + const action = VorgangActions.clearSearchString(); + const emptySearchString: string = EMPTY_STRING; - it('should call getAssignUserCommandByCreateCommandSuccess', () => { - const spy = jest.spyOn(Reducer, 'getAssignUserCommandByCreateCommandSuccess'); + const state: VorgangState = reducer(initialState, action); - const action = CommandActions.createCommandSuccess({ command }); + expect(state.searchString).toStrictEqual(emptySearchString); + }); + }); - reducer(initialState, action); + //VorgangWithEingang + describe('vorgangWithEingang', () => { + describe('on "loadVorgangWithEingang" action', () => { + const resourceUri: ResourceUri = faker.internet.url(); - expect(spy).toHaveBeenCalled(); - }) + it('should set loading to true', () => { + const action = VorgangActions.loadVorgangWithEingang({ resourceUri }); - it('should set vorgangWithEingang reload true', () => { - const action = CommandActions.createCommandSuccess({ command }); + const state: VorgangState = reducer(initialState, action); - const state: VorgangState = reducer(initialState, action); + expect(state.vorgangWithEingang.loading).toBeTruthy(); + }); + }); - expect(state.vorgangWithEingang.reload).toBeTruthy(); - }) - }) + describe('on "loadVorgangWithEingangSuccess" action', () => { + it('should set vorgangWithEingang', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); - describe('revokeCommand', () => { + const state: VorgangState = reducer(initialState, action); - const command: CommandResource = createCommandResource(); + expect(state.vorgangWithEingang.resource).toStrictEqual(vorgangWithEingang); + }); - it('should set revokeCommand loading true', () => { - const action = CommandActions.revokeCommand({ command }); + it('should set reload representationList', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); - const state: VorgangState = reducer(initialState, action); + const state: VorgangState = reducer(initialState, action); - expect(state.revokeCommand.loading).toBeTruthy(); - }) - }) + expect(state.representationList.reload).toBeTruthy(); + }); - describe('revokeCommandSuccess', () => { + it('should set reload attachmentList', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const action = VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }); - const command: CommandResource = createCommandResource(); + const state: VorgangState = reducer(initialState, action); - it('should clear statusCommandMap', () => { - const action = CommandActions.revokeCommandSuccess({ command }); + expect(state.attachmentList.reload).toBeTruthy(); + }); + }); - const state: VorgangState = reducer(initialState, action); + describe('on "setReloadVorgangWithEingang" action', () => { + it('should set vorgangWithEingang#reload to true', () => { + const action = VorgangActions.setReloadVorgangWithEingang(); - expect(state.statusCommandMap).toEqual({}); - }) + const state: VorgangState = reducer(initialState, action); - it('should set vorgangWithEingang reload true', () => { - const action = CommandActions.revokeCommandSuccess({ command }); + expect(state.vorgangWithEingang.reload).toBeTruthy(); + }); + }); + }); - const state: VorgangState = reducer(initialState, action); + describe('attachmentList', () => { + describe('on "loadAttachmentList" action', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - expect(state.vorgangWithEingang.reload).toBeTruthy(); - }) + it('should set state resource loading', () => { + const action = VorgangActions.loadAttachmentList({ vorgangWithEingang }); - it('should set revoke command', () => { - const action = CommandActions.revokeCommandSuccess({ command }); + const state: VorgangState = reducer(initialState, action); - const state: VorgangState = reducer(initialState, action); + expect(state.attachmentList.loading).toBeTruthy(); + }); + }); - expect(state.revokeCommand.resource).toBe(command); - }) - }) + describe('on "loadAttachmentListSuccess" action', () => { + it('should set state resource', () => { + const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); + const action = VorgangActions.loadAttachmentListSuccess({ binaryFileList }); - describe('getStatusCommandMapByCreateCommand', () => { + const state: VorgangState = reducer(initialState, action); - describe('on status command', () => { + expect(state.attachmentList.resource).toBe(binaryFileList); + }); + }); + }); - it('should set status order command loading true', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.VORGANG_ANNEHMEN }; + describe('representationList', () => { + describe('on "loadRepresentationList" action', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const statusCommandMap: StatusCommandMap = Reducer.getStatusCommandMapByCreateCommand(initialState, command); + it('should set state resource loading', () => { + const action = VorgangActions.loadRepresentationList({ vorgangWithEingang }); - expect(statusCommandMap[command.order].loading).toBeTruthy(); - }) - }) + const state: VorgangState = reducer(initialState, action); - describe('on other command', () => { + expect(state.representationList.loading).toBeTruthy(); + }); + }); - it('should return state value', () => { - const command: CommandResource = { ...createCommandResource(), order: 'quatsch' }; + describe('on "loadRepresentationListSuccess" action', () => { + it('should set state resource', () => { + const binaryFileList: BinaryFileListResource = createBinaryFileListResource(); + const action = VorgangActions.loadRepresentationListSuccess({ binaryFileList }); - const statusCommandMap: StatusCommandMap = Reducer.getStatusCommandMapByCreateCommand(initialState, command); + const state: VorgangState = reducer(initialState, action); - expect(statusCommandMap).toBe(initialState.statusCommandMap); - }) - }) - }) + expect(state.representationList.resource).toBe(binaryFileList); + }); + }); + }); - describe('getStatusCommandMapByCreateCommandSuccess', () => { + describe('pending commands', () => { + describe('on "loadPendingCommandListSuccess" action', () => { + it('should set forward command', () => { + const forwardCommand: CommandResource = { + ...createCommandResource(), + order: CommandOrder.REDIRECT_VORGANG, + }; + const commandList: CommandListResource = createCommandListResource([ + createCommandResource(), + forwardCommand, + ]); + const action = VorgangActions.loadPendingCommandListSuccess({ commandList }); - describe('on status command', () => { + const state: VorgangState = reducer(initialState, action); - it('should set status order command', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.VORGANG_ANNEHMEN }; + expect(state.forwardPendingCommand.resource).toBe(forwardCommand); + }); - const statusCommandMap: StatusCommandMap = Reducer.getStatusCommandMapByCreateCommandSuccess(initialState, command); + it('should set send postfach nachricht command', () => { + const sendPostfachNachrichtCommand: CommandResource = { + ...createCommandResource(), + order: CommandOrder.SEND_POSTFACH_NACHRICHT, + }; + const commandList: CommandListResource = createCommandListResource([ + createCommandResource(), + sendPostfachNachrichtCommand, + ]); + const action = VorgangActions.loadPendingCommandListSuccess({ commandList }); - expect(statusCommandMap[command.order].resource).toBe(command); - }) - }) + const state: VorgangState = reducer(initialState, action); - describe('on other command', () => { + expect(state.sendPostfachNachrichtPendingCommand.resource).toBe( + sendPostfachNachrichtCommand, + ); + }); + }); + }); - it('should return state value', () => { - const command: CommandResource = { ...createCommandResource(), order: 'quatsch' }; + describe('forwardPendingCommand', () => { + describe('on "setForwardingSingleCommandLoading" action', () => { + it('should set forward pending command loading', () => { + const action = VorgangActions.setForwardingSingleCommandLoading(); - const statusCommandMap: StatusCommandMap = Reducer.getStatusCommandMapByCreateCommandSuccess(initialState, command); + const state: VorgangState = reducer(initialState, action); - expect(statusCommandMap).toBe(initialState.statusCommandMap); - }) - }) - }) + expect(state.forwardPendingCommand.loading).toBeTruthy(); + }); + }); - describe('getAssignUserCommandByCreateCommand', () => { + describe('on "setForwardingSingleCommand" action', () => { + it('should set forward pending command', () => { + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + const action = VorgangActions.setForwardingSingleCommand({ commandStateResource }); - describe('on assignUser command', () => { + const state: VorgangState = reducer(initialState, action); - it('should set command loading true', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.ASSIGN_USER }; + expect(state.forwardPendingCommand).toBe(commandStateResource); + }); + }); + }); - const assignUserCommand: StateResource<CommandResource> = Reducer.getAssignUserCommandByCreateCommand(initialState, command); + describe('sendPostfachNachrichtPendingCommand', () => { + describe('on "setSendPostfachNachrichtSingleCommandLoading" action', () => { + it('should set send postfach nachricht pending command loading', () => { + const action = VorgangActions.setSendPostfachNachrichtSingleCommandLoading(); - expect(assignUserCommand.loading).toBeTruthy(); - }) - }) + const state: VorgangState = reducer(initialState, action); - describe('on other command', () => { + expect(state.sendPostfachNachrichtPendingCommand.loading).toBeTruthy(); + }); + }); - it('should return state value', () => { - const command: CommandResource = { ...createCommandResource(), order: 'quatsch' }; + describe('on "setSendPostfachNachrichtSingleCommand" action', () => { + it('should set forward pending command', () => { + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); + const action = VorgangActions.setSendPostfachNachrichtSingleCommand({ + commandStateResource, + }); - const assignUserCommand: StateResource<CommandResource> = Reducer.getAssignUserCommandByCreateCommand(initialState, command); + const state: VorgangState = reducer(initialState, action); - expect(assignUserCommand).toBe(initialState.assignUserCommand); - }) - }) - }) + expect(state.sendPostfachNachrichtPendingCommand).toBe(commandStateResource); + }); + }); + }); - describe('getAssignUserCommandByCreateCommandSuccess', () => { + describe('initAssignUser', () => { + it('should set reload true', () => { + const action = VorgangActions.initAssignUser(); - describe('on assignUser command', () => { + const state: VorgangState = reducer(initialState, action); - it('should set command', () => { - const command: CommandResource = { ...createCommandResource(), order: CommandOrder.ASSIGN_USER }; + expect(state.assignUserCommand.reload).toBeTruthy(); + }); + }); - const assignUserCommand: StateResource<CommandResource> = Reducer.getAssignUserCommandByCreateCommandSuccess(initialState, command); + describe('publishConcurrentModificationAction', () => { + it('should set vorgangWithEingang reload true', () => { + const action = CommandActions.publishConcurrentModificationAction(); - expect(assignUserCommand.resource).toBe(command); - }) - }) + const state: VorgangState = reducer(initialState, action); - describe('on other command', () => { + expect(state.vorgangWithEingang.reload).toBeTruthy(); + }); + }); - it('should return state value', () => { - const command: CommandResource = { ...createCommandResource(), order: 'quatsch' }; + describe('createCommand', () => { + const resource: Resource = createDummyResource(); + const linkRel: ResourceUri = faker.internet.url(); + const command: CreateCommand = createCommand(); - const assignUserCommand: StateResource<CommandResource> = Reducer.getAssignUserCommandByCreateCommandSuccess(initialState, command); + it('should call getStatusCommandMapByCreatedCommand', () => { + const spy = jest.spyOn(Reducer, 'getStatusCommandMapByCreateCommand'); - expect(assignUserCommand).toBe(initialState.assignUserCommand); - }) - }) - }) + const action = CommandActions.createCommand({ resource, linkRel, command }); - describe('vorgangExport', () => { + reducer(initialState, action); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + expect(spy).toHaveBeenCalled(); + }); - describe('on exportVorgang action', () => { + it('should call getAssignUserCommandByCreateCommand', () => { + const spy = jest.spyOn(Reducer, 'getAssignUserCommandByCreateCommand'); - it('should set stateResource loading', () => { - const action = VorgangActions.exportVorgang({ vorgangWithEingang }); + const action = CommandActions.createCommand({ resource, linkRel, command }); - const state: VorgangState = reducer(initialState, action); + reducer(initialState, action); - expect(state.vorgangExport.loading).toBeTruthy(); - }) - }) + expect(spy).toHaveBeenCalled(); + }); + }); - describe('on exportVorgangSuccess action', () => { + describe('createCommandSuccess', () => { + const command: CommandResource = createCommandResource(); - it('should clear stateResource', () => { - const action = VorgangActions.exportVorgangSuccess(); + it('should call getStatusCommandMapByCreateCommandSuccess', () => { + const spy = jest.spyOn(Reducer, 'getStatusCommandMapByCreateCommandSuccess'); - const state: VorgangState = reducer({ ...initialState, vorgangExport: createEmptyStateResource(true)}, action); + const action = CommandActions.createCommandSuccess({ command }); - expect(state.vorgangExport).toEqual(createStateResource(true)); - }) - }) - }) + reducer(initialState, action); - describe('updateByRouteData', () => { + expect(spy).toHaveBeenCalled(); + }); - describe('contains search route', () => { + it('should call getAssignUserCommandByCreateCommandSuccess', () => { + const spy = jest.spyOn(Reducer, 'getAssignUserCommandByCreateCommandSuccess'); - it('should set previewList reload on changed searchString', () => { - const action = NavigationActions.updateCurrentRouteData({ routeData: buildCurrentRouteData('search like me') }); - const state: VorgangState = reducer({ ...initialState, searchString: 'existingSearchString' }, action ); + const action = CommandActions.createCommandSuccess({ command }); - expect(state.searchPreviewList.reload).toBeTruthy(); - }) + reducer(initialState, action); - it('should keep searchString on same searchString', () => { - const searchString: string = 'existingSearchString'; - const action = NavigationActions.updateCurrentRouteData({ routeData: buildCurrentRouteData(searchString) }); + expect(spy).toHaveBeenCalled(); + }); - const state: VorgangState = reducer({ ...initialState, searchString }, action ); + it('should set vorgangWithEingang reload true', () => { + const action = CommandActions.createCommandSuccess({ command }); - expect(state.searchString).toEqual(searchString); - }) + const state: VorgangState = reducer(initialState, action); - function buildCurrentRouteData(searchString: string): RouteData { - const urlSegments: UrlSegment[] = [<any>{ path: MEINE_ROUTE_PARAM }, <any>{ path: ROUTE_PARAM_BY_VORGANG_VIEW[VorgangView.SEARCH] }, <any>{ path: searchString }]; - const queryParameter = { ['search']: searchString }; - return { ...createRouteData(), urlSegments, queryParameter }; - } - }) + expect(state.vorgangWithEingang.reload).toBeTruthy(); + }); + }); - describe('contains vorgangList route', () => { + describe('revokeCommand', () => { + const command: CommandResource = createCommandResource(); - describe('localStorage', () => { + it('should set revokeCommand loading true', () => { + const action = CommandActions.revokeCommand({ command }); - it('should be updated by given vorgangFilter and vorgangView', () => { - const urlSegments: UrlSegment[] = [<any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] }, { path: ROUTE_PARAM_BY_VORGANG_VIEW[VorgangView.ANGENOMMEN] }]; - const routeData: RouteData = { ...createRouteData(), urlSegments }; - const localStorageSpy = jest.spyOn(Reducer, 'updateLocalStorage'); + const state: VorgangState = reducer(initialState, action); - Reducer.updateByRouteData(initialState, routeData); + expect(state.revokeCommand.loading).toBeTruthy(); + }); + }); - expect(localStorageSpy).toHaveBeenCalledWith(VorgangFilter.ALLE, VorgangView.ANGENOMMEN); - }) + describe('revokeCommandSuccess', () => { + const command: CommandResource = createCommandResource(); - it('should be updated by given vorgangFilter and default view', () => { - const urlSegments: UrlSegment[] = [<any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] }]; - const routeData: RouteData = { ...createRouteData(), urlSegments }; - const localStorageSpy = jest.spyOn(Reducer, 'updateLocalStorage'); + it('should clear statusCommandMap', () => { + const action = CommandActions.revokeCommandSuccess({ command }); - Reducer.updateByRouteData(initialState, routeData); + const state: VorgangState = reducer(initialState, action); - expect(localStorageSpy).toHaveBeenCalledWith(VorgangFilter.ALLE, VorgangView.VORGANG_LIST); - }) - }) + expect(state.statusCommandMap).toEqual({}); + }); - describe('filter only', () => { + it('should set vorgangWithEingang reload true', () => { + const action = CommandActions.revokeCommandSuccess({ command }); - const urlSegments: UrlSegment[] = [<any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] }]; - const routeData: RouteData = { ...createRouteData(), urlSegments }; + const state: VorgangState = reducer(initialState, action); - it('should set reload vorgangList', () => { - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + expect(state.vorgangWithEingang.reload).toBeTruthy(); + }); - expect(state.vorgangList.reload).toBeTruthy(); - }) + it('should set revoke command', () => { + const action = CommandActions.revokeCommandSuccess({ command }); - it('should set vorgangView', () => { - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + const state: VorgangState = reducer(initialState, action); - expect(state.vorgangView).toBe(VorgangView.VORGANG_LIST); - }) + expect(state.revokeCommand.resource).toBe(command); + }); + }); - it('should set vorgangFilter', () => { - const routeData: RouteData = { ...createRouteData(), urlSegments: [<any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.MEINE_VORGAENGE] }] }; + describe('getStatusCommandMapByCreateCommand', () => { + describe('on status command', () => { + it('should set status order command loading true', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.VORGANG_ANNEHMEN, + }; - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + const statusCommandMap: StatusCommandMap = Reducer.getStatusCommandMapByCreateCommand( + initialState, + command, + ); - expect(state.vorgangFilter).toBe(VorgangFilter.MEINE_VORGAENGE); - }) + expect(statusCommandMap[command.order].loading).toBeTruthy(); + }); + }); - it('should clear vorgaenge', () => { - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + describe('on other command', () => { + it('should return state value', () => { + const command: CommandResource = { ...createCommandResource(), order: 'quatsch' }; - expect(state.vorgaenge).toBe(EMPTY_ARRAY); - }) - }) + const statusCommandMap: StatusCommandMap = Reducer.getStatusCommandMapByCreateCommand( + initialState, + command, + ); - describe('filter and view', () => { + expect(statusCommandMap).toBe(initialState.statusCommandMap); + }); + }); + }); - const urlSegments: UrlSegment[] = [<any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.MEINE_VORGAENGE] }, <any>{ path: ROUTE_PARAM_BY_VORGANG_VIEW[VorgangView.NEU] }]; - const routeData: RouteData = { ...createRouteData(), urlSegments }; + describe('getStatusCommandMapByCreateCommandSuccess', () => { + describe('on status command', () => { + it('should set status order command', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.VORGANG_ANNEHMEN, + }; - it('should set reload vorgangList', () => { - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + const statusCommandMap: StatusCommandMap = + Reducer.getStatusCommandMapByCreateCommandSuccess(initialState, command); - expect(state.vorgangList.reload).toBeTruthy(); - }) + expect(statusCommandMap[command.order].resource).toBe(command); + }); + }); - it('should set vorgangView', () => { - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + describe('on other command', () => { + it('should return state value', () => { + const command: CommandResource = { ...createCommandResource(), order: 'quatsch' }; - expect(state.vorgangView).toBe(VorgangView.NEU); - }) + const statusCommandMap: StatusCommandMap = + Reducer.getStatusCommandMapByCreateCommandSuccess(initialState, command); - it('should set VorgangFilter', () => { - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + expect(statusCommandMap).toBe(initialState.statusCommandMap); + }); + }); + }); + + describe('getAssignUserCommandByCreateCommand', () => { + describe('on assignUser command', () => { + it('should set command loading true', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.ASSIGN_USER, + }; + + const assignUserCommand: StateResource<CommandResource> = + Reducer.getAssignUserCommandByCreateCommand(initialState, command); + + expect(assignUserCommand.loading).toBeTruthy(); + }); + }); + + describe('on other command', () => { + it('should return state value', () => { + const command: CommandResource = { ...createCommandResource(), order: 'quatsch' }; + + const assignUserCommand: StateResource<CommandResource> = + Reducer.getAssignUserCommandByCreateCommand(initialState, command); + + expect(assignUserCommand).toBe(initialState.assignUserCommand); + }); + }); + }); + + describe('getAssignUserCommandByCreateCommandSuccess', () => { + describe('on assignUser command', () => { + it('should set command', () => { + const command: CommandResource = { + ...createCommandResource(), + order: CommandOrder.ASSIGN_USER, + }; + + const assignUserCommand: StateResource<CommandResource> = + Reducer.getAssignUserCommandByCreateCommandSuccess(initialState, command); + + expect(assignUserCommand.resource).toBe(command); + }); + }); + + describe('on other command', () => { + it('should return state value', () => { + const command: CommandResource = { ...createCommandResource(), order: 'quatsch' }; + + const assignUserCommand: StateResource<CommandResource> = + Reducer.getAssignUserCommandByCreateCommandSuccess(initialState, command); + + expect(assignUserCommand).toBe(initialState.assignUserCommand); + }); + }); + }); + + describe('vorgangExport', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + describe('on exportVorgang action', () => { + it('should set stateResource loading', () => { + const action = VorgangActions.exportVorgang({ vorgangWithEingang }); + + const state: VorgangState = reducer(initialState, action); + + expect(state.vorgangExport.loading).toBeTruthy(); + }); + }); + + describe('on exportVorgangSuccess action', () => { + it('should clear stateResource', () => { + const action = VorgangActions.exportVorgangSuccess(); + + const state: VorgangState = reducer( + { ...initialState, vorgangExport: createEmptyStateResource(true) }, + action, + ); + + expect(state.vorgangExport).toEqual(createStateResource(true)); + }); + }); + }); + + describe('updateByRouteData', () => { + describe('contains search route', () => { + it('should set previewList reload on changed searchString', () => { + const action = NavigationActions.updateCurrentRouteData({ + routeData: buildCurrentRouteData('search like me'), + }); + const state: VorgangState = reducer( + { ...initialState, searchString: 'existingSearchString' }, + action, + ); + + expect(state.searchPreviewList.reload).toBeTruthy(); + }); + + it('should keep searchString on same searchString', () => { + const searchString: string = 'existingSearchString'; + const action = NavigationActions.updateCurrentRouteData({ + routeData: buildCurrentRouteData(searchString), + }); + + const state: VorgangState = reducer({ ...initialState, searchString }, action); + + expect(state.searchString).toEqual(searchString); + }); + + function buildCurrentRouteData(searchString: string): RouteData { + const urlSegments: UrlSegment[] = [ + <any>{ path: MEINE_ROUTE_PARAM }, + <any>{ path: ROUTE_PARAM_BY_VORGANG_VIEW[VorgangView.SEARCH] }, + <any>{ path: searchString }, + ]; + const queryParameter = { ['search']: searchString }; + return { ...createRouteData(), urlSegments, queryParameter }; + } + }); + + describe('contains vorgangList route', () => { + describe('localStorage', () => { + it('should be updated by given vorgangFilter and vorgangView', () => { + const urlSegments: UrlSegment[] = [ + <any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] }, + { path: ROUTE_PARAM_BY_VORGANG_VIEW[VorgangView.ANGENOMMEN] }, + ]; + const routeData: RouteData = { ...createRouteData(), urlSegments }; + const localStorageSpy = jest.spyOn(Reducer, 'updateLocalStorage'); + + Reducer.updateByRouteData(initialState, routeData); + + expect(localStorageSpy).toHaveBeenCalledWith(VorgangFilter.ALLE, VorgangView.ANGENOMMEN); + }); + + it('should be updated by given vorgangFilter and default view', () => { + const urlSegments: UrlSegment[] = [ + <any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] }, + ]; + const routeData: RouteData = { ...createRouteData(), urlSegments }; + const localStorageSpy = jest.spyOn(Reducer, 'updateLocalStorage'); + + Reducer.updateByRouteData(initialState, routeData); + + expect(localStorageSpy).toHaveBeenCalledWith( + VorgangFilter.ALLE, + VorgangView.VORGANG_LIST, + ); + }); + }); + + describe('filter only', () => { + const urlSegments: UrlSegment[] = [ + <any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] }, + ]; + const routeData: RouteData = { ...createRouteData(), urlSegments }; + + it('should set reload vorgangList', () => { + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + + expect(state.vorgangList.reload).toBeTruthy(); + }); + + it('should set vorgangView', () => { + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + + expect(state.vorgangView).toBe(VorgangView.VORGANG_LIST); + }); + + it('should set vorgangFilter', () => { + const routeData: RouteData = { + ...createRouteData(), + urlSegments: [ + <any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.MEINE_VORGAENGE] }, + ], + }; + + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + + expect(state.vorgangFilter).toBe(VorgangFilter.MEINE_VORGAENGE); + }); + + it('should clear vorgaenge', () => { + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + + expect(state.vorgaenge).toBe(EMPTY_ARRAY); + }); + }); + + describe('filter and view', () => { + const urlSegments: UrlSegment[] = [ + <any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.MEINE_VORGAENGE] }, + <any>{ path: ROUTE_PARAM_BY_VORGANG_VIEW[VorgangView.NEU] }, + ]; + const routeData: RouteData = { ...createRouteData(), urlSegments }; - expect(state.vorgangFilter).toBe(VorgangFilter.MEINE_VORGAENGE); - }) + it('should set reload vorgangList', () => { + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); - it('should clear vorgaenge', () => { - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + expect(state.vorgangList.reload).toBeTruthy(); + }); - expect(state.vorgaenge).toBe(EMPTY_ARRAY); - }) - }) - }) + it('should set vorgangView', () => { + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); - describe('contains vorgang route', () => { + expect(state.vorgangView).toBe(VorgangView.NEU); + }); - const queryParameter = { [VORGANG_WITH_EINGANG_ROUTE_PARAM]: faker.internet.url() }; - const routeData: RouteData = { ...createRouteData(), queryParameter }; + it('should set VorgangFilter', () => { + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); - it('should set reload to vorgangWithEingang', () => { - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + expect(state.vorgangFilter).toBe(VorgangFilter.MEINE_VORGAENGE); + }); - expect(state.vorgangWithEingang).toEqual(createEmptyStateResource()); - }) + it('should clear vorgaenge', () => { + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); - it('should clear forwardPendingCommand', () => { - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + expect(state.vorgaenge).toBe(EMPTY_ARRAY); + }); + }); + }); - expect(state.forwardPendingCommand).toEqual(createEmptyStateResource()); - }) + describe('contains vorgang route', () => { + const queryParameter = { [VORGANG_WITH_EINGANG_ROUTE_PARAM]: faker.internet.url() }; + const routeData: RouteData = { ...createRouteData(), queryParameter }; - it('should clear sendPostfachNachrichtPendingCommand', () => { - const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); + it('should set reload to vorgangWithEingang', () => { + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); - expect(state.sendPostfachNachrichtPendingCommand).toEqual(createEmptyStateResource()); - }) - }) - }) + expect(state.vorgangWithEingang).toEqual(createEmptyStateResource()); + }); - describe('initialState', () => { + it('should clear forwardPendingCommand', () => { + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); - describe('vorgangStatistic', () => { + expect(state.forwardPendingCommand).toEqual(createEmptyStateResource()); + }); - describe('byStatus', () => { + it('should clear sendPostfachNachrichtPendingCommand', () => { + const state: VorgangState = Reducer.updateByRouteData(initialState, routeData); - it('should have null as neu', () => { - const vorgangStatistic: StateResource<VorgangStatistic> = Reducer.initialState.vorgangStatistic; + expect(state.sendPostfachNachrichtPendingCommand).toEqual(createEmptyStateResource()); + }); + }); + }); - expect(vorgangStatistic.resource.byStatus.neu).toBeNull(); - }) + describe('initialState', () => { + describe('vorgangStatistic', () => { + describe('byStatus', () => { + it('should have null as neu', () => { + const vorgangStatistic: StateResource<VorgangStatistic> = + Reducer.initialState.vorgangStatistic; - it('should have null as angenommen', () => { - const vorgangStatistic: StateResource<VorgangStatistic> = Reducer.initialState.vorgangStatistic; + expect(vorgangStatistic.resource.byStatus.neu).toBeNull(); + }); - expect(vorgangStatistic.resource.byStatus.angenommen).toBeNull(); - }) + it('should have null as angenommen', () => { + const vorgangStatistic: StateResource<VorgangStatistic> = + Reducer.initialState.vorgangStatistic; - it('should have null as inBearbeitung', () => { - const vorgangStatistic: StateResource<VorgangStatistic> = Reducer.initialState.vorgangStatistic; + expect(vorgangStatistic.resource.byStatus.angenommen).toBeNull(); + }); - expect(vorgangStatistic.resource.byStatus.inBearbeitung).toBeNull(); - }) + it('should have null as inBearbeitung', () => { + const vorgangStatistic: StateResource<VorgangStatistic> = + Reducer.initialState.vorgangStatistic; - it('should have null as beschieden', () => { - const vorgangStatistic: StateResource<VorgangStatistic> = Reducer.initialState.vorgangStatistic; + expect(vorgangStatistic.resource.byStatus.inBearbeitung).toBeNull(); + }); - expect(vorgangStatistic.resource.byStatus.beschieden).toBeNull(); - }) + it('should have null as beschieden', () => { + const vorgangStatistic: StateResource<VorgangStatistic> = + Reducer.initialState.vorgangStatistic; - it('should have null as abgeschlossen', () => { - const vorgangStatistic: StateResource<VorgangStatistic> = Reducer.initialState.vorgangStatistic; + expect(vorgangStatistic.resource.byStatus.beschieden).toBeNull(); + }); - expect(vorgangStatistic.resource.byStatus.abgeschlossen).toBeNull(); - }) + it('should have null as abgeschlossen', () => { + const vorgangStatistic: StateResource<VorgangStatistic> = + Reducer.initialState.vorgangStatistic; - it('should have null as verworfen', () => { - const vorgangStatistic: StateResource<VorgangStatistic> = Reducer.initialState.vorgangStatistic; + expect(vorgangStatistic.resource.byStatus.abgeschlossen).toBeNull(); + }); - expect(vorgangStatistic.resource.byStatus.verworfen).toBeNull(); - }) + it('should have null as verworfen', () => { + const vorgangStatistic: StateResource<VorgangStatistic> = + Reducer.initialState.vorgangStatistic; - it('should have null as zuLoeschen', () => { - const vorgangStatistic: StateResource<VorgangStatistic> = Reducer.initialState.vorgangStatistic; + expect(vorgangStatistic.resource.byStatus.verworfen).toBeNull(); + }); - expect(vorgangStatistic.resource.byStatus.zuLoeschen).toBeNull(); - }) - }) + it('should have null as zuLoeschen', () => { + const vorgangStatistic: StateResource<VorgangStatistic> = + Reducer.initialState.vorgangStatistic; + expect(vorgangStatistic.resource.byStatus.zuLoeschen).toBeNull(); + }); + }); - it('should have null as wiedervorlagen', () => { - const vorgangStatistic: StateResource<VorgangStatistic> = Reducer.initialState.vorgangStatistic; + it('should have null as wiedervorlagen', () => { + const vorgangStatistic: StateResource<VorgangStatistic> = + Reducer.initialState.vorgangStatistic; - expect(vorgangStatistic.resource.wiedervorlagen).toBeNull(); - }) + expect(vorgangStatistic.resource.wiedervorlagen).toBeNull(); + }); - it('should have false as existsWiedervorlageOverdue', () => { - const vorgangStatistic: StateResource<VorgangStatistic> = Reducer.initialState.vorgangStatistic; + it('should have false as existsWiedervorlageOverdue', () => { + const vorgangStatistic: StateResource<VorgangStatistic> = + Reducer.initialState.vorgangStatistic; - expect(vorgangStatistic.resource.existsWiedervorlageOverdue).toBeFalsy(); - }) - }) - }) -}); \ No newline at end of file + expect(vorgangStatistic.resource.existsWiedervorlageOverdue).toBeFalsy(); + }); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts index 8f46f23cfe60e9f62f37b10c19aac25d7d7dcd84..94216faa5f7884f6fa1252e711f49e26d957462c 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts @@ -21,17 +21,63 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { removeLocalStorageView, setFilterIntoStorage, setViewIntoStorage } from '@alfa-client/app-shared'; -import { BinaryFileListResource, LoadBinaryFileListSuccessProps } from '@alfa-client/binary-file-shared'; -import { CommandOrder, CommandProps, CommandResource, CommandStateResourceProps, CreateCommand, CreateCommandProps, LoadCommandListSuccessProps, getPendingCommandByOrder } from '@alfa-client/command-shared'; +import { + removeLocalStorageView, + setFilterIntoStorage, + setViewIntoStorage, +} from '@alfa-client/app-shared'; +import { + BinaryFileListResource, + LoadBinaryFileListSuccessProps, +} from '@alfa-client/binary-file-shared'; +import { + CommandOrder, + CommandProps, + CommandResource, + CommandStateResourceProps, + CreateCommand, + CreateCommandProps, + LoadCommandListSuccessProps, + getPendingCommandByOrder, +} from '@alfa-client/command-shared'; import { RouteData } from '@alfa-client/navigation-shared'; -import { ApiErrorAction, EMPTY_ARRAY, EMPTY_STRING, StateResource, createEmptyStateResource, createErrorStateResource, createStateResource, getApiErrorFromHttpErrorResponse } from '@alfa-client/tech-shared'; +import { + ApiErrorAction, + EMPTY_ARRAY, + EMPTY_STRING, + StateResource, + createEmptyStateResource, + createErrorStateResource, + createStateResource, + getApiErrorFromHttpErrorResponse, +} from '@alfa-client/tech-shared'; import { Action, ActionReducer, createReducer, on } from '@ngrx/store'; import { isNil } from 'lodash-es'; -import { ROUTE_PARAM_BY_VORGANG_FILTER, ROUTE_PARAM_BY_VORGANG_VIEW, getSearchString, getVorgangFilter, getVorgangView, isUebersichtsSeite, isVorgangPage } from '../vorgang-navigation.util'; -import { StatusCommandMap, VorgangFilter, VorgangListResource, VorgangResource, VorgangStatistic, VorgangView, VorgangWithEingangResource } from '../vorgang.model'; +import { + ROUTE_PARAM_BY_VORGANG_FILTER, + ROUTE_PARAM_BY_VORGANG_VIEW, + getSearchString, + getVorgangFilter, + getVorgangView, + isUebersichtsSeite, + isVorgangPage, +} from '../vorgang-navigation.util'; +import { + StatusCommandMap, + VorgangFilter, + VorgangListResource, + VorgangResource, + VorgangStatistic, + VorgangView, + VorgangWithEingangResource, +} from '../vorgang.model'; import { getVorgaengeFromList, isAssignUserCommand, isStatusCommand } from '../vorgang.util'; -import { HttpErrorAction, StringBasedProps, VorgangListAction, VorgangWithEingangAction } from './vorgang.actions'; +import { + HttpErrorAction, + StringBasedProps, + VorgangListAction, + VorgangWithEingangAction, +} from './vorgang.actions'; import * as CommandActions from '../../../../command-shared/src/lib/+state/command.actions'; import * as NavigationActions from '../../../../navigation-shared/src/lib/+state/navigation.actions'; @@ -41,355 +87,487 @@ import * as VorgangReducer from './vorgang.reducer'; export const VORGANG_FEATURE_KEY = 'VorgangState'; export interface VorgangPartialState { - readonly [VORGANG_FEATURE_KEY]: VorgangState; + readonly [VORGANG_FEATURE_KEY]: VorgangState; } export interface VorgangState { - vorgangList: StateResource<VorgangListResource>; - vorgaenge: VorgangResource[]; - vorgangStatistic: StateResource<VorgangStatistic>; - searchString: string; - searchPreviewList: StateResource<VorgangListResource>; - vorgangView: VorgangView; - vorgangFilter: VorgangFilter; - - vorgangWithEingang: StateResource<VorgangWithEingangResource>; - attachmentList: StateResource<BinaryFileListResource>; - representationList: StateResource<BinaryFileListResource>; - assignUserCommand: StateResource<CommandResource>; - forwardPendingCommand: StateResource<CommandResource>; - sendPostfachNachrichtPendingCommand: StateResource<CommandResource>; - statusCommandMap: StatusCommandMap; - revokeCommand: StateResource<CommandResource>; - vorgangExport: StateResource<boolean>; + vorgangList: StateResource<VorgangListResource>; + vorgaenge: VorgangResource[]; + vorgangStatistic: StateResource<VorgangStatistic>; + searchString: string; + searchPreviewList: StateResource<VorgangListResource>; + vorgangView: VorgangView; + vorgangFilter: VorgangFilter; + + vorgangWithEingang: StateResource<VorgangWithEingangResource>; + attachmentList: StateResource<BinaryFileListResource>; + representationList: StateResource<BinaryFileListResource>; + assignUserCommand: StateResource<CommandResource>; + forwardPendingCommand: StateResource<CommandResource>; + sendPostfachNachrichtPendingCommand: StateResource<CommandResource>; + statusCommandMap: StatusCommandMap; + revokeCommand: StateResource<CommandResource>; + vorgangExport: StateResource<boolean>; } export const initialState: VorgangState = { - vorgangList: createEmptyStateResource(), - vorgangStatistic: createStateResource(createEmptyVorgangStatistic()), - vorgaenge: EMPTY_ARRAY, - searchString: EMPTY_STRING, - searchPreviewList: createEmptyStateResource(), - vorgangView: VorgangView.VORGANG_LIST, - vorgangFilter: VorgangFilter.ALLE, - - vorgangWithEingang: createEmptyStateResource(), - attachmentList: createEmptyStateResource(), - representationList: createEmptyStateResource(), - assignUserCommand: createEmptyStateResource(), - forwardPendingCommand: createEmptyStateResource(), - sendPostfachNachrichtPendingCommand: createEmptyStateResource(), - statusCommandMap: <any>{}, - revokeCommand: createEmptyStateResource(), - vorgangExport: createEmptyStateResource(), + vorgangList: createEmptyStateResource(), + vorgangStatistic: createStateResource(createEmptyVorgangStatistic()), + vorgaenge: EMPTY_ARRAY, + searchString: EMPTY_STRING, + searchPreviewList: createEmptyStateResource(), + vorgangView: VorgangView.VORGANG_LIST, + vorgangFilter: VorgangFilter.ALLE, + + vorgangWithEingang: createEmptyStateResource(), + attachmentList: createEmptyStateResource(), + representationList: createEmptyStateResource(), + assignUserCommand: createEmptyStateResource(), + forwardPendingCommand: createEmptyStateResource(), + sendPostfachNachrichtPendingCommand: createEmptyStateResource(), + statusCommandMap: <any>{}, + revokeCommand: createEmptyStateResource(), + vorgangExport: createEmptyStateResource(), }; function createEmptyVorgangStatistic(): VorgangStatistic { - return { - byStatus: { - abgeschlossen: null, - angenommen: null, - neu: null, - inBearbeitung: null, - beschieden: null, - verworfen: null, - zuLoeschen: null - }, - wiedervorlagen: null, - existsWiedervorlageOverdue: false - }; + return { + byStatus: { + abgeschlossen: null, + angenommen: null, + neu: null, + inBearbeitung: null, + beschieden: null, + verworfen: null, + zuLoeschen: null, + }, + wiedervorlagen: null, + existsWiedervorlageOverdue: false, + }; } const vorgangReducer: ActionReducer<VorgangState, Action> = createReducer( - initialState, - - //VorgangList - on(VorgangActions.loadVorgangList, (state: VorgangState): VorgangState => ({ - ...state, - vorgangList: { ...state.vorgangList, loading: true } - })), - on(VorgangActions.loadVorgangListSuccess, (state: VorgangState, action: VorgangListAction) => ({ - ...state, - vorgangList: createStateResource<VorgangListResource>(action.vorgangList), - vorgaenge: getVorgaengeFromList(action.vorgangList), - vorgangStatistic: createStateResource(action.vorgangList.statistic), - searchPreviewList: createEmptyStateResource<VorgangListResource>() - })), - on(VorgangActions.loadVorgangListFailure, (state: VorgangState, action: ApiErrorAction): VorgangState => ({ - ...state, - vorgangList: createErrorStateResource(action.apiError), - searchPreviewList: createEmptyStateResource() - })), - - - on(VorgangActions.loadNextPage, (state: VorgangState): VorgangState => ({ - ...state, - vorgangList: { ...state.vorgangList, loading: true }, - })), - on(VorgangActions.loadNextPageSuccess, (state, action: VorgangListAction): VorgangState => ({ - ...state, - vorgangList: createStateResource<VorgangListResource>(action.vorgangList), - vorgaenge: [...state.vorgaenge].concat(getVorgaengeFromList(action.vorgangList)), - vorgangStatistic: createStateResource(action.vorgangList.statistic) - })), - - - //Search - on(VorgangActions.searchVorgaengeBy, (state: VorgangState): VorgangState => ({ - ...state, - vorgangList: { ...state.vorgangList, loading: true }, - vorgaenge: EMPTY_ARRAY, - searchPreviewList: createEmptyStateResource() - })), - on(VorgangActions.searchVorgaengeBySuccess, (state: VorgangState, action: VorgangListAction): VorgangState => ({ - ...state, - vorgangList: createStateResource<VorgangListResource>(action.vorgangList), - vorgaenge: getVorgaengeFromList(action.vorgangList), - vorgangStatistic: createStateResource(action.vorgangList.statistic), - searchPreviewList: createEmptyStateResource<VorgangListResource>() - })), - on(VorgangActions.searchVorgaengeByFailure, (state: VorgangState, action: HttpErrorAction): VorgangState => ({ - ...state, - vorgangList: createErrorStateResource(getApiErrorFromHttpErrorResponse(action.httpErrorResponse)), - searchPreviewList: createEmptyStateResource() - })), - - - on(VorgangActions.setSearchString, (state: VorgangState, props: StringBasedProps): VorgangState => ({ - ...state, - searchString: props.string, - searchPreviewList: clearPreviewList(props) ? createEmptyStateResource() : { ...state.searchPreviewList, reload: true } - })), - on(VorgangActions.searchForPreview, (state: VorgangState): VorgangState => ({ - ...state, - searchPreviewList: { ...state.searchPreviewList, loading: true } - })), - on(VorgangActions.searchForPreviewSuccess, (state: VorgangState, action: VorgangListAction): VorgangState => ({ - ...state, - searchPreviewList: createStateResource<VorgangListResource>(action.vorgangList) - })), - on(VorgangActions.searchForPreviewFailure, (state: VorgangState, action: HttpErrorAction): VorgangState => ({ - ...state, - searchPreviewList: createErrorStateResource(getApiErrorFromHttpErrorResponse(action.httpErrorResponse)) - })), - - - on(VorgangActions.clearSearchPreviewList, (state: VorgangState): VorgangState => ({ - ...state, - searchPreviewList: createEmptyStateResource() - })), - - on(VorgangActions.clearSearchString, (state: VorgangState): VorgangState => ({ - ...state, - searchString: EMPTY_STRING - })), - - on(VorgangActions.setSearchString, (state: VorgangState, action: StringBasedProps): VorgangState => ({ - ...state, - searchString: action.string - })), - - - //VorgangWithEingang - on(VorgangActions.loadVorgangWithEingang, (state: VorgangState): VorgangState => ({ - ...state, - vorgangWithEingang: { ...state.vorgangWithEingang, loading: true } - })), - on(VorgangActions.loadVorgangWithEingangSuccess, (state: VorgangState, props: VorgangWithEingangAction): VorgangState => ({ - ...state, - vorgangWithEingang: createStateResource(props.vorgangWithEingang), - representationList: { ...state.representationList, reload: true }, - attachmentList: { ...state.attachmentList, reload: true } - })), - on(VorgangActions.loadVorgangWithEingangFailure, (state: VorgangState, props: ApiErrorAction): VorgangState => ({ - ...state, - vorgangWithEingang: createErrorStateResource(props.apiError) - })), - on(VorgangActions.setReloadVorgangWithEingang, (state: VorgangState): VorgangState => ({ - ...state, - vorgangWithEingang: { ...state.vorgangWithEingang, reload: true } - })), - - - on(VorgangActions.loadAttachmentList, (state: VorgangState): VorgangState => ({ - ...state, - attachmentList: { ...state.attachmentList, loading: true } - })), - on(VorgangActions.loadAttachmentListSuccess, (state: VorgangState, props: LoadBinaryFileListSuccessProps): VorgangState => ({ - ...state, - attachmentList: createStateResource(props.binaryFileList) - })), - - on(VorgangActions.loadRepresentationList, (state: VorgangState): VorgangState => ({ - ...state, - representationList: { ...state.representationList, loading: true } - })), - on(VorgangActions.loadRepresentationListSuccess, (state: VorgangState, props: LoadBinaryFileListSuccessProps): VorgangState => ({ - ...state, - representationList: createStateResource(props.binaryFileList) - })), - - - on(VorgangActions.loadPendingCommandListSuccess, (state: VorgangState, props: LoadCommandListSuccessProps): VorgangState => ({ - ...state, - forwardPendingCommand: createStateResource(getPendingCommandByOrder(props.commandList, [CommandOrder.REDIRECT_VORGANG])), - sendPostfachNachrichtPendingCommand: createStateResource(getPendingCommandByOrder(props.commandList, [CommandOrder.SEND_POSTFACH_NACHRICHT])) - })), - - on(VorgangActions.setForwardingSingleCommandLoading, (state: VorgangState): VorgangState => ({ - ...state, - forwardPendingCommand: createEmptyStateResource(true), - })), - on(VorgangActions.setForwardingSingleCommand, (state: VorgangState, props: CommandStateResourceProps): VorgangState => ({ - ...state, - forwardPendingCommand: props.commandStateResource, - })), - - on(VorgangActions.setSendPostfachNachrichtSingleCommandLoading, (state: VorgangState): VorgangState => ({ - ...state, - sendPostfachNachrichtPendingCommand: createEmptyStateResource(true), - })), - on(VorgangActions.setSendPostfachNachrichtSingleCommand, (state: VorgangState, props: CommandStateResourceProps): VorgangState => ({ - ...state, - sendPostfachNachrichtPendingCommand: props.commandStateResource, - })), - - - on(VorgangActions.initAssignUser, (state: VorgangState): VorgangState => ({ - ...state, - assignUserCommand: { ...state.assignUserCommand, reload: true } - })), - - - on(VorgangActions.exportVorgang, (state: VorgangState): VorgangState => ({ - ...state, - vorgangExport: createEmptyStateResource(true) - })), - on(VorgangActions.exportVorgangSuccess, (state: VorgangState): VorgangState => ({ - ...state, - vorgangExport: createStateResource(true) - })), - - - //Command - on(CommandActions.createCommand, (state, props: CreateCommandProps): VorgangState => { - return {...state, - statusCommandMap: VorgangReducer.getStatusCommandMapByCreateCommand(state, props.command), - assignUserCommand: VorgangReducer.getAssignUserCommandByCreateCommand(state, props.command) - }; - }), - on(CommandActions.createCommandSuccess, (state, props: CommandProps): VorgangState => { - return {...state, - statusCommandMap: VorgangReducer.getStatusCommandMapByCreateCommandSuccess(state, props.command), - assignUserCommand: VorgangReducer.getAssignUserCommandByCreateCommandSuccess(state, props.command), - vorgangWithEingang: VorgangReducer.getVorgangWithEingangStateResourceByCreateCommandSucces(state, props.command) - }; - }), - on(CommandActions.revokeCommand, (state): VorgangState => { - return { ...state, revokeCommand: createEmptyStateResource(true) }; - }), - on(CommandActions.revokeCommandSuccess, (state, props: CommandProps): VorgangState => { - return {...state, - statusCommandMap: <any>{}, - vorgangWithEingang: { ...state.vorgangWithEingang, reload: true }, - revokeCommand: createStateResource(props.command) - } - }), - on(CommandActions.publishConcurrentModificationAction, (state): VorgangState => { - return { ...state, vorgangWithEingang: { ...state.vorgangWithEingang, reload: true } }; - }), - - - //Navigation - on(NavigationActions.updateCurrentRouteData, (state, action): VorgangState => { - return VorgangReducer.updateByRouteData(state, action.routeData); - }), + initialState, + + //VorgangList + on( + VorgangActions.loadVorgangList, + (state: VorgangState): VorgangState => ({ + ...state, + vorgangList: { ...state.vorgangList, loading: true }, + }), + ), + on(VorgangActions.loadVorgangListSuccess, (state: VorgangState, action: VorgangListAction) => ({ + ...state, + vorgangList: createStateResource<VorgangListResource>(action.vorgangList), + vorgaenge: getVorgaengeFromList(action.vorgangList), + vorgangStatistic: createStateResource(action.vorgangList.statistic), + searchPreviewList: createEmptyStateResource<VorgangListResource>(), + })), + on( + VorgangActions.loadVorgangListFailure, + (state: VorgangState, action: ApiErrorAction): VorgangState => ({ + ...state, + vorgangList: createErrorStateResource(action.apiError), + searchPreviewList: createEmptyStateResource(), + }), + ), + + on( + VorgangActions.loadNextPage, + (state: VorgangState): VorgangState => ({ + ...state, + vorgangList: { ...state.vorgangList, loading: true }, + }), + ), + on( + VorgangActions.loadNextPageSuccess, + (state, action: VorgangListAction): VorgangState => ({ + ...state, + vorgangList: createStateResource<VorgangListResource>(action.vorgangList), + vorgaenge: [...state.vorgaenge].concat(getVorgaengeFromList(action.vorgangList)), + vorgangStatistic: createStateResource(action.vorgangList.statistic), + }), + ), + + //Search + on( + VorgangActions.searchVorgaengeBy, + (state: VorgangState): VorgangState => ({ + ...state, + vorgangList: { ...state.vorgangList, loading: true }, + vorgaenge: EMPTY_ARRAY, + searchPreviewList: createEmptyStateResource(), + }), + ), + on( + VorgangActions.searchVorgaengeBySuccess, + (state: VorgangState, action: VorgangListAction): VorgangState => ({ + ...state, + vorgangList: createStateResource<VorgangListResource>(action.vorgangList), + vorgaenge: getVorgaengeFromList(action.vorgangList), + vorgangStatistic: createStateResource(action.vorgangList.statistic), + searchPreviewList: createEmptyStateResource<VorgangListResource>(), + }), + ), + on( + VorgangActions.searchVorgaengeByFailure, + (state: VorgangState, action: HttpErrorAction): VorgangState => ({ + ...state, + vorgangList: createErrorStateResource( + getApiErrorFromHttpErrorResponse(action.httpErrorResponse), + ), + searchPreviewList: createEmptyStateResource(), + }), + ), + + on( + VorgangActions.setSearchString, + (state: VorgangState, props: StringBasedProps): VorgangState => ({ + ...state, + searchString: props.string, + searchPreviewList: + clearPreviewList(props) ? + createEmptyStateResource() + : { ...state.searchPreviewList, reload: true }, + }), + ), + on( + VorgangActions.searchForPreview, + (state: VorgangState): VorgangState => ({ + ...state, + searchPreviewList: { ...state.searchPreviewList, loading: true }, + }), + ), + on( + VorgangActions.searchForPreviewSuccess, + (state: VorgangState, action: VorgangListAction): VorgangState => ({ + ...state, + searchPreviewList: createStateResource<VorgangListResource>(action.vorgangList), + }), + ), + on( + VorgangActions.searchForPreviewFailure, + (state: VorgangState, action: HttpErrorAction): VorgangState => ({ + ...state, + searchPreviewList: createErrorStateResource( + getApiErrorFromHttpErrorResponse(action.httpErrorResponse), + ), + }), + ), + + on( + VorgangActions.clearSearchPreviewList, + (state: VorgangState): VorgangState => ({ + ...state, + searchPreviewList: createEmptyStateResource(), + }), + ), + + on( + VorgangActions.clearSearchString, + (state: VorgangState): VorgangState => ({ + ...state, + searchString: EMPTY_STRING, + }), + ), + + on( + VorgangActions.setSearchString, + (state: VorgangState, action: StringBasedProps): VorgangState => ({ + ...state, + searchString: action.string, + }), + ), + + //VorgangWithEingang + on( + VorgangActions.loadVorgangWithEingang, + (state: VorgangState): VorgangState => ({ + ...state, + vorgangWithEingang: { ...state.vorgangWithEingang, loading: true }, + }), + ), + on( + VorgangActions.loadVorgangWithEingangSuccess, + (state: VorgangState, props: VorgangWithEingangAction): VorgangState => ({ + ...state, + vorgangWithEingang: createStateResource(props.vorgangWithEingang), + representationList: { ...state.representationList, reload: true }, + attachmentList: { ...state.attachmentList, reload: true }, + }), + ), + on( + VorgangActions.loadVorgangWithEingangFailure, + (state: VorgangState, props: ApiErrorAction): VorgangState => ({ + ...state, + vorgangWithEingang: createErrorStateResource(props.apiError), + }), + ), + on( + VorgangActions.setReloadVorgangWithEingang, + (state: VorgangState): VorgangState => ({ + ...state, + vorgangWithEingang: { ...state.vorgangWithEingang, reload: true }, + }), + ), + + on( + VorgangActions.loadAttachmentList, + (state: VorgangState): VorgangState => ({ + ...state, + attachmentList: { ...state.attachmentList, loading: true }, + }), + ), + on( + VorgangActions.loadAttachmentListSuccess, + (state: VorgangState, props: LoadBinaryFileListSuccessProps): VorgangState => ({ + ...state, + attachmentList: createStateResource(props.binaryFileList), + }), + ), + + on( + VorgangActions.loadRepresentationList, + (state: VorgangState): VorgangState => ({ + ...state, + representationList: { ...state.representationList, loading: true }, + }), + ), + on( + VorgangActions.loadRepresentationListSuccess, + (state: VorgangState, props: LoadBinaryFileListSuccessProps): VorgangState => ({ + ...state, + representationList: createStateResource(props.binaryFileList), + }), + ), + + on( + VorgangActions.loadPendingCommandListSuccess, + (state: VorgangState, props: LoadCommandListSuccessProps): VorgangState => ({ + ...state, + forwardPendingCommand: createStateResource( + getPendingCommandByOrder(props.commandList, [CommandOrder.REDIRECT_VORGANG]), + ), + sendPostfachNachrichtPendingCommand: createStateResource( + getPendingCommandByOrder(props.commandList, [CommandOrder.SEND_POSTFACH_NACHRICHT]), + ), + }), + ), + + on( + VorgangActions.setForwardingSingleCommandLoading, + (state: VorgangState): VorgangState => ({ + ...state, + forwardPendingCommand: createEmptyStateResource(true), + }), + ), + on( + VorgangActions.setForwardingSingleCommand, + (state: VorgangState, props: CommandStateResourceProps): VorgangState => ({ + ...state, + forwardPendingCommand: props.commandStateResource, + }), + ), + + on( + VorgangActions.setSendPostfachNachrichtSingleCommandLoading, + (state: VorgangState): VorgangState => ({ + ...state, + sendPostfachNachrichtPendingCommand: createEmptyStateResource(true), + }), + ), + on( + VorgangActions.setSendPostfachNachrichtSingleCommand, + (state: VorgangState, props: CommandStateResourceProps): VorgangState => ({ + ...state, + sendPostfachNachrichtPendingCommand: props.commandStateResource, + }), + ), + + on( + VorgangActions.initAssignUser, + (state: VorgangState): VorgangState => ({ + ...state, + assignUserCommand: { ...state.assignUserCommand, reload: true }, + }), + ), + + on( + VorgangActions.exportVorgang, + (state: VorgangState): VorgangState => ({ + ...state, + vorgangExport: createEmptyStateResource(true), + }), + ), + on( + VorgangActions.exportVorgangSuccess, + (state: VorgangState): VorgangState => ({ + ...state, + vorgangExport: createStateResource(true), + }), + ), + + //Command + on(CommandActions.createCommand, (state, props: CreateCommandProps): VorgangState => { + return { + ...state, + statusCommandMap: VorgangReducer.getStatusCommandMapByCreateCommand(state, props.command), + assignUserCommand: VorgangReducer.getAssignUserCommandByCreateCommand(state, props.command), + }; + }), + on(CommandActions.createCommandSuccess, (state, props: CommandProps): VorgangState => { + return { + ...state, + statusCommandMap: VorgangReducer.getStatusCommandMapByCreateCommandSuccess( + state, + props.command, + ), + assignUserCommand: VorgangReducer.getAssignUserCommandByCreateCommandSuccess( + state, + props.command, + ), + vorgangWithEingang: VorgangReducer.getVorgangWithEingangStateResourceByCreateCommandSucces( + state, + props.command, + ), + }; + }), + on(CommandActions.revokeCommand, (state): VorgangState => { + return { ...state, revokeCommand: createEmptyStateResource(true) }; + }), + on(CommandActions.revokeCommandSuccess, (state, props: CommandProps): VorgangState => { + return { + ...state, + statusCommandMap: <any>{}, + vorgangWithEingang: { ...state.vorgangWithEingang, reload: true }, + revokeCommand: createStateResource(props.command), + }; + }), + on(CommandActions.publishConcurrentModificationAction, (state): VorgangState => { + return { ...state, vorgangWithEingang: { ...state.vorgangWithEingang, reload: true } }; + }), + + //Navigation + on(NavigationActions.updateCurrentRouteData, (state, action): VorgangState => { + return VorgangReducer.updateByRouteData(state, action.routeData); + }), ); -export function getVorgangWithEingangStateResourceByCreateCommandSucces(state: VorgangState, command: CreateCommand): StateResource<VorgangWithEingangResource> { - return command.order === CommandOrder.VORGANG_LOESCHEN //TODO spezifischer und mit den orders conditionieren die einen reload verlangen - ? state.vorgangWithEingang - : { ...state.vorgangWithEingang, reload: true }; +export function getVorgangWithEingangStateResourceByCreateCommandSucces( + state: VorgangState, + command: CreateCommand, +): StateResource<VorgangWithEingangResource> { + return ( + command.order === CommandOrder.VORGANG_LOESCHEN //TODO spezifischer und mit den orders conditionieren die einen reload verlangen + ) ? + state.vorgangWithEingang + : { ...state.vorgangWithEingang, reload: true }; } -export function getStatusCommandMapByCreateCommand(state: VorgangState, command: CreateCommand): StatusCommandMap { - return isStatusCommand(command.order) - ? { ...state.statusCommandMap, [command.order]: createEmptyStateResource(true) } - : state.statusCommandMap; +export function getStatusCommandMapByCreateCommand( + state: VorgangState, + command: CreateCommand, +): StatusCommandMap { + return isStatusCommand(command.order) ? + { ...state.statusCommandMap, [command.order]: createEmptyStateResource(true) } + : state.statusCommandMap; } -export function getStatusCommandMapByCreateCommandSuccess(state: VorgangState, command: CommandResource): StatusCommandMap { - return isStatusCommand(command.order) - ? { ...state.statusCommandMap, [command.order]: createStateResource(command) } - : state.statusCommandMap; +export function getStatusCommandMapByCreateCommandSuccess( + state: VorgangState, + command: CommandResource, +): StatusCommandMap { + return isStatusCommand(command.order) ? + { ...state.statusCommandMap, [command.order]: createStateResource(command) } + : state.statusCommandMap; } -export function getAssignUserCommandByCreateCommand(state: VorgangState, command: CreateCommand): StateResource<CommandResource> { - return isAssignUserCommand(command.order) ? createEmptyStateResource(true): state.assignUserCommand; +export function getAssignUserCommandByCreateCommand( + state: VorgangState, + command: CreateCommand, +): StateResource<CommandResource> { + return isAssignUserCommand(command.order) ? + createEmptyStateResource(true) + : state.assignUserCommand; } -export function getAssignUserCommandByCreateCommandSuccess(state: VorgangState, command: CommandResource): StateResource<CommandResource> { - return isAssignUserCommand(command.order) ? createStateResource(command) : state.assignUserCommand; +export function getAssignUserCommandByCreateCommandSuccess( + state: VorgangState, + command: CommandResource, +): StateResource<CommandResource> { + return isAssignUserCommand(command.order) ? + createStateResource(command) + : state.assignUserCommand; } function clearPreviewList(props: StringBasedProps): boolean { - return isNil(props.string) || props.string === EMPTY_STRING || props.string.length <= 3; + return isNil(props.string) || props.string === EMPTY_STRING || props.string.length <= 3; } export function updateByRouteData(state: VorgangState, routeData: RouteData): VorgangState { - let newState = { ...state, vorgangList: {...state.vorgangList, reload: true }, vorgaenge: EMPTY_ARRAY }; - - if (isUebersichtsSeite(routeData)) { - newState = prepareStateOnVorgangListNavigation(newState, routeData); - } - if (isVorgangPage(routeData)) { - newState = prepareStateOnVorgangNavigation(newState); - } - return newState; + let newState = { + ...state, + vorgangList: { ...state.vorgangList, reload: true }, + vorgaenge: EMPTY_ARRAY, + }; + + if (isUebersichtsSeite(routeData)) { + newState = prepareStateOnVorgangListNavigation(newState, routeData); + } + if (isVorgangPage(routeData)) { + newState = prepareStateOnVorgangNavigation(newState); + } + return newState; } -function prepareStateOnVorgangListNavigation(state: VorgangState, routeData: RouteData): VorgangState { - let newState: VorgangState = { ...state, - vorgangFilter: getVorgangFilter(routeData), - vorgangView: getVorgangView(routeData), - vorgangWithEingang: createEmptyStateResource(), - attachmentList: createEmptyStateResource(), - representationList: createEmptyStateResource(), - forwardPendingCommand: createEmptyStateResource(), - sendPostfachNachrichtPendingCommand: createEmptyStateResource(), - statusCommandMap: <any>{} - }; - - VorgangReducer.updateLocalStorage(newState.vorgangFilter, newState.vorgangView); - - const searchString: string = getSearchString(routeData); - newState = { ...newState, searchString }; - - if (state.searchString != getSearchString(routeData)) { - newState = { ...newState, searchPreviewList: { ...state.searchPreviewList, reload: true }}; - } - - return newState; +function prepareStateOnVorgangListNavigation( + state: VorgangState, + routeData: RouteData, +): VorgangState { + let newState: VorgangState = { + ...state, + vorgangFilter: getVorgangFilter(routeData), + vorgangView: getVorgangView(routeData), + vorgangWithEingang: createEmptyStateResource(), + attachmentList: createEmptyStateResource(), + representationList: createEmptyStateResource(), + forwardPendingCommand: createEmptyStateResource(), + sendPostfachNachrichtPendingCommand: createEmptyStateResource(), + statusCommandMap: <any>{}, + }; + + VorgangReducer.updateLocalStorage(newState.vorgangFilter, newState.vorgangView); + + const searchString: string = getSearchString(routeData); + newState = { ...newState, searchString }; + + if (state.searchString != getSearchString(routeData)) { + newState = { ...newState, searchPreviewList: { ...state.searchPreviewList, reload: true } }; + } + + return newState; } function prepareStateOnVorgangNavigation(state: VorgangState): VorgangState { - return {...state, - vorgangWithEingang: createEmptyStateResource(), - forwardPendingCommand: createEmptyStateResource(), - sendPostfachNachrichtPendingCommand: createEmptyStateResource() - } + return { + ...state, + vorgangWithEingang: createEmptyStateResource(), + forwardPendingCommand: createEmptyStateResource(), + sendPostfachNachrichtPendingCommand: createEmptyStateResource(), + }; } export function updateLocalStorage(vorgangFilter: VorgangFilter, vorgangView: VorgangView): void { - setFilterIntoStorage(ROUTE_PARAM_BY_VORGANG_FILTER[vorgangFilter]); + setFilterIntoStorage(ROUTE_PARAM_BY_VORGANG_FILTER[vorgangFilter]); - if (vorgangView === VorgangView.VORGANG_LIST) { - removeLocalStorageView(); - } else { - setViewIntoStorage(ROUTE_PARAM_BY_VORGANG_VIEW[vorgangView]); - } + if (vorgangView === VorgangView.VORGANG_LIST) { + removeLocalStorageView(); + } else { + setViewIntoStorage(ROUTE_PARAM_BY_VORGANG_VIEW[vorgangView]); + } } export function reducer(state: VorgangState, action: Action): VorgangState { - return vorgangReducer(state, action); + return vorgangReducer(state, action); } diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.spec.ts index 824bf4c7feb231a9add08965b7972bb7d41a3e1b..2d9a3e2bf1511d046a4183281dfa3e1c94dc6ea3 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.spec.ts @@ -23,297 +23,358 @@ */ import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; -import { ContentType, GetRequestOptions, HttpErrorHandler, HttpHeader } from '@alfa-client/tech-shared'; +import { + ContentType, + GetRequestOptions, + HttpErrorHandler, + HttpHeader, +} from '@alfa-client/tech-shared'; import { mock, mockClass, useFromMock } from '@alfa-client/test-utils'; import { LinkRel, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { TechSharedModule } from 'libs/tech-shared/src/lib/tech-shared.module'; -import { createVorgangListResource, createVorgangResource, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; -import { VorgangHeaderLinkRel, VorgangListLinkRel, VorgangWithEingangLinkRel } from './../vorgang.linkrel'; -import { VorgangListResource, VorgangResource, VorgangWithEingangResource } from './../vorgang.model'; +import { + createVorgangListResource, + createVorgangResource, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; +import { + VorgangHeaderLinkRel, + VorgangListLinkRel, + VorgangWithEingangLinkRel, +} from './../vorgang.linkrel'; +import { + VorgangListResource, + VorgangResource, + VorgangWithEingangResource, +} from './../vorgang.model'; import { VorgangRepository } from './vorgang.repository'; describe('VorgangRepository', () => { - let repository: VorgangRepository; - let resourceFactory = mock(ResourceFactory); - let resourceWrapper = { get: jest.fn() }; - let httpClient = mock(HttpClient); + let repository: VorgangRepository; + let resourceFactory = mock(ResourceFactory); + let resourceWrapper = { get: jest.fn() }; + let httpClient = mock(HttpClient); - beforeEach(() => { - repository = new VorgangRepository(useFromMock(resourceFactory), useFromMock(httpClient)); + beforeEach(() => { + repository = new VorgangRepository(useFromMock(resourceFactory), useFromMock(httpClient)); - resourceFactory.fromId.mockReturnValue(resourceWrapper); - resourceFactory.from.mockReturnValue(resourceWrapper); - }) + resourceFactory.fromId.mockReturnValue(resourceWrapper); + resourceFactory.from.mockReturnValue(resourceWrapper); + }); - describe('loadVorgangList', () => { - const vorgangListResource: VorgangListResource = createVorgangListResource(); - const apiRootResource: ApiRootResource = createApiRootResource(); - const linkRel: string = 'dummyLinkRel'; + describe('loadVorgangList', () => { + const vorgangListResource: VorgangListResource = createVorgangListResource(); + const apiRootResource: ApiRootResource = createApiRootResource(); + const linkRel: string = 'dummyLinkRel'; - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource })); - }) + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource })); + }); - it('should call resourceFactory with resource', () => { - repository.loadVorgangList(apiRootResource, linkRel); + it('should call resourceFactory with resource', () => { + repository.loadVorgangList(apiRootResource, linkRel); - expect(resourceFactory.from).toHaveBeenCalledWith(apiRootResource); - }) + expect(resourceFactory.from).toHaveBeenCalledWith(apiRootResource); + }); - it('should call resourceWrapper with link', () => { - repository.loadVorgangList(apiRootResource, linkRel); + it('should call resourceWrapper with link', () => { + repository.loadVorgangList(apiRootResource, linkRel); - expect(resourceWrapper.get).toHaveBeenCalledWith(linkRel) - }) + expect(resourceWrapper.get).toHaveBeenCalledWith(linkRel); + }); - it('should return result', () => { - let result = repository.loadVorgangList(apiRootResource, linkRel); + it('should return result', () => { + let result = repository.loadVorgangList(apiRootResource, linkRel); - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: vorgangListResource })); - }) - }) + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: vorgangListResource })); + }); + }); - describe('getNextVorgangListPage', () => { - const vorgangListResource: VorgangListResource = createVorgangListResource([VorgangListLinkRel.NEXT]); + describe('getNextVorgangListPage', () => { + const vorgangListResource: VorgangListResource = createVorgangListResource([ + VorgangListLinkRel.NEXT, + ]); - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource })); - }) + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource })); + }); - it('should call resourceFactory with resource', () => { - repository.getNextVorgangListPage(vorgangListResource); + it('should call resourceFactory with resource', () => { + repository.getNextVorgangListPage(vorgangListResource); - expect(resourceFactory.from).toHaveBeenCalledWith(vorgangListResource); - }) + expect(resourceFactory.from).toHaveBeenCalledWith(vorgangListResource); + }); - it('should call resourceWrapper with link', () => { - repository.getNextVorgangListPage(vorgangListResource); + it('should call resourceWrapper with link', () => { + repository.getNextVorgangListPage(vorgangListResource); - expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangListLinkRel.NEXT) - }) + expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangListLinkRel.NEXT); + }); - it('should return result', () => { - let result = repository.getNextVorgangListPage(vorgangListResource); + it('should return result', () => { + let result = repository.getNextVorgangListPage(vorgangListResource); - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: vorgangListResource })); - }) - }) + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: vorgangListResource })); + }); + }); - describe('getVorgangWithEingang', () => { - const vorgangResource: VorgangResource = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]); - const vorgangWithEingangUrl = getUrl(vorgangResource, VorgangHeaderLinkRel.VORGANG_WITH_EINGANG); - const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource(); + describe('getVorgangWithEingang', () => { + const vorgangResource: VorgangResource = createVorgangResource([ + VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, + ]); + const vorgangWithEingangUrl = getUrl( + vorgangResource, + VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, + ); + const vorgangWithEingangResource: VorgangWithEingangResource = + createVorgangWithEingangResource(); - beforeEach(() => { - const classMock = mockClass(TechSharedModule); - classMock.injector = <any>{ get: () => useFromMock(mock(HttpErrorHandler)) }; - - resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangWithEingangResource })); - }) - - it('should call resourceFactory with resource', () => { - repository.getVorgang(vorgangWithEingangUrl); - - expect(resourceFactory.fromId).toHaveBeenCalledWith(vorgangWithEingangUrl); - }) - - it('should call resourceWrapper with link', () => { - repository.getVorgang(vorgangWithEingangUrl); - - expect(resourceWrapper.get).toHaveBeenCalled() - }) - - it('should return result', () => { - let result = repository.getVorgang(vorgangWithEingangUrl); - - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: vorgangWithEingangResource })); - }) - }) - - describe('getAttachments', () => { - - const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.ATTACHMENTS]); - - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangWithEingangResource })); - }) - - it('should call resourceFactory with resource', () => { - repository.getAttachments(vorgangWithEingangResource); - - expect(resourceFactory.from).toHaveBeenCalledWith(vorgangWithEingangResource); - }) - - it('should call resourceWrapper with link', () => { - repository.getAttachments(vorgangWithEingangResource); - - expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangWithEingangLinkRel.ATTACHMENTS) - }) - - it('should return result', () => { - let result = repository.getAttachments(vorgangWithEingangResource); - - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: vorgangWithEingangResource })); - }) - }) - - describe('searchVorgaengeBy', () => { - - const vorgangListResource: VorgangListResource = createVorgangListResource(); - const apiRootResource: ApiRootResource = createApiRootResource(); - - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource })); - repository.buildSearchByUrl = jest.fn(); - }) - - it('should call resourceFactory', () => { - repository.searchVorgaengeBy(apiRootResource, null, ApiRootLinkRel.SEARCH_ALLE); - - expect(resourceFactory.fromId).toHaveBeenCalled(); - }) - - it('should call resourceWrapper ', () => { - repository.searchVorgaengeBy(apiRootResource, null, ApiRootLinkRel.SEARCH_ALLE); - - expect(resourceWrapper.get).toHaveBeenCalled(); - }) - - it('should call buildSearchByUrl', () => { - const searchString: string = 'i search for...'; - const limit: number = 7; - repository.searchVorgaengeBy(apiRootResource, searchString, ApiRootLinkRel.SEARCH_ALLE, limit); - - expect(repository.buildSearchByUrl).toHaveBeenCalledWith(apiRootResource, searchString, ApiRootLinkRel.SEARCH_ALLE, limit) - }) - }) - - describe('buildSearchByUrl', () => { - - const baseUrl: string = 'http://localhost/vorgangs?page=0'; - - it('should build search by url', () => { - const _links = { - self: { href: '/api/1' }, search_all: { href: baseUrl + '{&' + VorgangRepository.SEARCH_PARAM + '}' } - }; - const apiRootResource: ApiRootResource = { ...createApiRootResource([ApiRootLinkRel.SEARCH_ALLE]), _links }; - - const searchUrl: ResourceUri = repository.buildSearchByUrl(apiRootResource, 'searchParam', ApiRootLinkRel.SEARCH_ALLE); - - expect(searchUrl).toEqual(baseUrl + '&' + VorgangRepository.SEARCH_PARAM + '=searchParam'); - }) - - it('should ignore unused, optional parameters', () => { - const apiRoot: ApiRootResource = buildLinksWithSearch(baseUrl + '{&searchBy,limit}'); - - const searchUrl: ResourceUri = repository.buildSearchByUrl(apiRoot, 'search', ApiRootLinkRel.SEARCH_ALLE); - - expect(searchUrl).toEqual(baseUrl + '&' + VorgangRepository.SEARCH_PARAM + '=search'); - }) - - it('should set limit if present', () => { - const limit = 5; - const res = buildLinksWithSearch(baseUrl + '{&searchBy,limit}'); - - const searchUrl: ResourceUri = repository.buildSearchByUrl(res, 'search', ApiRootLinkRel.SEARCH_ALLE, limit); - - expect(searchUrl).toEqual(baseUrl + '&' + VorgangRepository.SEARCH_PARAM + '=search&limit=' + limit); - }) - - function buildLinksWithSearch(searchHref: string): ApiRootResource { - let res: ApiRootResource = { ...createApiRootResource([LinkRel.Self]) } - res = { ...res, _links: { ...res._links, search_all: { href: searchHref } } } - return res; - } - }) - - describe('loadMeineVorgaengeList', () => { - const vorgangListResource: VorgangListResource = createVorgangListResource(); - const apiRootResource: ApiRootResource = createApiRootResource([ApiRootLinkRel.MEINE_VORGAENGE]); - - beforeEach(() => { - resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource })); - }) - - it('should call resourceFactory with uri', () => { - repository.loadMeineVorgaengeList(apiRootResource); - - const urlWithoutParameter: URL = repository.getUrlWithoutParameter(apiRootResource, ApiRootLinkRel.MEINE_VORGAENGE); - expect(resourceFactory.fromId).toHaveBeenCalledWith(urlWithoutParameter.href); - }) - - it('should call resourceWrapper with link', () => { - repository.loadMeineVorgaengeList(apiRootResource); - - expect(resourceWrapper.get).toHaveBeenCalledWith() - }) - - it('should return result', () => { - let result = repository.loadMeineVorgaengeList(apiRootResource); - - expect(result).not.toBeNull(); - expect(result).toBeObservable(cold('a', { a: vorgangListResource })); - }) - }) - - describe('export', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangWithEingangLinkRel.EXPORT]); - - const body: Blob = new Blob(); - const fileName: string = '927ee047-0123-4c36-911c-52e984accc87_Abgabe.Abgabe.0401.xdomea'; - const headerString: string = 'attachment; filename=' + fileName - const httpResponse: HttpResponse<Blob> = <any>{ body, headers: { get: () => headerString }}; - - beforeEach(() => { - httpClient.get.mockReturnValue(hot('a', { a: httpResponse })); - }) - - it('should call httpClient', () => { - const requestOptions = {}; - repository.buildRequestOptions = jest.fn(); - (<any>repository.buildRequestOptions).mockReturnValue(requestOptions); - - repository.export(vorgangWithEingang); - - expect(httpClient.get).toHaveBeenCalledWith(getUrl(vorgangWithEingang, VorgangWithEingangLinkRel.EXPORT), requestOptions); - }) - - it('should return value', () => { - const result = repository.export(vorgangWithEingang); - - expect(result).toBeObservable(cold('b', { b: { blob: body, fileName } })); - }) - }) - - describe('buildRequestOptions', () => { - - it('should return httpHeaders', () => { - const result: GetRequestOptions = repository.buildRequestOptions(); - - expect(result.responseType).toEqual('blob'); - }) - - it('should return responseType', () => { - const result: GetRequestOptions = repository.buildRequestOptions(); - - expect(result.headers).toEqual(getExpectedRequestOptions()); - }) - - it('should observe response', () => { - const result: GetRequestOptions = repository.buildRequestOptions(); - - expect((<any>result).observe).toEqual('response'); - }) - - function getExpectedRequestOptions(): HttpHeaders { - return new HttpHeaders().set(HttpHeader.ACCEPT, ContentType.APPLICATION_OCTET_STREAM); - } - }) -}) \ No newline at end of file + beforeEach(() => { + const classMock = mockClass(TechSharedModule); + classMock.injector = <any>{ get: () => useFromMock(mock(HttpErrorHandler)) }; + + resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangWithEingangResource })); + }); + + it('should call resourceFactory with resource', () => { + repository.getVorgang(vorgangWithEingangUrl); + + expect(resourceFactory.fromId).toHaveBeenCalledWith(vorgangWithEingangUrl); + }); + + it('should call resourceWrapper with link', () => { + repository.getVorgang(vorgangWithEingangUrl); + + expect(resourceWrapper.get).toHaveBeenCalled(); + }); + + it('should return result', () => { + let result = repository.getVorgang(vorgangWithEingangUrl); + + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: vorgangWithEingangResource })); + }); + }); + + describe('getAttachments', () => { + const vorgangWithEingangResource: VorgangWithEingangResource = createVorgangWithEingangResource( + [VorgangWithEingangLinkRel.ATTACHMENTS], + ); + + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangWithEingangResource })); + }); + + it('should call resourceFactory with resource', () => { + repository.getAttachments(vorgangWithEingangResource); + + expect(resourceFactory.from).toHaveBeenCalledWith(vorgangWithEingangResource); + }); + + it('should call resourceWrapper with link', () => { + repository.getAttachments(vorgangWithEingangResource); + + expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangWithEingangLinkRel.ATTACHMENTS); + }); + + it('should return result', () => { + let result = repository.getAttachments(vorgangWithEingangResource); + + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: vorgangWithEingangResource })); + }); + }); + + describe('searchVorgaengeBy', () => { + const vorgangListResource: VorgangListResource = createVorgangListResource(); + const apiRootResource: ApiRootResource = createApiRootResource(); + + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource })); + repository.buildSearchByUrl = jest.fn(); + }); + + it('should call resourceFactory', () => { + repository.searchVorgaengeBy(apiRootResource, null, ApiRootLinkRel.SEARCH_ALLE); + + expect(resourceFactory.fromId).toHaveBeenCalled(); + }); + + it('should call resourceWrapper ', () => { + repository.searchVorgaengeBy(apiRootResource, null, ApiRootLinkRel.SEARCH_ALLE); + + expect(resourceWrapper.get).toHaveBeenCalled(); + }); + + it('should call buildSearchByUrl', () => { + const searchString: string = 'i search for...'; + const limit: number = 7; + repository.searchVorgaengeBy( + apiRootResource, + searchString, + ApiRootLinkRel.SEARCH_ALLE, + limit, + ); + + expect(repository.buildSearchByUrl).toHaveBeenCalledWith( + apiRootResource, + searchString, + ApiRootLinkRel.SEARCH_ALLE, + limit, + ); + }); + }); + + describe('buildSearchByUrl', () => { + const baseUrl: string = 'http://localhost/vorgangs?page=0'; + + it('should build search by url', () => { + const _links = { + self: { href: '/api/1' }, + search_all: { href: baseUrl + '{&' + VorgangRepository.SEARCH_PARAM + '}' }, + }; + const apiRootResource: ApiRootResource = { + ...createApiRootResource([ApiRootLinkRel.SEARCH_ALLE]), + _links, + }; + + const searchUrl: ResourceUri = repository.buildSearchByUrl( + apiRootResource, + 'searchParam', + ApiRootLinkRel.SEARCH_ALLE, + ); + + expect(searchUrl).toEqual(baseUrl + '&' + VorgangRepository.SEARCH_PARAM + '=searchParam'); + }); + + it('should ignore unused, optional parameters', () => { + const apiRoot: ApiRootResource = buildLinksWithSearch(baseUrl + '{&searchBy,limit}'); + + const searchUrl: ResourceUri = repository.buildSearchByUrl( + apiRoot, + 'search', + ApiRootLinkRel.SEARCH_ALLE, + ); + + expect(searchUrl).toEqual(baseUrl + '&' + VorgangRepository.SEARCH_PARAM + '=search'); + }); + + it('should set limit if present', () => { + const limit = 5; + const res = buildLinksWithSearch(baseUrl + '{&searchBy,limit}'); + + const searchUrl: ResourceUri = repository.buildSearchByUrl( + res, + 'search', + ApiRootLinkRel.SEARCH_ALLE, + limit, + ); + + expect(searchUrl).toEqual( + baseUrl + '&' + VorgangRepository.SEARCH_PARAM + '=search&limit=' + limit, + ); + }); + + function buildLinksWithSearch(searchHref: string): ApiRootResource { + let res: ApiRootResource = { ...createApiRootResource([LinkRel.Self]) }; + res = { ...res, _links: { ...res._links, search_all: { href: searchHref } } }; + return res; + } + }); + + describe('loadMeineVorgaengeList', () => { + const vorgangListResource: VorgangListResource = createVorgangListResource(); + const apiRootResource: ApiRootResource = createApiRootResource([ + ApiRootLinkRel.MEINE_VORGAENGE, + ]); + + beforeEach(() => { + resourceWrapper.get.mockReturnValue(hot('a', { a: vorgangListResource })); + }); + + it('should call resourceFactory with uri', () => { + repository.loadMeineVorgaengeList(apiRootResource); + + const urlWithoutParameter: URL = repository.getUrlWithoutParameter( + apiRootResource, + ApiRootLinkRel.MEINE_VORGAENGE, + ); + expect(resourceFactory.fromId).toHaveBeenCalledWith(urlWithoutParameter.href); + }); + + it('should call resourceWrapper with link', () => { + repository.loadMeineVorgaengeList(apiRootResource); + + expect(resourceWrapper.get).toHaveBeenCalledWith(); + }); + + it('should return result', () => { + let result = repository.loadMeineVorgaengeList(apiRootResource); + + expect(result).not.toBeNull(); + expect(result).toBeObservable(cold('a', { a: vorgangListResource })); + }); + }); + + describe('export', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangWithEingangLinkRel.EXPORT, + ]); + + const body: Blob = new Blob(); + const fileName: string = '927ee047-0123-4c36-911c-52e984accc87_Abgabe.Abgabe.0401.xdomea'; + const headerString: string = 'attachment; filename=' + fileName; + const httpResponse: HttpResponse<Blob> = <any>{ body, headers: { get: () => headerString } }; + + beforeEach(() => { + httpClient.get.mockReturnValue(hot('a', { a: httpResponse })); + }); + + it('should call httpClient', () => { + const requestOptions = {}; + repository.buildRequestOptions = jest.fn(); + (<any>repository.buildRequestOptions).mockReturnValue(requestOptions); + + repository.export(vorgangWithEingang); + + expect(httpClient.get).toHaveBeenCalledWith( + getUrl(vorgangWithEingang, VorgangWithEingangLinkRel.EXPORT), + requestOptions, + ); + }); + + it('should return value', () => { + const result = repository.export(vorgangWithEingang); + + expect(result).toBeObservable(cold('b', { b: { blob: body, fileName } })); + }); + }); + + describe('buildRequestOptions', () => { + it('should return httpHeaders', () => { + const result: GetRequestOptions = repository.buildRequestOptions(); + + expect(result.responseType).toEqual('blob'); + }); + + it('should return responseType', () => { + const result: GetRequestOptions = repository.buildRequestOptions(); + + expect(result.headers).toEqual(getExpectedRequestOptions()); + }); + + it('should observe response', () => { + const result: GetRequestOptions = repository.buildRequestOptions(); + + expect((<any>result).observe).toEqual('response'); + }); + + function getExpectedRequestOptions(): HttpHeaders { + return new HttpHeaders().set(HttpHeader.ACCEPT, ContentType.APPLICATION_OCTET_STREAM); + } + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.ts index 4e7a6eb480d1e814d3262fc13bb25b2e5c0af2b7..effb4d999bb5906a071fd352b593b79e8e578490 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.ts @@ -25,7 +25,16 @@ import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; import { BinaryFileListResource } from '@alfa-client/binary-file-shared'; -import { BlobWithFileName, ContentType, EMPTY_STRING, GetRequestOptions, HttpHeader, SkipInterceptor, buildBlobWithFileName, isNotUndefined } from '@alfa-client/tech-shared'; +import { + BlobWithFileName, + ContentType, + EMPTY_STRING, + GetRequestOptions, + HttpHeader, + SkipInterceptor, + buildBlobWithFileName, + isNotUndefined, +} from '@alfa-client/tech-shared'; import { Resource, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest'; import { Observable, map } from 'rxjs'; import { VorgangListLinkRel, VorgangWithEingangLinkRel } from './../vorgang.linkrel'; @@ -33,63 +42,89 @@ import { VorgangListResource, VorgangWithEingangResource } from './../vorgang.mo @Injectable({ providedIn: 'root' }) export class VorgangRepository { + static SEARCH_PARAM: string = 'searchBy'; + static LIMIT_PARAM: string = 'limit'; - static SEARCH_PARAM: string = 'searchBy'; - static LIMIT_PARAM: string = 'limit'; + static GET_VORGANG: string = 'getVorgang'; - static GET_VORGANG: string = 'getVorgang'; + constructor( + private resourceFactory: ResourceFactory, + private httpClient: HttpClient, + ) {} - constructor(private resourceFactory: ResourceFactory, private httpClient: HttpClient) { } + public loadVorgangList( + apiRootResource: ApiRootResource, + linkRel: string, + ): Observable<VorgangListResource> { + return this.resourceFactory.from(apiRootResource).get(linkRel); + } - public loadVorgangList(apiRootResource: ApiRootResource, linkRel: string): Observable<VorgangListResource> { - return this.resourceFactory.from(apiRootResource).get(linkRel); - } + public getNextVorgangListPage( + vorgangListResource: VorgangListResource, + ): Observable<VorgangListResource> { + return this.resourceFactory.from(vorgangListResource).get(VorgangListLinkRel.NEXT); + } - public getNextVorgangListPage(vorgangListResource: VorgangListResource): Observable<VorgangListResource> { - return this.resourceFactory.from(vorgangListResource).get(VorgangListLinkRel.NEXT); - } + public loadMeineVorgaengeList(apiRootResource: ApiRootResource): Observable<VorgangListResource> { + const url: URL = this.getUrlWithoutParameter(apiRootResource, ApiRootLinkRel.MEINE_VORGAENGE); + return this.resourceFactory.fromId(url.href).get(); + } - public loadMeineVorgaengeList(apiRootResource: ApiRootResource): Observable<VorgangListResource> { - const url: URL = this.getUrlWithoutParameter(apiRootResource, ApiRootLinkRel.MEINE_VORGAENGE); - return this.resourceFactory.fromId(url.href).get(); - } + public getVorgang(vorgangWithEingangUrl: ResourceUri): Observable<VorgangWithEingangResource> { + return this.resourceFactory.fromId(vorgangWithEingangUrl).get(); + } - public getVorgang(vorgangWithEingangUrl: ResourceUri): Observable<VorgangWithEingangResource> { - return this.resourceFactory.fromId(vorgangWithEingangUrl).get(); - } + public getAttachments(vorgang: VorgangWithEingangResource): Observable<BinaryFileListResource> { + return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.ATTACHMENTS); + } - public getAttachments(vorgang: VorgangWithEingangResource): Observable<BinaryFileListResource> { - return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.ATTACHMENTS); - } + public getRepresentations( + vorgang: VorgangWithEingangResource, + ): Observable<BinaryFileListResource> { + return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.REPRESENTATIONS); + } - public getRepresentations(vorgang: VorgangWithEingangResource): Observable<BinaryFileListResource> { - return this.resourceFactory.from(vorgang).get(VorgangWithEingangLinkRel.REPRESENTATIONS); - } + @SkipInterceptor() + public searchVorgaengeBy( + apiRootResource: ApiRootResource, + searchBy: string, + linkRel: string, + limit?: number, + ): Observable<VorgangListResource> { + return this.resourceFactory + .fromId(this.buildSearchByUrl(apiRootResource, searchBy, linkRel, limit)) + .get(); + } - @SkipInterceptor() - public searchVorgaengeBy(apiRootResource: ApiRootResource, searchBy: string, linkRel: string, limit?: number): Observable<VorgangListResource> { - return this.resourceFactory.fromId(this.buildSearchByUrl(apiRootResource, searchBy, linkRel, limit)).get(); - } + buildSearchByUrl( + apiRootResource: ApiRootResource, + searchBy: string, + linkRel: string, + limit?: number, + ): ResourceUri { + //TODO sollte mal bei ngxp eingebaut werden und geprüft werden, dass nur erwartete Paramter befüllt werden + const url: URL = this.getUrlWithoutParameter(apiRootResource, linkRel); + url.searchParams.set(VorgangRepository.SEARCH_PARAM, searchBy); + if (isNotUndefined(limit)) + url.searchParams.set(VorgangRepository.LIMIT_PARAM, limit.toString()); + return url.href; + } - buildSearchByUrl(apiRootResource: ApiRootResource, searchBy: string, linkRel: string, limit?: number): ResourceUri { - //TODO sollte mal bei ngxp eingebaut werden und geprüft werden, dass nur erwartete Paramter befüllt werden - const url: URL = this.getUrlWithoutParameter(apiRootResource, linkRel); - url.searchParams.set(VorgangRepository.SEARCH_PARAM, searchBy); - if (isNotUndefined(limit)) url.searchParams.set(VorgangRepository.LIMIT_PARAM, limit.toString()); - return url.href; - } + getUrlWithoutParameter(resource: Resource, linkRel: string): URL { + return new URL(getUrl(resource, linkRel).replace(/{&[\w,]*}$/, EMPTY_STRING)); + } - getUrlWithoutParameter(resource: Resource, linkRel: string): URL { - return new URL(getUrl(resource, linkRel).replace(/{&[\w,]*}$/, EMPTY_STRING)); - } + public export(vorgangWithEingang: VorgangWithEingangResource): Observable<BlobWithFileName> { + return this.httpClient + .get< + HttpResponse<Blob> + >(getUrl(vorgangWithEingang, VorgangWithEingangLinkRel.EXPORT), this.buildRequestOptions()) + .pipe(map(buildBlobWithFileName)); + } - public export(vorgangWithEingang: VorgangWithEingangResource): Observable<BlobWithFileName> { - return this.httpClient.get<HttpResponse<Blob>>(getUrl(vorgangWithEingang, VorgangWithEingangLinkRel.EXPORT), this.buildRequestOptions()).pipe(map(buildBlobWithFileName)); - } - - buildRequestOptions(): GetRequestOptions { - let headers = new HttpHeaders(); - headers = headers.set(HttpHeader.ACCEPT, ContentType.APPLICATION_OCTET_STREAM); - return <GetRequestOptions>{ headers, responseType: 'blob' as 'json', observe: 'response' }; - } -} \ No newline at end of file + buildRequestOptions(): GetRequestOptions { + let headers = new HttpHeaders(); + headers = headers.set(HttpHeader.ACCEPT, ContentType.APPLICATION_OCTET_STREAM); + return <GetRequestOptions>{ headers, responseType: 'blob' as 'json', observe: 'response' }; + } +} diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.selectors.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.selectors.spec.ts index d9d5e887b75ce6bd61b3db3bb1a3c1f4f4bfb17e..165b89b1e349e9188e8d4086a15f5508bd565a84 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.selectors.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.selectors.spec.ts @@ -26,223 +26,269 @@ import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; import { StateResource, createStateResource } from '@alfa-client/tech-shared'; import { createBinaryFileListResource } from 'libs/binary-file-shared/test/binary-file'; import { createCommandResource } from 'libs/command-shared/test/command'; -import { createVorgangListResource, createVorgangResources, createVorgangStatistic, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; -import { StatusCommandMap, VorgangFilter, VorgangListResource, VorgangResource, VorgangStatistic, VorgangView, VorgangWithEingangResource } from '../vorgang.model'; +import { + createVorgangListResource, + createVorgangResources, + createVorgangStatistic, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; +import { + StatusCommandMap, + VorgangFilter, + VorgangListResource, + VorgangResource, + VorgangStatistic, + VorgangView, + VorgangWithEingangResource, +} from '../vorgang.model'; import { VorgangPartialState, initialState } from './vorgang.reducer'; import * as VorgangNavigationUtil from '../vorgang-navigation.util'; import * as VorgangSelectors from './vorgang.selectors'; describe('Vorgang Selectors', () => { - - let state: VorgangPartialState; - - const vorgangList: StateResource<VorgangListResource> = createStateResource(createVorgangListResource()); - const vorgaenge: VorgangResource[] = createVorgangResources(); - const vorgangStatistic: StateResource<VorgangStatistic> = createStateResource(createVorgangStatistic()); - const searchPreviewList: StateResource<VorgangListResource> = createStateResource(createVorgangListResource()); - const searchString: string = 'searchThisForMe'; - const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; - const vorgangView: VorgangView = VorgangView.VORGANG_LIST; - - const vorgangWithEingang: StateResource<VorgangWithEingangResource> = createStateResource(createVorgangWithEingangResource()); - const attachmentList: StateResource<BinaryFileListResource> = createStateResource(createBinaryFileListResource()); - const representationList: StateResource<BinaryFileListResource> = createStateResource(createBinaryFileListResource()); - const assignUserCommand: StateResource<CommandResource> = createStateResource(createCommandResource()); - const forwardPendingCommand: StateResource<CommandResource> = createStateResource(createCommandResource()); - const sendPostfachNachrichtPendingCommand: StateResource<CommandResource> = createStateResource(createCommandResource()); - - const annehmenCommand: StateResource<CommandResource> = createStateResource(createCommandResource()); - const statusCommandMap: StatusCommandMap = <any>{ [CommandOrder.VORGANG_ANNEHMEN]: annehmenCommand }; - const revokeCommand: StateResource<CommandResource> = createStateResource(createCommandResource()); - const vorgangExport: StateResource<boolean> = createStateResource(false); - - beforeEach(() => { - state = { - VorgangState: { - ...initialState, - vorgangList, - vorgaenge, - vorgangStatistic, - searchPreviewList, - searchString, - vorgangFilter, - vorgangView, - - vorgangWithEingang, - attachmentList, - representationList, - assignUserCommand, - forwardPendingCommand, - sendPostfachNachrichtPendingCommand, - statusCommandMap, - revokeCommand, - vorgangExport - } - }; - }); - - it('should return vorgangList', () => { - const result: StateResource<VorgangListResource> = VorgangSelectors.vorgangList.projector(state.VorgangState); - - expect(result).toBe(vorgangList); - }) - - it('should return vorgaenge', () => { - const result: VorgangResource[] = VorgangSelectors.vorgaenge.projector(state.VorgangState); - - expect(result).toBe(vorgaenge); - }) - - it('should return vorgangStatistic', () => { - const result: StateResource<VorgangStatistic> = VorgangSelectors.vorgangStatistic.projector(state.VorgangState); - - expect(result).toBe(vorgangStatistic); - }) - - it('should return vorgangFilter', () => { - const result: VorgangFilter = VorgangSelectors.vorgangFilter.projector(state.VorgangState); - - expect(result).toBe(vorgangFilter); - }) - - it('should return vorgangView', () => { - const result: VorgangView = VorgangSelectors.vorgangView.projector(state.VorgangState); - - expect(result).toBe(vorgangView); - }) - - it('should return searchPreviewList', () => { - const result: StateResource<VorgangListResource> = VorgangSelectors.searchPreviewList.projector(state.VorgangState); - - expect(result).toBe(searchPreviewList); - }) - - it('should return searchString', () => { - const result: string = VorgangSelectors.searchString.projector(state.VorgangState); - - expect(result).toBe(searchString); - }) - - describe('backButtonUrl', () => { - - it('should call vorgangNavigationUtil buildVorgangListRoutePath', () => { - const utilSpy = jest.spyOn(VorgangNavigationUtil, 'buildBackButtonUrl'); - - VorgangSelectors.backButtonUrl.projector(state.VorgangState); - - expect(utilSpy).toHaveBeenCalledWith(state.VorgangState); - }) - }) - - describe('isVorgangViewSelected', () => { - - it('should return true if state and view matches', () => { - const result: boolean = VorgangSelectors.isVorgangViewSelected(VorgangView.VORGANG_LIST).projector(vorgangView); - - expect(result).toBeTruthy(); - }) - - it('should return false if state and view does not match', () => { - const result: boolean = VorgangSelectors.isVorgangViewSelected(VorgangView.NEU).projector(vorgangView); - - expect(result).toBeFalsy(); - }) - }) - - describe('getVorgangViewRoutePath', () => { - - it('should return /alle/neu', () => { - const result: string = VorgangSelectors.getVorgangViewRoutePath(VorgangView.NEU).projector(vorgangFilter); - - expect(result).toBe('/alle/neu'); - }) - }) - - //VorgangWithEingang - it('should return vorgangWithEingang', () => { - const result: StateResource<VorgangWithEingangResource> = VorgangSelectors.vorgangWithEingang.projector(state.VorgangState); - - expect(result).toBe(vorgangWithEingang); - }) - - describe('attachmentList', () => { - - it('should Return attachmentList from state', () => { - const result: StateResource<BinaryFileListResource> = VorgangSelectors.attachmentList.projector(state.VorgangState); - - expect(result).toBe(attachmentList); - }) - }) - - describe('representationList', () => { - - it('should Return representationList from state', () => { - const result: StateResource<BinaryFileListResource> = VorgangSelectors.representationList.projector(state.VorgangState); - - expect(result).toBe(representationList); - }) - }) - - describe('forwardPendingCommand', () => { - - it('should return command from state', () => { - const result: StateResource<CommandResource> = VorgangSelectors.forwardPendingCommand.projector(state.VorgangState); - - expect(result).toBe(forwardPendingCommand); - }) - }) - - describe('send postfach command', () => { - - it('should return command from state', () => { - const result: StateResource<CommandResource> = VorgangSelectors.sendPostfachNachrichtPendingCommand.projector(state.VorgangState); - - expect(result).toBe(sendPostfachNachrichtPendingCommand); - }) - }) - - describe('user assign command', () => { - - it('should return command from state', () => { - const result: StateResource<CommandResource> = VorgangSelectors.assignUserCommand.projector(state.VorgangState); - - expect(result).toBe(assignUserCommand); - }) - }) - - describe('stausCommandMap', () => { - - it('should select statusCommandMap from state', () => { - const result: StatusCommandMap = VorgangSelectors.statusCommandMap.projector(state.VorgangState); - - expect(result).toBe(statusCommandMap); - }) - }) - - describe('getStatusCommand', () => { - - it('should return statusCommand from state by order', () => { - const result: boolean = VorgangSelectors.getStatusCommand(CommandOrder.VORGANG_ANNEHMEN).projector(statusCommandMap); - - expect(result).toBe(annehmenCommand); - }) - }) - - describe('revokeCommand', () => { - - it('should return revokeCommand from state', () => { - const result: StateResource<CommandResource> = VorgangSelectors.revokeCommand.projector(state.VorgangState); - - expect(result).toBe(revokeCommand); - }) - }) - - describe('exportCommand', () => { - - it('should return exportCommand from state', () => { - const result: StateResource<boolean> = VorgangSelectors.vorgangExport.projector(state.VorgangState); - - expect(result).toBe(vorgangExport); - }) - })}); \ No newline at end of file + let state: VorgangPartialState; + + const vorgangList: StateResource<VorgangListResource> = createStateResource( + createVorgangListResource(), + ); + const vorgaenge: VorgangResource[] = createVorgangResources(); + const vorgangStatistic: StateResource<VorgangStatistic> = + createStateResource(createVorgangStatistic()); + const searchPreviewList: StateResource<VorgangListResource> = createStateResource( + createVorgangListResource(), + ); + const searchString: string = 'searchThisForMe'; + const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + const vorgangView: VorgangView = VorgangView.VORGANG_LIST; + + const vorgangWithEingang: StateResource<VorgangWithEingangResource> = createStateResource( + createVorgangWithEingangResource(), + ); + const attachmentList: StateResource<BinaryFileListResource> = createStateResource( + createBinaryFileListResource(), + ); + const representationList: StateResource<BinaryFileListResource> = createStateResource( + createBinaryFileListResource(), + ); + const assignUserCommand: StateResource<CommandResource> = + createStateResource(createCommandResource()); + const forwardPendingCommand: StateResource<CommandResource> = + createStateResource(createCommandResource()); + const sendPostfachNachrichtPendingCommand: StateResource<CommandResource> = + createStateResource(createCommandResource()); + + const annehmenCommand: StateResource<CommandResource> = + createStateResource(createCommandResource()); + const statusCommandMap: StatusCommandMap = <any>{ + [CommandOrder.VORGANG_ANNEHMEN]: annehmenCommand, + }; + const revokeCommand: StateResource<CommandResource> = + createStateResource(createCommandResource()); + const vorgangExport: StateResource<boolean> = createStateResource(false); + + beforeEach(() => { + state = { + VorgangState: { + ...initialState, + vorgangList, + vorgaenge, + vorgangStatistic, + searchPreviewList, + searchString, + vorgangFilter, + vorgangView, + + vorgangWithEingang, + attachmentList, + representationList, + assignUserCommand, + forwardPendingCommand, + sendPostfachNachrichtPendingCommand, + statusCommandMap, + revokeCommand, + vorgangExport, + }, + }; + }); + + it('should return vorgangList', () => { + const result: StateResource<VorgangListResource> = VorgangSelectors.vorgangList.projector( + state.VorgangState, + ); + + expect(result).toBe(vorgangList); + }); + + it('should return vorgaenge', () => { + const result: VorgangResource[] = VorgangSelectors.vorgaenge.projector(state.VorgangState); + + expect(result).toBe(vorgaenge); + }); + + it('should return vorgangStatistic', () => { + const result: StateResource<VorgangStatistic> = VorgangSelectors.vorgangStatistic.projector( + state.VorgangState, + ); + + expect(result).toBe(vorgangStatistic); + }); + + it('should return vorgangFilter', () => { + const result: VorgangFilter = VorgangSelectors.vorgangFilter.projector(state.VorgangState); + + expect(result).toBe(vorgangFilter); + }); + + it('should return vorgangView', () => { + const result: VorgangView = VorgangSelectors.vorgangView.projector(state.VorgangState); + + expect(result).toBe(vorgangView); + }); + + it('should return searchPreviewList', () => { + const result: StateResource<VorgangListResource> = VorgangSelectors.searchPreviewList.projector( + state.VorgangState, + ); + + expect(result).toBe(searchPreviewList); + }); + + it('should return searchString', () => { + const result: string = VorgangSelectors.searchString.projector(state.VorgangState); + + expect(result).toBe(searchString); + }); + + describe('backButtonUrl', () => { + it('should call vorgangNavigationUtil buildVorgangListRoutePath', () => { + const utilSpy = jest.spyOn(VorgangNavigationUtil, 'buildBackButtonUrl'); + + VorgangSelectors.backButtonUrl.projector(state.VorgangState); + + expect(utilSpy).toHaveBeenCalledWith(state.VorgangState); + }); + }); + + describe('isVorgangViewSelected', () => { + it('should return true if state and view matches', () => { + const result: boolean = VorgangSelectors.isVorgangViewSelected( + VorgangView.VORGANG_LIST, + ).projector(vorgangView); + + expect(result).toBeTruthy(); + }); + + it('should return false if state and view does not match', () => { + const result: boolean = VorgangSelectors.isVorgangViewSelected(VorgangView.NEU).projector( + vorgangView, + ); + + expect(result).toBeFalsy(); + }); + }); + + describe('getVorgangViewRoutePath', () => { + it('should return /alle/neu', () => { + const result: string = VorgangSelectors.getVorgangViewRoutePath(VorgangView.NEU).projector( + vorgangFilter, + ); + + expect(result).toBe('/alle/neu'); + }); + }); + + //VorgangWithEingang + it('should return vorgangWithEingang', () => { + const result: StateResource<VorgangWithEingangResource> = + VorgangSelectors.vorgangWithEingang.projector(state.VorgangState); + + expect(result).toBe(vorgangWithEingang); + }); + + describe('attachmentList', () => { + it('should Return attachmentList from state', () => { + const result: StateResource<BinaryFileListResource> = + VorgangSelectors.attachmentList.projector(state.VorgangState); + + expect(result).toBe(attachmentList); + }); + }); + + describe('representationList', () => { + it('should Return representationList from state', () => { + const result: StateResource<BinaryFileListResource> = + VorgangSelectors.representationList.projector(state.VorgangState); + + expect(result).toBe(representationList); + }); + }); + + describe('forwardPendingCommand', () => { + it('should return command from state', () => { + const result: StateResource<CommandResource> = + VorgangSelectors.forwardPendingCommand.projector(state.VorgangState); + + expect(result).toBe(forwardPendingCommand); + }); + }); + + describe('send postfach command', () => { + it('should return command from state', () => { + const result: StateResource<CommandResource> = + VorgangSelectors.sendPostfachNachrichtPendingCommand.projector(state.VorgangState); + + expect(result).toBe(sendPostfachNachrichtPendingCommand); + }); + }); + + describe('user assign command', () => { + it('should return command from state', () => { + const result: StateResource<CommandResource> = VorgangSelectors.assignUserCommand.projector( + state.VorgangState, + ); + + expect(result).toBe(assignUserCommand); + }); + }); + + describe('stausCommandMap', () => { + it('should select statusCommandMap from state', () => { + const result: StatusCommandMap = VorgangSelectors.statusCommandMap.projector( + state.VorgangState, + ); + + expect(result).toBe(statusCommandMap); + }); + }); + + describe('getStatusCommand', () => { + it('should return statusCommand from state by order', () => { + const result: boolean = VorgangSelectors.getStatusCommand( + CommandOrder.VORGANG_ANNEHMEN, + ).projector(statusCommandMap); + + expect(result).toBe(annehmenCommand); + }); + }); + + describe('revokeCommand', () => { + it('should return revokeCommand from state', () => { + const result: StateResource<CommandResource> = VorgangSelectors.revokeCommand.projector( + state.VorgangState, + ); + + expect(result).toBe(revokeCommand); + }); + }); + + describe('exportCommand', () => { + it('should return exportCommand from state', () => { + const result: StateResource<boolean> = VorgangSelectors.vorgangExport.projector( + state.VorgangState, + ); + + expect(result).toBe(vorgangExport); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.selectors.ts b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.selectors.ts index 2e9b7884bcf603a857b95f6933cfda028806aefa..8e6bc79b6cef37c29b287598531ab0af36ea0492 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.selectors.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/+state/vorgang.selectors.ts @@ -26,42 +26,123 @@ import { CommandOrder, CommandResource } from '@alfa-client/command-shared'; import { EMPTY_STRING, StateResource } from '@alfa-client/tech-shared'; import { MemoizedSelector, createFeatureSelector, createSelector } from '@ngrx/store'; import { buildBackButtonUrl, buildVorgangFilterViewRoutePath } from '../vorgang-navigation.util'; -import { StatusCommandMap, VorgangFilter, VorgangListResource, VorgangResource, VorgangStatistic, VorgangView, VorgangWithEingangResource } from '../vorgang.model'; +import { + StatusCommandMap, + VorgangFilter, + VorgangListResource, + VorgangResource, + VorgangStatistic, + VorgangView, + VorgangWithEingangResource, +} from '../vorgang.model'; import { VORGANG_FEATURE_KEY, VorgangState } from './vorgang.reducer'; -export const getVorgangState: MemoizedSelector<object, VorgangState> = createFeatureSelector<VorgangState>(VORGANG_FEATURE_KEY); +export const getVorgangState: MemoizedSelector<object, VorgangState> = + createFeatureSelector<VorgangState>(VORGANG_FEATURE_KEY); // VorgangList -export const vorgangList: MemoizedSelector<VorgangState, StateResource<VorgangListResource>> = createSelector(getVorgangState, (state: VorgangState) => state.vorgangList); -export const vorgaenge: MemoizedSelector<VorgangState, VorgangResource[]> = createSelector(getVorgangState, (state: VorgangState) => state.vorgaenge); -export const vorgangStatistic: MemoizedSelector<VorgangState, StateResource<VorgangStatistic>> = createSelector(getVorgangState, (state: VorgangState) => state.vorgangStatistic); +export const vorgangList: MemoizedSelector< + VorgangState, + StateResource<VorgangListResource> +> = createSelector(getVorgangState, (state: VorgangState) => state.vorgangList); +export const vorgaenge: MemoizedSelector<VorgangState, VorgangResource[]> = createSelector( + getVorgangState, + (state: VorgangState) => state.vorgaenge, +); +export const vorgangStatistic: MemoizedSelector< + VorgangState, + StateResource<VorgangStatistic> +> = createSelector(getVorgangState, (state: VorgangState) => state.vorgangStatistic); -export const vorgangFilter = createSelector(getVorgangState, (state: VorgangState) => state.vorgangFilter); -export const vorgangView = createSelector(getVorgangState, (state: VorgangState) => state.vorgangView); +export const vorgangFilter = createSelector( + getVorgangState, + (state: VorgangState) => state.vorgangFilter, +); +export const vorgangView = createSelector( + getVorgangState, + (state: VorgangState) => state.vorgangView, +); -export const searchPreviewList: MemoizedSelector<VorgangState, StateResource<VorgangListResource>> = createSelector(getVorgangState, (state: VorgangState) => state.searchPreviewList); -export const searchString: MemoizedSelector<VorgangState, string> = createSelector(getVorgangState, (state: VorgangState) => state.searchString); +export const searchPreviewList: MemoizedSelector< + VorgangState, + StateResource<VorgangListResource> +> = createSelector(getVorgangState, (state: VorgangState) => state.searchPreviewList); +export const searchString: MemoizedSelector<VorgangState, string> = createSelector( + getVorgangState, + (state: VorgangState) => state.searchString, +); -export const backButtonUrl: MemoizedSelector<VorgangState, string> = createSelector(getVorgangState, (state: VorgangState) => buildBackButtonUrl(state)); +export const backButtonUrl: MemoizedSelector<VorgangState, string> = createSelector( + getVorgangState, + (state: VorgangState) => buildBackButtonUrl(state), +); -export const isVorgangViewSelected = (view: VorgangView) => createSelector(vorgangView, (vorgangViewInState: VorgangView) => vorgangViewInState === view); -export const getVorgangViewRoutePath = (view: VorgangView) => createSelector(vorgangFilter, (vorgangFilterInState: VorgangFilter) => buildVorgangFilterViewRoutePath(vorgangFilterInState, view, EMPTY_STRING)); +export const isVorgangViewSelected = (view: VorgangView) => + createSelector(vorgangView, (vorgangViewInState: VorgangView) => vorgangViewInState === view); +export const getVorgangViewRoutePath = (view: VorgangView) => + createSelector(vorgangFilter, (vorgangFilterInState: VorgangFilter) => + buildVorgangFilterViewRoutePath(vorgangFilterInState, view, EMPTY_STRING), + ); -export const isVorgangFilterSelected = (filter: VorgangFilter) => createSelector(vorgangFilter, (vorgangFilterInState: VorgangFilter) => vorgangFilterInState === filter); -export const getVorgangFilterRoutePath = (filter: VorgangFilter) => createSelector(vorgangView, searchString, (vorgangViewInState: VorgangView, searchStringInState: string) => buildVorgangFilterViewRoutePath(filter, vorgangViewInState, searchStringInState)); +export const isVorgangFilterSelected = (filter: VorgangFilter) => + createSelector( + vorgangFilter, + (vorgangFilterInState: VorgangFilter) => vorgangFilterInState === filter, + ); +export const getVorgangFilterRoutePath = (filter: VorgangFilter) => + createSelector( + vorgangView, + searchString, + (vorgangViewInState: VorgangView, searchStringInState: string) => + buildVorgangFilterViewRoutePath(filter, vorgangViewInState, searchStringInState), + ); //VorgangWithEingang -export const vorgangWithEingang: MemoizedSelector<VorgangState, StateResource<VorgangWithEingangResource>> = createSelector(getVorgangState, (state: VorgangState) => state.vorgangWithEingang); -export const attachmentList: MemoizedSelector<VorgangState, StateResource<BinaryFileListResource>> = createSelector(getVorgangState, (state: VorgangState) => state.attachmentList); -export const representationList: MemoizedSelector<VorgangState, StateResource<BinaryFileListResource>> = createSelector(getVorgangState, (state: VorgangState) => state.representationList); -export const forwardPendingCommand: MemoizedSelector<VorgangState, StateResource<CommandResource>> = createSelector(getVorgangState, (state: VorgangState) => state.forwardPendingCommand); -export const sendPostfachNachrichtPendingCommand: MemoizedSelector<VorgangState, StateResource<CommandResource>> = createSelector(getVorgangState, (state: VorgangState) => state.sendPostfachNachrichtPendingCommand); +export const vorgangWithEingang: MemoizedSelector< + VorgangState, + StateResource<VorgangWithEingangResource> +> = createSelector(getVorgangState, (state: VorgangState) => state.vorgangWithEingang); +export const attachmentList: MemoizedSelector< + VorgangState, + StateResource<BinaryFileListResource> +> = createSelector(getVorgangState, (state: VorgangState) => state.attachmentList); +export const representationList: MemoizedSelector< + VorgangState, + StateResource<BinaryFileListResource> +> = createSelector(getVorgangState, (state: VorgangState) => state.representationList); +export const forwardPendingCommand: MemoizedSelector< + VorgangState, + StateResource<CommandResource> +> = createSelector(getVorgangState, (state: VorgangState) => state.forwardPendingCommand); +export const sendPostfachNachrichtPendingCommand: MemoizedSelector< + VorgangState, + StateResource<CommandResource> +> = createSelector( + getVorgangState, + (state: VorgangState) => state.sendPostfachNachrichtPendingCommand, +); -export const assignUserCommand: MemoizedSelector<VorgangState, StateResource<CommandResource>> = createSelector(getVorgangState, (state: VorgangState) => state.assignUserCommand); +export const assignUserCommand: MemoizedSelector< + VorgangState, + StateResource<CommandResource> +> = createSelector(getVorgangState, (state: VorgangState) => state.assignUserCommand); -export const statusCommandMap: MemoizedSelector<VorgangState, StatusCommandMap> = createSelector(getVorgangState, (state: VorgangState) => state.statusCommandMap); -export const getStatusCommand = (order: CommandOrder) => createSelector(statusCommandMap, (statusCommandMapInState: StatusCommandMap) => statusCommandMapInState[order]); +export const statusCommandMap: MemoizedSelector<VorgangState, StatusCommandMap> = createSelector( + getVorgangState, + (state: VorgangState) => state.statusCommandMap, +); +export const getStatusCommand = (order: CommandOrder) => + createSelector( + statusCommandMap, + (statusCommandMapInState: StatusCommandMap) => statusCommandMapInState[order], + ); -export const revokeCommand: MemoizedSelector<VorgangState, StateResource<CommandResource>> = createSelector(getVorgangState, (state: VorgangState) => state.revokeCommand); +export const revokeCommand: MemoizedSelector< + VorgangState, + StateResource<CommandResource> +> = createSelector(getVorgangState, (state: VorgangState) => state.revokeCommand); -export const vorgangExport: MemoizedSelector<VorgangState, StateResource<boolean>> = createSelector(getVorgangState, (state: VorgangState) => state.vorgangExport); \ No newline at end of file +export const vorgangExport: MemoizedSelector<VorgangState, StateResource<boolean>> = createSelector( + getVorgangState, + (state: VorgangState) => state.vorgangExport, +); diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.spec.ts index 53bfce3accaa2c223bc00a6f7887f72c92e2233e..f6ba035446518ba10b12353177a3f766c8a0f1e4 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.spec.ts @@ -30,167 +30,174 @@ import { VorgangCommandService } from './vorgang-command.service'; import { VorgangWithEingangResource } from './vorgang.model'; describe('VorgangCommandService', () => { - let service: VorgangCommandService; - let facade: Mock<VorgangFacade>; - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - - beforeEach(() => { - facade = mock(VorgangFacade); - - service = new VorgangCommandService(useFromMock(facade)); - }) - - describe('getAnnehmenCommand', () => { - - it('should call facade', () => { - service.getAnnehmenCommand(); - - expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_ANNEHMEN); - }) - }) - - describe('annehmen', () => { - - it('should call facade', () => { - service.annehmen(vorgangWithEingang); - - expect(facade.annehmen).toHaveBeenCalledWith(vorgangWithEingang, createCreateCommand(CommandOrder.VORGANG_ANNEHMEN)); - }) - }) - - describe('getBearbeitenCommand', () => { - - it('should call facade', () => { - service.getBearbeitenCommand(); - - expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_BEARBEITEN); - }) - }) - - describe('bearbeiten', () => { - - it('should call facade', () => { - service.bearbeiten(vorgangWithEingang); - - expect(facade.bearbeiten).toHaveBeenCalledWith(vorgangWithEingang, createCreateCommand(CommandOrder.VORGANG_BEARBEITEN)); - }) - }) - - describe('getBeschiedenCommand', () => { - - it('should call facade', () => { - service.getBeschiedenCommand(); - - expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_BESCHEIDEN); - }) - }) - - describe('bescheiden', () => { - - it('should call facade', () => { - service.bescheiden(vorgangWithEingang); - - expect(facade.bescheiden).toHaveBeenCalledWith(vorgangWithEingang, createCreateCommand(CommandOrder.VORGANG_BESCHEIDEN)); - }) - }) - - describe('getVerwerfenCommand', () => { - - it('should call facade', () => { - service.getVerwerfenCommand(); - - expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_VERWERFEN); - }) - }) - - describe('verwerfen', () => { - - it('should call facade', () => { - service.verwerfen(vorgangWithEingang); - - expect(facade.verwerfen).toHaveBeenCalledWith(vorgangWithEingang, createCreateCommand(CommandOrder.VORGANG_VERWERFEN)); - }) - }) - - describe('getWiedereroeffnenCommand', () => { - - it('should call facade', () => { - service.getWiedereroeffnenCommand(); - - expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_WIEDEREROEFFNEN); - }) - }) - - describe('wiedereroeffnen', () => { - - it('should call facade', () => { - service.wiedereroeffnen(vorgangWithEingang); - - expect(facade.wiedereroeffnen).toHaveBeenCalledWith(vorgangWithEingang, createCreateCommand(CommandOrder.VORGANG_WIEDEREROEFFNEN)); - }) - }) - - describe('getZurueckholenCommand', () => { - - it('should call facade', () => { - service.getZurueckholenCommand(); - - expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_ZURUECKHOLEN); - }) - }) - - describe('zurueckholen', () => { - - it('should call facade', () => { - service.zurueckholen(vorgangWithEingang); - - expect(facade.zurueckholen).toHaveBeenCalledWith(vorgangWithEingang, createCreateCommand(CommandOrder.VORGANG_ZURUECKHOLEN)); - }) - }) - - describe('getZurueckstellenCommand', () => { - - it('should call facade', () => { - service.getZurueckstellenCommand(); - - expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_ZURUECKSTELLEN); - }) - }) - - describe('zurueckstellen', () => { - - it('should call facade', () => { - service.zurueckstellen(vorgangWithEingang); - - expect(facade.zurueckstellen).toHaveBeenCalledWith(vorgangWithEingang, createCreateCommand(CommandOrder.VORGANG_ZURUECKSTELLEN)); - }) - }) - - describe('getAbschliessenCommand', () => { - - it('should call facade', () => { - service.getAbschliessenCommand(); - - expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_ABSCHLIESSEN); - }) - }) - - describe('abschliessen', () => { - - it('should call facade', () => { - service.abschliessen(vorgangWithEingang); - - expect(facade.abschliessen).toHaveBeenCalledWith(vorgangWithEingang, createCreateCommand(CommandOrder.VORGANG_ABSCHLIESSEN)); - }) - }) - - describe('getRevokeCommand', () => { - - it('should call facade', () => { - service.getRevokeCommand(); - - expect(facade.getRevokeCommand).toHaveBeenCalled(); - }) - }) -}) + let service: VorgangCommandService; + let facade: Mock<VorgangFacade>; + + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + + beforeEach(() => { + facade = mock(VorgangFacade); + + service = new VorgangCommandService(useFromMock(facade)); + }); + + describe('getAnnehmenCommand', () => { + it('should call facade', () => { + service.getAnnehmenCommand(); + + expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_ANNEHMEN); + }); + }); + + describe('annehmen', () => { + it('should call facade', () => { + service.annehmen(vorgangWithEingang); + + expect(facade.annehmen).toHaveBeenCalledWith( + vorgangWithEingang, + createCreateCommand(CommandOrder.VORGANG_ANNEHMEN), + ); + }); + }); + + describe('getBearbeitenCommand', () => { + it('should call facade', () => { + service.getBearbeitenCommand(); + + expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_BEARBEITEN); + }); + }); + + describe('bearbeiten', () => { + it('should call facade', () => { + service.bearbeiten(vorgangWithEingang); + + expect(facade.bearbeiten).toHaveBeenCalledWith( + vorgangWithEingang, + createCreateCommand(CommandOrder.VORGANG_BEARBEITEN), + ); + }); + }); + + describe('getBeschiedenCommand', () => { + it('should call facade', () => { + service.getBeschiedenCommand(); + + expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_BESCHEIDEN); + }); + }); + + describe('bescheiden', () => { + it('should call facade', () => { + service.bescheiden(vorgangWithEingang); + + expect(facade.bescheiden).toHaveBeenCalledWith( + vorgangWithEingang, + createCreateCommand(CommandOrder.VORGANG_BESCHEIDEN), + ); + }); + }); + + describe('getVerwerfenCommand', () => { + it('should call facade', () => { + service.getVerwerfenCommand(); + + expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_VERWERFEN); + }); + }); + + describe('verwerfen', () => { + it('should call facade', () => { + service.verwerfen(vorgangWithEingang); + + expect(facade.verwerfen).toHaveBeenCalledWith( + vorgangWithEingang, + createCreateCommand(CommandOrder.VORGANG_VERWERFEN), + ); + }); + }); + + describe('getWiedereroeffnenCommand', () => { + it('should call facade', () => { + service.getWiedereroeffnenCommand(); + + expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_WIEDEREROEFFNEN); + }); + }); + + describe('wiedereroeffnen', () => { + it('should call facade', () => { + service.wiedereroeffnen(vorgangWithEingang); + + expect(facade.wiedereroeffnen).toHaveBeenCalledWith( + vorgangWithEingang, + createCreateCommand(CommandOrder.VORGANG_WIEDEREROEFFNEN), + ); + }); + }); + + describe('getZurueckholenCommand', () => { + it('should call facade', () => { + service.getZurueckholenCommand(); + + expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_ZURUECKHOLEN); + }); + }); + + describe('zurueckholen', () => { + it('should call facade', () => { + service.zurueckholen(vorgangWithEingang); + + expect(facade.zurueckholen).toHaveBeenCalledWith( + vorgangWithEingang, + createCreateCommand(CommandOrder.VORGANG_ZURUECKHOLEN), + ); + }); + }); + + describe('getZurueckstellenCommand', () => { + it('should call facade', () => { + service.getZurueckstellenCommand(); + + expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_ZURUECKSTELLEN); + }); + }); + + describe('zurueckstellen', () => { + it('should call facade', () => { + service.zurueckstellen(vorgangWithEingang); + + expect(facade.zurueckstellen).toHaveBeenCalledWith( + vorgangWithEingang, + createCreateCommand(CommandOrder.VORGANG_ZURUECKSTELLEN), + ); + }); + }); + + describe('getAbschliessenCommand', () => { + it('should call facade', () => { + service.getAbschliessenCommand(); + + expect(facade.getStatusCommand).toHaveBeenCalledWith(CommandOrder.VORGANG_ABSCHLIESSEN); + }); + }); + + describe('abschliessen', () => { + it('should call facade', () => { + service.abschliessen(vorgangWithEingang); + + expect(facade.abschliessen).toHaveBeenCalledWith( + vorgangWithEingang, + createCreateCommand(CommandOrder.VORGANG_ABSCHLIESSEN), + ); + }); + }); + + describe('getRevokeCommand', () => { + it('should call facade', () => { + service.getRevokeCommand(); + + expect(facade.getRevokeCommand).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.ts index 7b345dcc8b4dbbc353fd45d67773eb7fb58ba1a5..96059578bb8016fbac9f6b1780e53e86eac22296 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-command.service.ts @@ -27,78 +27,86 @@ import { StateResource } from '@alfa-client/tech-shared'; import { Observable } from 'rxjs'; import { VorgangFacade } from './+state/vorgang.facade'; import { VorgangWithEingangResource } from './vorgang.model'; -import { createAbschliessenCommand, createAnnehmenCommand, createBearbeitenCommand, createBescheidenCommand, createVerwerfenCommand, createWiedereroeffnenCommand, createZurueckholenCommand, createZurueckstellenCommand } from './vorgang.util'; +import { + createAbschliessenCommand, + createAnnehmenCommand, + createBearbeitenCommand, + createBescheidenCommand, + createVerwerfenCommand, + createWiedereroeffnenCommand, + createZurueckholenCommand, + createZurueckstellenCommand, +} from './vorgang.util'; @Injectable({ providedIn: 'root' }) export class VorgangCommandService { + constructor(private facade: VorgangFacade) {} - constructor(private facade: VorgangFacade) { } + public getAnnehmenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getStatusCommand(CommandOrder.VORGANG_ANNEHMEN); + } - public getAnnehmenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getStatusCommand(CommandOrder.VORGANG_ANNEHMEN); - } + public annehmen(vorgang: VorgangWithEingangResource): void { + this.facade.annehmen(vorgang, createAnnehmenCommand()); + } - public annehmen(vorgang: VorgangWithEingangResource): void { - this.facade.annehmen(vorgang, createAnnehmenCommand()); - } + public getBearbeitenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getStatusCommand(CommandOrder.VORGANG_BEARBEITEN); + } - public getBearbeitenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getStatusCommand(CommandOrder.VORGANG_BEARBEITEN); - } + public bearbeiten(vorgang: VorgangWithEingangResource): void { + this.facade.bearbeiten(vorgang, createBearbeitenCommand()); + } - public bearbeiten(vorgang: VorgangWithEingangResource): void { - this.facade.bearbeiten(vorgang, createBearbeitenCommand()); - } + public getBeschiedenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getStatusCommand(CommandOrder.VORGANG_BESCHEIDEN); + } - public getBeschiedenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getStatusCommand(CommandOrder.VORGANG_BESCHEIDEN); - } + public bescheiden(vorgang: VorgangWithEingangResource): void { + this.facade.bescheiden(vorgang, createBescheidenCommand()); + } - public bescheiden(vorgang: VorgangWithEingangResource): void { - this.facade.bescheiden(vorgang, createBescheidenCommand()); - } + public getVerwerfenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getStatusCommand(CommandOrder.VORGANG_VERWERFEN); + } - public getVerwerfenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getStatusCommand(CommandOrder.VORGANG_VERWERFEN); - } + public verwerfen(vorgang: VorgangWithEingangResource): void { + this.facade.verwerfen(vorgang, createVerwerfenCommand()); + } - public verwerfen(vorgang: VorgangWithEingangResource): void { - this.facade.verwerfen(vorgang, createVerwerfenCommand()); - } + public getWiedereroeffnenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getStatusCommand(CommandOrder.VORGANG_WIEDEREROEFFNEN); + } - public getWiedereroeffnenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getStatusCommand(CommandOrder.VORGANG_WIEDEREROEFFNEN); - } + public wiedereroeffnen(vorgang: VorgangWithEingangResource): void { + this.facade.wiedereroeffnen(vorgang, createWiedereroeffnenCommand()); + } - public wiedereroeffnen(vorgang: VorgangWithEingangResource): void { - this.facade.wiedereroeffnen(vorgang, createWiedereroeffnenCommand()); - } + public getZurueckholenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getStatusCommand(CommandOrder.VORGANG_ZURUECKHOLEN); + } - public getZurueckholenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getStatusCommand(CommandOrder.VORGANG_ZURUECKHOLEN); - } + public zurueckholen(vorgang: VorgangWithEingangResource): void { + this.facade.zurueckholen(vorgang, createZurueckholenCommand()); + } - public zurueckholen(vorgang: VorgangWithEingangResource): void { - this.facade.zurueckholen(vorgang, createZurueckholenCommand()); - } + public getZurueckstellenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getStatusCommand(CommandOrder.VORGANG_ZURUECKSTELLEN); + } - public getZurueckstellenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getStatusCommand(CommandOrder.VORGANG_ZURUECKSTELLEN); - } + public zurueckstellen(vorgang: VorgangWithEingangResource): void { + this.facade.zurueckstellen(vorgang, createZurueckstellenCommand()); + } - public zurueckstellen(vorgang: VorgangWithEingangResource): void { - this.facade.zurueckstellen(vorgang, createZurueckstellenCommand()); - } + public getAbschliessenCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getStatusCommand(CommandOrder.VORGANG_ABSCHLIESSEN); + } - public getAbschliessenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getStatusCommand(CommandOrder.VORGANG_ABSCHLIESSEN); - } + public abschliessen(vorgang: VorgangWithEingangResource): void { + this.facade.abschliessen(vorgang, createAbschliessenCommand()); + } - public abschliessen(vorgang: VorgangWithEingangResource): void { - this.facade.abschliessen(vorgang, createAbschliessenCommand()); - } - - public getRevokeCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getRevokeCommand(); - } -} \ No newline at end of file + public getRevokeCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getRevokeCommand(); + } +} diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-http-error.service.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-http-error.service.spec.ts index fc782e95f6a8ec178a3668e88de8d0909f7b9a36..875db7a7f80dd0d718e4c82a6c08ab7c1ddc671f 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-http-error.service.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-http-error.service.spec.ts @@ -29,24 +29,24 @@ import { VorgangHttpErrorService } from './vorgang-http-error.service'; import { VorgangService } from './vorgang.service'; describe('VorgangHttpErrorService', () => { - - let service: VorgangHttpErrorService; - let errorHandler: Mock<HttpErrorHandler> = mock(HttpErrorHandler); - let vorgangService: Mock<VorgangService> = mock(VorgangService); - - beforeEach(() => { - service = new VorgangHttpErrorService(useFromMock(errorHandler), useFromMock(vorgangService)); - }) - - describe('register', () => { - - describe('getVorgang', () => { - - it('should call error handler', () => { - service.register(); - - expect(errorHandler.registerCustomHandling).toHaveBeenCalledWith(VorgangRepository.GET_VORGANG, expect.anything()); - }) - }) - }) -}) \ No newline at end of file + let service: VorgangHttpErrorService; + let errorHandler: Mock<HttpErrorHandler> = mock(HttpErrorHandler); + let vorgangService: Mock<VorgangService> = mock(VorgangService); + + beforeEach(() => { + service = new VorgangHttpErrorService(useFromMock(errorHandler), useFromMock(vorgangService)); + }); + + describe('register', () => { + describe('getVorgang', () => { + it('should call error handler', () => { + service.register(); + + expect(errorHandler.registerCustomHandling).toHaveBeenCalledWith( + VorgangRepository.GET_VORGANG, + expect.anything(), + ); + }); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-http-error.service.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-http-error.service.ts index 8aa304cf77bff3b1611198f421d6f4894f14bcec..1eb7c2f3bca7405ce45e2cddc31204350f43a9e8 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-http-error.service.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-http-error.service.ts @@ -28,12 +28,16 @@ import { VorgangService } from './vorgang.service'; @Injectable({ providedIn: 'root' }) export class VorgangHttpErrorService { + constructor( + private errorHandler: HttpErrorHandler, + private vorgangService: VorgangService, + ) { + this.register(); + } - constructor(private errorHandler: HttpErrorHandler, private vorgangService: VorgangService) { - this.register(); - } - - register(): void { - this.errorHandler.registerCustomHandling(VorgangRepository.GET_VORGANG, () => this.vorgangService.clearVorgang()); - } -} \ No newline at end of file + register(): void { + this.errorHandler.registerCustomHandling(VorgangRepository.GET_VORGANG, () => + this.vorgangService.clearVorgang(), + ); + } +} diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-list.service.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-list.service.spec.ts index 430d4190ec82f88cb437f7a3e8cc8c77c4d592a0..8c9236fd4c65659c85e9068b3addddcc90c1093b 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-list.service.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-list.service.spec.ts @@ -22,7 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ApiRootFacade, ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; -import { StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { cold, hot } from 'jest-marbles'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; @@ -35,354 +39,373 @@ import { VorgangFilter, VorgangListResource, VorgangStatistic, VorgangView } fro import * as VorgangNavigationUtil from './vorgang-navigation.util'; describe('VorgangListService', () => { - let service: VorgangListService; - let vorgangFacade: Mock<VorgangFacade>; - let apiRootFacade: Mock<ApiRootFacade>; - - beforeEach(() => { - vorgangFacade = mock(VorgangFacade); - apiRootFacade = mock(ApiRootFacade); - - service = new VorgangListService(useFromMock(vorgangFacade), useFromMock(apiRootFacade)); - }) - - describe('getVorgangList', () => { - - describe('load required data', () => { - - const vorgangListStateResource: StateResource<VorgangListResource> = createStateResource(createVorgangListResource()); - - beforeEach(() => { - service.loadVorgangList = jest.fn(); - - vorgangFacade.getVorgangList.mockReturnValue(of(vorgangListStateResource)); - }) - - it('should get vorgang list by facade', () => { - service.getVorgangList(); - - expect(vorgangFacade.getVorgangList).toHaveBeenCalled(); - }) - - it('should get apiroot by service', () => { - service.getVorgangList(); - - expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); - }) - - it('should get current route data by navigation facade', () => { - service.getVorgangList(); - - expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); - }) - }) - - describe('on loaded resource', () => { - - const vorgangListStateResource: StateResource<VorgangListResource> = createStateResource(createVorgangListResource()); - const apiRootStateResource: StateResource<ApiRootResource> = createStateResource(createApiRootResource()); - const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; - const vorgangView: VorgangView = VorgangView.NEU; - const searchString: string = 'dummySearchString'; - - beforeEach(() => { - service.loadVorgangList = jest.fn(); - - vorgangFacade.getVorgangList.mockReturnValue(hot('-a', { a: vorgangListStateResource })); - apiRootFacade.getApiRoot.mockReturnValue(of(apiRootStateResource)); - vorgangFacade.getVorgangFilter.mockReturnValue(of(vorgangFilter)); - vorgangFacade.getVorgangView.mockReturnValue(of(vorgangView)); - vorgangFacade.getSearchString.mockReturnValue(of(searchString)); - }) - - it('should return loaded resource', () => { - const vorgangList = service.getVorgangList(); - - expect(vorgangList).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: vorgangListStateResource })); - }) - - it('should not load vorgangList', () => { - service.getVorgangList(); - - expect(service.loadVorgangList).not.toHaveBeenCalled(); - }) - }) - - describe('on reload required', () => { - - const vorgangListResource: VorgangListResource = createVorgangListResource(); - const vorgangListStateResource: StateResource<VorgangListResource> = { ...createStateResource(vorgangListResource), reload: true }; - const apiRootStateResource: StateResource<ApiRootResource> = createStateResource(createApiRootResource()); - const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; - const vorgangView: VorgangView = VorgangView.NEU; - const searchString: string = 'dummySearchString'; - - beforeEach(() => { - vorgangFacade.getVorgangList.mockReturnValue(hot('-a', { a: vorgangListStateResource })); - apiRootFacade.getApiRoot.mockReturnValue(of(apiRootStateResource)); - vorgangFacade.getVorgangFilter.mockReturnValue(of(vorgangFilter)); - vorgangFacade.getVorgangView.mockReturnValue(of(vorgangView)); - vorgangFacade.getSearchString.mockReturnValue(of(searchString)); - }) - - it('should return value on loaded resource', () => { - const vorgangList = service.getVorgangList(); - - expect(vorgangList).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: vorgangListStateResource })); - }) - }) - }) - - describe('loadVorgangList', () => { - - const apiRootResource: ApiRootResource = createApiRootResource([ApiRootLinkRel.SEARCH_ALLE]); - const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; - const searchString: string = 'searchDummyString'; - - describe('on search view', () => { - - const vorgangView: VorgangView = VorgangView.SEARCH; - - it('should call facade searchVorgaengeBy', () => { - service.loadVorgangList(apiRootResource, vorgangFilter, vorgangView, searchString); - - expect(vorgangFacade.searchVorgaengeBy).toHaveBeenCalledWith(apiRootResource, searchString, ApiRootLinkRel.SEARCH_ALLE); - }) - - it('should call getSearchLinkRel', () => { - const utilSpy = jest.spyOn(VorgangNavigationUtil, 'getSearchLinkRel'); - - service.loadVorgangList(apiRootResource, vorgangFilter, vorgangView, searchString); - - expect(utilSpy).toHaveBeenCalledWith(vorgangFilter); - }) - }) - - describe('on vorganglist loadVorgangList', () => { - - const vorgangView: VorgangView = VorgangView.VORGANG_LIST; - - it('should call facade loadVorgaengeList', () => { - service.loadVorgangList(apiRootResource, vorgangFilter, vorgangView, searchString); - - expect(vorgangFacade.loadVorgangList).toHaveBeenCalled(); - }) - - it('should call buildLinkRel', () => { - const utilSpy = jest.spyOn(VorgangNavigationUtil, 'buildLinkRel'); - - service.loadVorgangList(apiRootResource, vorgangFilter, vorgangView, searchString); - - expect(utilSpy).toHaveBeenCalledWith(vorgangFilter, vorgangView); - }) - }) - }) - - describe('loadNextPage', () => { - - it('should call facade', () => { - service.loadNextPage(); - - expect(vorgangFacade.loadNextPage).toHaveBeenCalled(); - }) - }) - - describe('getVorgaenge', () => { - - it('should call facade', () => { - service.getVorgaenge(); - - expect(vorgangFacade.getVorgaenge).toHaveBeenCalled(); - }) - }) - - describe('getVorgangStatistic', () => { - const vorgangStatisticStateResource: StateResource<VorgangStatistic> = createStateResource(<VorgangStatistic>{}); - - beforeEach(() => { - vorgangFacade.getVorgangStatistic.mockReturnValue(of(vorgangStatisticStateResource)); - service.getVorgangList = jest.fn().mockReturnValue(of(<StateResource<VorgangListResource>>{})); - }) - - it('should call facade', () => { - service.getVorgangStatistic(); - - expect(vorgangFacade.getVorgangStatistic).toHaveBeenCalled(); - }) - - it('should return vorgangStatistic', (done) => { - service.getVorgangStatistic().subscribe(vorgangStatistic => { - expect(vorgangStatistic).toEqual(vorgangStatisticStateResource); - done(); - }) - }) - }) - - describe('getSelectedFilterAsRouteParam', () => { - - beforeEach(() => { - vorgangFacade.getVorgangFilter.mockReturnValue(of(VorgangFilter.ALLE)); - }) - - it('should call facade', (done) => { - service.getSelectedFilterAsRouteParam().subscribe(() => { - expect(vorgangFacade.getVorgangFilter).toHaveBeenCalled(); - done(); - }); - }) - - it('should return value', (done) => { - service.getSelectedFilterAsRouteParam().subscribe(routeParam => { - expect(routeParam).toBe('alle'); - done(); - }); - }) - }) - - describe('isVorgangViewSelected', () => { - - const vorgangView: VorgangView = VorgangView.VORGANG_LIST; - - it('should call facade', () => { - service.isVorgangViewSelected(vorgangView); - - expect(vorgangFacade.isVorgangViewSelected).toHaveBeenCalledWith(vorgangView); - }) - }) - - describe('getVorgangViewRoutePath', () => { - - const vorgangView: VorgangView = VorgangView.VORGANG_LIST; - - it('should call facade', () => { - service.getVorgangViewRoutePath(vorgangView); - - expect(vorgangFacade.getVorgangViewRoutePath).toHaveBeenCalledWith(vorgangView); - }) - }) - - describe('getSearchPreviewList', () => { - - describe('load required data', () => { - - const vorgangListStateResource: StateResource<VorgangListResource> = createStateResource(createVorgangListResource()); - - beforeEach(() => { - service.loadVorgangList = jest.fn(); - - vorgangFacade.getSearchPreviewList.mockReturnValue(of(vorgangListStateResource)); - }) - - it('should get apiroot by facade', () => { - service.getSearchPreviewList(); - - expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); - }) - - it('should get search preview list by facade', () => { - service.getSearchPreviewList(); - - expect(vorgangFacade.getSearchPreviewList).toHaveBeenCalled(); - }) - - it('should get search string by facade', () => { - service.getSearchPreviewList(); - - expect(vorgangFacade.getSearchString).toHaveBeenCalled(); - }) - }) - - describe('on loaded resource', () => { - - const vorgangListStateResource: StateResource<VorgangListResource> = createStateResource(createVorgangListResource()); - const apiRootStateResource: StateResource<ApiRootResource> = createStateResource(createApiRootResource()); - const searchString: string = 'dummySearchString'; - const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; - - beforeEach(() => { - vorgangFacade.getSearchPreviewList.mockReturnValue(hot('-a', { a: vorgangListStateResource })); - vorgangFacade.getSearchString.mockReturnValue(of(searchString)); - apiRootFacade.getApiRoot.mockReturnValue(of(apiRootStateResource)); - vorgangFacade.getVorgangFilter.mockReturnValue(of(vorgangFilter)); - }) - - it('should return loaded resource', () => { - const searchPreviewList = service.getSearchPreviewList(); - - expect(searchPreviewList).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: vorgangListStateResource })); - }) - - it('should not load searchPreviewList', () => { - service.getSearchPreviewList(); - - expect(vorgangFacade.searchForPreview).not.toHaveBeenCalled(); - }) - }) - - describe('on reload required', () => { - - const searchPreviewList: StateResource<VorgangListResource> = { ...createStateResource(createVorgangListResource()), reload: true }; - const apiRootStateResource: StateResource<ApiRootResource> = createStateResource(createApiRootResource()); - const searchString: string = 'dummySearchString'; - const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; - - beforeEach(() => { - vorgangFacade.getSearchPreviewList.mockReturnValue(hot('-a', { a: searchPreviewList })); - vorgangFacade.getSearchString.mockReturnValue(of(searchString)); - apiRootFacade.getApiRoot.mockReturnValue(of(apiRootStateResource)); - vorgangFacade.getVorgangFilter.mockReturnValue(of(vorgangFilter)); - }) - - it('should return value on loaded resource', () => { - const vorgangList = service.getSearchPreviewList(); - - expect(vorgangList).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: { ...searchPreviewList, reload: true } })); - }) - - it('should call facade searchForPreview', () => { - vorgangFacade.getSearchPreviewList.mockReturnValue(of(searchPreviewList)); - - service.getSearchPreviewList().subscribe(); - - expect(vorgangFacade.searchForPreview).toHaveBeenCalledWith(searchString); - }) - }) - }) - - describe('clearSearchPreviewList', () => { - - it('should call facade clearSearchPreviewList', () => { - service.clearSearchPreviewList(); - - expect(vorgangFacade.clearSearchPreviewList).toHaveBeenCalled(); - }) - }) - - describe('clearSearchString', () => { - - it('should call facade clearSearchString', () => { - service.clearSearchString(); - - expect(vorgangFacade.clearSearchString).toHaveBeenCalled(); - }) - }) - - describe('getSearchString', () => { - - it('should call facade getSearchString', () => { - service.getSearchString(); - - expect(vorgangFacade.getSearchString).toHaveBeenCalled(); - }) - }) - - describe('searchForPreview', () => { - - it('should call facade searchForPreview', () => { - const searchString: string = 'dummySearchString'; - service.searchForPreview(searchString); - - expect(vorgangFacade.searchForPreview).toHaveBeenCalledWith(searchString); - }) - }) -}) \ No newline at end of file + let service: VorgangListService; + let vorgangFacade: Mock<VorgangFacade>; + let apiRootFacade: Mock<ApiRootFacade>; + + beforeEach(() => { + vorgangFacade = mock(VorgangFacade); + apiRootFacade = mock(ApiRootFacade); + + service = new VorgangListService(useFromMock(vorgangFacade), useFromMock(apiRootFacade)); + }); + + describe('getVorgangList', () => { + describe('load required data', () => { + const vorgangListStateResource: StateResource<VorgangListResource> = createStateResource( + createVorgangListResource(), + ); + + beforeEach(() => { + service.loadVorgangList = jest.fn(); + + vorgangFacade.getVorgangList.mockReturnValue(of(vorgangListStateResource)); + }); + + it('should get vorgang list by facade', () => { + service.getVorgangList(); + + expect(vorgangFacade.getVorgangList).toHaveBeenCalled(); + }); + + it('should get apiroot by service', () => { + service.getVorgangList(); + + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }); + + it('should get current route data by navigation facade', () => { + service.getVorgangList(); + + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }); + }); + + describe('on loaded resource', () => { + const vorgangListStateResource: StateResource<VorgangListResource> = createStateResource( + createVorgangListResource(), + ); + const apiRootStateResource: StateResource<ApiRootResource> = + createStateResource(createApiRootResource()); + const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + const vorgangView: VorgangView = VorgangView.NEU; + const searchString: string = 'dummySearchString'; + + beforeEach(() => { + service.loadVorgangList = jest.fn(); + + vorgangFacade.getVorgangList.mockReturnValue(hot('-a', { a: vorgangListStateResource })); + apiRootFacade.getApiRoot.mockReturnValue(of(apiRootStateResource)); + vorgangFacade.getVorgangFilter.mockReturnValue(of(vorgangFilter)); + vorgangFacade.getVorgangView.mockReturnValue(of(vorgangView)); + vorgangFacade.getSearchString.mockReturnValue(of(searchString)); + }); + + it('should return loaded resource', () => { + const vorgangList = service.getVorgangList(); + + expect(vorgangList).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: vorgangListStateResource }), + ); + }); + + it('should not load vorgangList', () => { + service.getVorgangList(); + + expect(service.loadVorgangList).not.toHaveBeenCalled(); + }); + }); + + describe('on reload required', () => { + const vorgangListResource: VorgangListResource = createVorgangListResource(); + const vorgangListStateResource: StateResource<VorgangListResource> = { + ...createStateResource(vorgangListResource), + reload: true, + }; + const apiRootStateResource: StateResource<ApiRootResource> = + createStateResource(createApiRootResource()); + const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + const vorgangView: VorgangView = VorgangView.NEU; + const searchString: string = 'dummySearchString'; + + beforeEach(() => { + vorgangFacade.getVorgangList.mockReturnValue(hot('-a', { a: vorgangListStateResource })); + apiRootFacade.getApiRoot.mockReturnValue(of(apiRootStateResource)); + vorgangFacade.getVorgangFilter.mockReturnValue(of(vorgangFilter)); + vorgangFacade.getVorgangView.mockReturnValue(of(vorgangView)); + vorgangFacade.getSearchString.mockReturnValue(of(searchString)); + }); + + it('should return value on loaded resource', () => { + const vorgangList = service.getVorgangList(); + + expect(vorgangList).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: vorgangListStateResource }), + ); + }); + }); + }); + + describe('loadVorgangList', () => { + const apiRootResource: ApiRootResource = createApiRootResource([ApiRootLinkRel.SEARCH_ALLE]); + const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + const searchString: string = 'searchDummyString'; + + describe('on search view', () => { + const vorgangView: VorgangView = VorgangView.SEARCH; + + it('should call facade searchVorgaengeBy', () => { + service.loadVorgangList(apiRootResource, vorgangFilter, vorgangView, searchString); + + expect(vorgangFacade.searchVorgaengeBy).toHaveBeenCalledWith( + apiRootResource, + searchString, + ApiRootLinkRel.SEARCH_ALLE, + ); + }); + + it('should call getSearchLinkRel', () => { + const utilSpy = jest.spyOn(VorgangNavigationUtil, 'getSearchLinkRel'); + + service.loadVorgangList(apiRootResource, vorgangFilter, vorgangView, searchString); + + expect(utilSpy).toHaveBeenCalledWith(vorgangFilter); + }); + }); + + describe('on vorganglist loadVorgangList', () => { + const vorgangView: VorgangView = VorgangView.VORGANG_LIST; + + it('should call facade loadVorgaengeList', () => { + service.loadVorgangList(apiRootResource, vorgangFilter, vorgangView, searchString); + + expect(vorgangFacade.loadVorgangList).toHaveBeenCalled(); + }); + + it('should call buildLinkRel', () => { + const utilSpy = jest.spyOn(VorgangNavigationUtil, 'buildLinkRel'); + + service.loadVorgangList(apiRootResource, vorgangFilter, vorgangView, searchString); + + expect(utilSpy).toHaveBeenCalledWith(vorgangFilter, vorgangView); + }); + }); + }); + + describe('loadNextPage', () => { + it('should call facade', () => { + service.loadNextPage(); + + expect(vorgangFacade.loadNextPage).toHaveBeenCalled(); + }); + }); + + describe('getVorgaenge', () => { + it('should call facade', () => { + service.getVorgaenge(); + + expect(vorgangFacade.getVorgaenge).toHaveBeenCalled(); + }); + }); + + describe('getVorgangStatistic', () => { + const vorgangStatisticStateResource: StateResource<VorgangStatistic> = createStateResource( + <VorgangStatistic>{}, + ); + + beforeEach(() => { + vorgangFacade.getVorgangStatistic.mockReturnValue(of(vorgangStatisticStateResource)); + service.getVorgangList = jest + .fn() + .mockReturnValue(of(<StateResource<VorgangListResource>>{})); + }); + + it('should call facade', () => { + service.getVorgangStatistic(); + + expect(vorgangFacade.getVorgangStatistic).toHaveBeenCalled(); + }); + + it('should return vorgangStatistic', (done) => { + service.getVorgangStatistic().subscribe((vorgangStatistic) => { + expect(vorgangStatistic).toEqual(vorgangStatisticStateResource); + done(); + }); + }); + }); + + describe('getSelectedFilterAsRouteParam', () => { + beforeEach(() => { + vorgangFacade.getVorgangFilter.mockReturnValue(of(VorgangFilter.ALLE)); + }); + + it('should call facade', (done) => { + service.getSelectedFilterAsRouteParam().subscribe(() => { + expect(vorgangFacade.getVorgangFilter).toHaveBeenCalled(); + done(); + }); + }); + + it('should return value', (done) => { + service.getSelectedFilterAsRouteParam().subscribe((routeParam) => { + expect(routeParam).toBe('alle'); + done(); + }); + }); + }); + + describe('isVorgangViewSelected', () => { + const vorgangView: VorgangView = VorgangView.VORGANG_LIST; + + it('should call facade', () => { + service.isVorgangViewSelected(vorgangView); + + expect(vorgangFacade.isVorgangViewSelected).toHaveBeenCalledWith(vorgangView); + }); + }); + + describe('getVorgangViewRoutePath', () => { + const vorgangView: VorgangView = VorgangView.VORGANG_LIST; + + it('should call facade', () => { + service.getVorgangViewRoutePath(vorgangView); + + expect(vorgangFacade.getVorgangViewRoutePath).toHaveBeenCalledWith(vorgangView); + }); + }); + + describe('getSearchPreviewList', () => { + describe('load required data', () => { + const vorgangListStateResource: StateResource<VorgangListResource> = createStateResource( + createVorgangListResource(), + ); + + beforeEach(() => { + service.loadVorgangList = jest.fn(); + + vorgangFacade.getSearchPreviewList.mockReturnValue(of(vorgangListStateResource)); + }); + + it('should get apiroot by facade', () => { + service.getSearchPreviewList(); + + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }); + + it('should get search preview list by facade', () => { + service.getSearchPreviewList(); + + expect(vorgangFacade.getSearchPreviewList).toHaveBeenCalled(); + }); + + it('should get search string by facade', () => { + service.getSearchPreviewList(); + + expect(vorgangFacade.getSearchString).toHaveBeenCalled(); + }); + }); + + describe('on loaded resource', () => { + const vorgangListStateResource: StateResource<VorgangListResource> = createStateResource( + createVorgangListResource(), + ); + const apiRootStateResource: StateResource<ApiRootResource> = + createStateResource(createApiRootResource()); + const searchString: string = 'dummySearchString'; + const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + + beforeEach(() => { + vorgangFacade.getSearchPreviewList.mockReturnValue( + hot('-a', { a: vorgangListStateResource }), + ); + vorgangFacade.getSearchString.mockReturnValue(of(searchString)); + apiRootFacade.getApiRoot.mockReturnValue(of(apiRootStateResource)); + vorgangFacade.getVorgangFilter.mockReturnValue(of(vorgangFilter)); + }); + + it('should return loaded resource', () => { + const searchPreviewList = service.getSearchPreviewList(); + + expect(searchPreviewList).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: vorgangListStateResource }), + ); + }); + + it('should not load searchPreviewList', () => { + service.getSearchPreviewList(); + + expect(vorgangFacade.searchForPreview).not.toHaveBeenCalled(); + }); + }); + + describe('on reload required', () => { + const searchPreviewList: StateResource<VorgangListResource> = { + ...createStateResource(createVorgangListResource()), + reload: true, + }; + const apiRootStateResource: StateResource<ApiRootResource> = + createStateResource(createApiRootResource()); + const searchString: string = 'dummySearchString'; + const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + + beforeEach(() => { + vorgangFacade.getSearchPreviewList.mockReturnValue(hot('-a', { a: searchPreviewList })); + vorgangFacade.getSearchString.mockReturnValue(of(searchString)); + apiRootFacade.getApiRoot.mockReturnValue(of(apiRootStateResource)); + vorgangFacade.getVorgangFilter.mockReturnValue(of(vorgangFilter)); + }); + + it('should return value on loaded resource', () => { + const vorgangList = service.getSearchPreviewList(); + + expect(vorgangList).toBeObservable( + cold('ab', { + a: createEmptyStateResource(true), + b: { ...searchPreviewList, reload: true }, + }), + ); + }); + + it('should call facade searchForPreview', () => { + vorgangFacade.getSearchPreviewList.mockReturnValue(of(searchPreviewList)); + + service.getSearchPreviewList().subscribe(); + + expect(vorgangFacade.searchForPreview).toHaveBeenCalledWith(searchString); + }); + }); + }); + + describe('clearSearchPreviewList', () => { + it('should call facade clearSearchPreviewList', () => { + service.clearSearchPreviewList(); + + expect(vorgangFacade.clearSearchPreviewList).toHaveBeenCalled(); + }); + }); + + describe('clearSearchString', () => { + it('should call facade clearSearchString', () => { + service.clearSearchString(); + + expect(vorgangFacade.clearSearchString).toHaveBeenCalled(); + }); + }); + + describe('getSearchString', () => { + it('should call facade getSearchString', () => { + service.getSearchString(); + + expect(vorgangFacade.getSearchString).toHaveBeenCalled(); + }); + }); + + describe('searchForPreview', () => { + it('should call facade searchForPreview', () => { + const searchString: string = 'dummySearchString'; + service.searchForPreview(searchString); + + expect(vorgangFacade.searchForPreview).toHaveBeenCalledWith(searchString); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-list.service.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-list.service.ts index 81b1ae82b2ee1ff01a941a02e89532f30770ef6c..ef9f2200b1b9fc6ec320798574e7a634fba8802d 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-list.service.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-list.service.ts @@ -22,95 +22,141 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ApiRootFacade, ApiRootResource } from '@alfa-client/api-root-shared'; -import { EMPTY_STRING, StateResource, createEmptyStateResource, doIfLoadingRequired, isNotNull } from '@alfa-client/tech-shared'; +import { + EMPTY_STRING, + StateResource, + createEmptyStateResource, + doIfLoadingRequired, + isNotNull, +} from '@alfa-client/tech-shared'; import { Injectable } from '@angular/core'; import { Observable, combineLatest } from 'rxjs'; import { map, startWith, tap, withLatestFrom } from 'rxjs/operators'; import { VorgangFacade } from './+state/vorgang.facade'; -import { ROUTE_PARAM_BY_VORGANG_FILTER, buildLinkRel, getSearchLinkRel } from './vorgang-navigation.util'; -import { VorgangFilter, VorgangListResource, VorgangResource, VorgangStatistic, VorgangView } from './vorgang.model'; +import { + ROUTE_PARAM_BY_VORGANG_FILTER, + buildLinkRel, + getSearchLinkRel, +} from './vorgang-navigation.util'; +import { + VorgangFilter, + VorgangListResource, + VorgangResource, + VorgangStatistic, + VorgangView, +} from './vorgang.model'; @Injectable({ providedIn: 'root' }) export class VorgangListService { - - static readonly SEARCH_PREVIEW_LIST_LIMIT: number = 7; - - constructor(private vorgangFacade: VorgangFacade, private apiRootFacade: ApiRootFacade) { } - - public getVorgangList(): Observable<StateResource<VorgangListResource>> { - return this.vorgangFacade.getVorgangList().pipe( - withLatestFrom(this.apiRootFacade.getApiRoot(), this.vorgangFacade.getVorgangFilter(), this.vorgangFacade.getVorgangView(), this.vorgangFacade.getSearchString()), - tap(([vorgangList, apiRoot, vorgangFilter, vorgangView, searchString]) => { - doIfLoadingRequired(vorgangList, () => this.loadVorgangList(apiRoot.resource, vorgangFilter, vorgangView, searchString)); - }), - map(([vorgangList, ]) => vorgangList), - startWith(createEmptyStateResource<VorgangListResource>(true))); - } - - loadVorgangList(apiRoot: ApiRootResource, vorgangFilter: VorgangFilter, vorgangView: VorgangView, searchString: string): void { - if(vorgangView === VorgangView.SEARCH){ - this.vorgangFacade.searchVorgaengeBy(apiRoot, searchString, getSearchLinkRel(vorgangFilter)); - } else { - this.vorgangFacade.loadVorgangList(apiRoot, buildLinkRel(vorgangFilter, vorgangView)); - } - } - - public loadNextPage(): void { - this.vorgangFacade.loadNextPage(); - } - - public getVorgaenge(): Observable<VorgangResource[]> { - return this.vorgangFacade.getVorgaenge(); - } - - public getVorgangStatistic(): Observable<StateResource<VorgangStatistic>> { - return this.vorgangFacade.getVorgangStatistic(); - } - - public getSelectedFilterAsRouteParam(): Observable<string> { - return this.vorgangFacade.getVorgangFilter().pipe(map((vorgangFilter: VorgangFilter) => ROUTE_PARAM_BY_VORGANG_FILTER[vorgangFilter])); - } - - public isVorgangViewSelected(vorgangView: VorgangView): Observable<boolean> { - return this.vorgangFacade.isVorgangViewSelected(vorgangView); - } - - public getVorgangViewRoutePath(vorgangView: VorgangView): Observable<string> { - return this.vorgangFacade.getVorgangViewRoutePath(vorgangView); - } - - public getSearchPreviewList(): Observable<StateResource<VorgangListResource>> { - return combineLatest([this.apiRootFacade.getApiRoot(), this.vorgangFacade.getSearchPreviewList(), this.vorgangFacade.getSearchString()]).pipe( - tap(([apiRoot, previewList, searchString]) => { - if (isNotNull(apiRoot.resource) && this.shouldSearchForPreview(previewList, searchString)) { - this.vorgangFacade.searchForPreview(searchString); - } - }), - map(([, previewList,]) => previewList), - startWith(createEmptyStateResource<VorgangListResource>(true))); - } - - private shouldSearchForPreview(previewList: StateResource<VorgangListResource>, searchString: string): boolean { - return previewList.reload && !previewList.loading && (searchString != EMPTY_STRING && searchString != undefined); - } - - public clearSearchPreviewList(): void { - this.vorgangFacade.clearSearchPreviewList(); - } - - public getSearchString(): Observable<string> { - return this.vorgangFacade.getSearchString(); - } - - public setSearchString(searchString: string): void { - this.vorgangFacade.setSearchString(searchString); - } - - public clearSearchString(): void { - this.vorgangFacade.clearSearchString(); - } - - public searchForPreview(searchString: string) { - this.vorgangFacade.searchForPreview(searchString); - } -} \ No newline at end of file + static readonly SEARCH_PREVIEW_LIST_LIMIT: number = 7; + + constructor( + private vorgangFacade: VorgangFacade, + private apiRootFacade: ApiRootFacade, + ) {} + + public getVorgangList(): Observable<StateResource<VorgangListResource>> { + return this.vorgangFacade.getVorgangList().pipe( + withLatestFrom( + this.apiRootFacade.getApiRoot(), + this.vorgangFacade.getVorgangFilter(), + this.vorgangFacade.getVorgangView(), + this.vorgangFacade.getSearchString(), + ), + tap(([vorgangList, apiRoot, vorgangFilter, vorgangView, searchString]) => { + doIfLoadingRequired(vorgangList, () => + this.loadVorgangList(apiRoot.resource, vorgangFilter, vorgangView, searchString), + ); + }), + map(([vorgangList]) => vorgangList), + startWith(createEmptyStateResource<VorgangListResource>(true)), + ); + } + + loadVorgangList( + apiRoot: ApiRootResource, + vorgangFilter: VorgangFilter, + vorgangView: VorgangView, + searchString: string, + ): void { + if (vorgangView === VorgangView.SEARCH) { + this.vorgangFacade.searchVorgaengeBy(apiRoot, searchString, getSearchLinkRel(vorgangFilter)); + } else { + this.vorgangFacade.loadVorgangList(apiRoot, buildLinkRel(vorgangFilter, vorgangView)); + } + } + + public loadNextPage(): void { + this.vorgangFacade.loadNextPage(); + } + + public getVorgaenge(): Observable<VorgangResource[]> { + return this.vorgangFacade.getVorgaenge(); + } + + public getVorgangStatistic(): Observable<StateResource<VorgangStatistic>> { + return this.vorgangFacade.getVorgangStatistic(); + } + + public getSelectedFilterAsRouteParam(): Observable<string> { + return this.vorgangFacade + .getVorgangFilter() + .pipe(map((vorgangFilter: VorgangFilter) => ROUTE_PARAM_BY_VORGANG_FILTER[vorgangFilter])); + } + + public isVorgangViewSelected(vorgangView: VorgangView): Observable<boolean> { + return this.vorgangFacade.isVorgangViewSelected(vorgangView); + } + + public getVorgangViewRoutePath(vorgangView: VorgangView): Observable<string> { + return this.vorgangFacade.getVorgangViewRoutePath(vorgangView); + } + + public getSearchPreviewList(): Observable<StateResource<VorgangListResource>> { + return combineLatest([ + this.apiRootFacade.getApiRoot(), + this.vorgangFacade.getSearchPreviewList(), + this.vorgangFacade.getSearchString(), + ]).pipe( + tap(([apiRoot, previewList, searchString]) => { + if (isNotNull(apiRoot.resource) && this.shouldSearchForPreview(previewList, searchString)) { + this.vorgangFacade.searchForPreview(searchString); + } + }), + map(([, previewList]) => previewList), + startWith(createEmptyStateResource<VorgangListResource>(true)), + ); + } + + private shouldSearchForPreview( + previewList: StateResource<VorgangListResource>, + searchString: string, + ): boolean { + return ( + previewList.reload && + !previewList.loading && + searchString != EMPTY_STRING && + searchString != undefined + ); + } + + public clearSearchPreviewList(): void { + this.vorgangFacade.clearSearchPreviewList(); + } + + public getSearchString(): Observable<string> { + return this.vorgangFacade.getSearchString(); + } + + public setSearchString(searchString: string): void { + this.vorgangFacade.setSearchString(searchString); + } + + public clearSearchString(): void { + this.vorgangFacade.clearSearchString(); + } + + public searchForPreview(searchString: string) { + this.vorgangFacade.searchForPreview(searchString); + } +} diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.spec.ts index 817ff0f099197a6ae96568584100e2bff2d4ac1e..d2bce3b55be83c1af73b2a0ff41ac449d799a48b 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.spec.ts @@ -28,7 +28,21 @@ import { RouteData } from '@alfa-client/navigation-shared'; import { EMPTY_STRING } from '@alfa-client/tech-shared'; import { createRouteData } from 'libs/navigation-shared/test/navigation-test-factory'; import { initialState, VorgangState } from './+state/vorgang.reducer'; -import { ALLE_ROUTE_PARAM, buildLinkRel, buildLinkRelFromPathSegments, buildPathSegmentsFromLocalStorage, buildVorgangFilterViewRoutePath, buildVorgangListRouteWithVorgangFilter, getSearchLinkRel, getSearchString, getVorgangFilter, isVorgangPage, ROUTE_PARAM_BY_VORGANG_FILTER, ROUTE_PARAM_BY_VORGANG_VIEW, SEARCH_ROUTE_PARAM } from './vorgang-navigation.util'; +import { + ALLE_ROUTE_PARAM, + buildLinkRel, + buildLinkRelFromPathSegments, + buildPathSegmentsFromLocalStorage, + buildVorgangFilterViewRoutePath, + buildVorgangListRouteWithVorgangFilter, + getSearchLinkRel, + getSearchString, + getVorgangFilter, + isVorgangPage, + ROUTE_PARAM_BY_VORGANG_FILTER, + ROUTE_PARAM_BY_VORGANG_VIEW, + SEARCH_ROUTE_PARAM, +} from './vorgang-navigation.util'; import { VorgangFilter, VorgangView } from './vorgang.model'; import * as Storage from '@alfa-client/app-shared'; @@ -37,450 +51,489 @@ import * as VorgangNavigationUtil from './vorgang-navigation.util'; jest.mock('@alfa-client/app-shared', () => mockAsEsModule('@alfa-client/app-shared')); function mockAsEsModule(module: string) { - return { - __esModule: true, - ...jest.requireActual(module) - }; + return { + __esModule: true, + ...jest.requireActual(module), + }; } describe('Vorgang Navigation Util', () => { + afterEach(() => { + jest.restoreAllMocks(); + }); - afterEach(() => { - jest.restoreAllMocks(); - }); + describe('getSearchString', () => { + it('should return searchString', () => { + const searchString: string = 'searchThisForMe'; - describe('getSearchString', () => { + const result = getSearchString(buildCurrentRouteData(searchString)); - it('should return searchString', () => { - const searchString: string = 'searchThisForMe'; + expect(result).toBe(searchString); + }); - const result = getSearchString(buildCurrentRouteData(searchString)); + it('should return decoded searchString', () => { + const searchString: string = 'search This For Me'; - expect(result).toBe(searchString); - }) + const result = getSearchString(buildCurrentRouteData(encodeURIComponent(searchString))); - it('should return decoded searchString', () => { - const searchString: string = 'search This For Me'; + expect(result).toBe(searchString); + }); - const result = getSearchString(buildCurrentRouteData(encodeURIComponent(searchString))); + it('should return empty string', () => { + const searchString: string = EMPTY_STRING; - expect(result).toBe(searchString); - }) + const result = getSearchString(buildCurrentRouteData(searchString)); - it('should return empty string', () => { - const searchString: string = EMPTY_STRING; + expect(result).toBe(EMPTY_STRING); + }); - const result = getSearchString(buildCurrentRouteData(searchString)); + function buildCurrentRouteData(searchString: string): RouteData { + const urlSegments: UrlSegment[] = [ + <any>{ path: ALLE_ROUTE_PARAM }, + <any>{ path: SEARCH_ROUTE_PARAM }, + <any>{ path: searchString }, + ]; + const queryParameter = { [SEARCH_ROUTE_PARAM]: searchString }; + return { ...createRouteData(), urlSegments, queryParameter }; + } + }); - expect(result).toBe(EMPTY_STRING); - }) + describe('getSearchLinkRel', () => { + it('should return linkrel for my', () => { + const linkRel: string = getSearchLinkRel(VorgangFilter.MEINE_VORGAENGE); - function buildCurrentRouteData(searchString: string): RouteData { - const urlSegments: UrlSegment[] = [<any>{ path: ALLE_ROUTE_PARAM}, <any>{ path: SEARCH_ROUTE_PARAM}, <any>{ path: searchString }]; - const queryParameter = { [SEARCH_ROUTE_PARAM]: searchString }; - return { ...createRouteData(), urlSegments, queryParameter }; - } - }) + expect(linkRel).toBe(ApiRootLinkRel.SEARCH_MEINE); + }); - describe('getSearchLinkRel', () => { + it('should return linkrel for all', () => { + const linkRel: string = getSearchLinkRel(VorgangFilter.ALLE); - it('should return linkrel for my', () => { - const linkRel: string = getSearchLinkRel(VorgangFilter.MEINE_VORGAENGE); + expect(linkRel).toBe(ApiRootLinkRel.SEARCH_ALLE); + }); - expect(linkRel).toBe(ApiRootLinkRel.SEARCH_MEINE); - }) + it('should return linkrel for unassigned', () => { + const linkRel: string = getSearchLinkRel(VorgangFilter.NICHT_ZUGEWIESEN); - it('should return linkrel for all', () => { - const linkRel: string = getSearchLinkRel(VorgangFilter.ALLE); + expect(linkRel).toBe(ApiRootLinkRel.SEARCH_UNASSIGNED); + }); + }); - expect(linkRel).toBe(ApiRootLinkRel.SEARCH_ALLE); - }) + describe('getVorgangFilter', () => { + it('should return undefined if not uebersichtsSeite', () => { + jest.spyOn(VorgangNavigationUtil, 'isUebersichtsSeite').mockReturnValue(false); + const vorgangFilter: VorgangFilter = getVorgangFilter(createRouteData()); - it('should return linkrel for unassigned', () => { - const linkRel: string = getSearchLinkRel(VorgangFilter.NICHT_ZUGEWIESEN); + expect(vorgangFilter).toBeUndefined(); + }); - expect(linkRel).toBe(ApiRootLinkRel.SEARCH_UNASSIGNED); - }) - }) + it('should return value on uebersichtsSeite', () => { + jest.spyOn(VorgangNavigationUtil, 'isUebersichtsSeite').mockReturnValue(true); - describe('getVorgangFilter', () => { + const vorgangFilter: VorgangFilter = getVorgangFilter( + buildWithRouteParam(VorgangFilter.ALLE), + ); - it('should return undefined if not uebersichtsSeite', () => { - jest.spyOn(VorgangNavigationUtil, 'isUebersichtsSeite').mockReturnValue(false); + expect(vorgangFilter).toBe(VorgangFilter.ALLE); + }); + }); - const vorgangFilter: VorgangFilter = getVorgangFilter(createRouteData()); + describe('isViewSelected', () => { + it('should call getVorgangView', () => { + const utilSpy = jest.spyOn(VorgangNavigationUtil, 'getVorgangView'); + const routeData: RouteData = createRouteData(); - expect(vorgangFilter).toBeUndefined(); - }) + VorgangNavigationUtil.isViewSelected(routeData, VorgangView.NEU); - it('should return value on uebersichtsSeite', () => { - jest.spyOn(VorgangNavigationUtil, 'isUebersichtsSeite').mockReturnValue(true); + expect(utilSpy).toHaveBeenCalledWith(routeData); + }); - const vorgangFilter: VorgangFilter = getVorgangFilter(buildWithRouteParam(VorgangFilter.ALLE)); + it('should return true on matching vorgangView', () => { + const vorgangView: VorgangView = VorgangView.ANGENOMMEN; + jest.spyOn(VorgangNavigationUtil, 'getVorgangView').mockReturnValue(vorgangView); - expect(vorgangFilter).toBe(VorgangFilter.ALLE); - }) - }) + const isSelected: boolean = VorgangNavigationUtil.isViewSelected( + createRouteData(), + vorgangView, + ); - describe('isViewSelected', () => { + expect(isSelected).toBeTruthy(); + }); - it('should call getVorgangView', () => { - const utilSpy = jest.spyOn(VorgangNavigationUtil, 'getVorgangView'); - const routeData: RouteData = createRouteData(); + it('should return false on NON matching VorgangView', () => { + const vorgangView: VorgangView = VorgangView.ANGENOMMEN; + jest.spyOn(VorgangNavigationUtil, 'getVorgangView').mockReturnValue(VorgangView.NEU); - VorgangNavigationUtil.isViewSelected(routeData, VorgangView.NEU); + const isSelected: boolean = VorgangNavigationUtil.isViewSelected( + createRouteData(), + vorgangView, + ); - expect(utilSpy).toHaveBeenCalledWith(routeData); - }) + expect(isSelected).toBeFalsy(); + }); + }); - it('should return true on matching vorgangView', () => { - const vorgangView: VorgangView = VorgangView.ANGENOMMEN; - jest.spyOn(VorgangNavigationUtil, 'getVorgangView').mockReturnValue(vorgangView); + describe('getVorgangView', () => { + it('should call getRouteUrlSegment', () => { + const utilSpy = jest.spyOn(VorgangNavigationUtil, 'getRouteUrlSegment'); + const routeData: RouteData = createRouteData(); - const isSelected: boolean = VorgangNavigationUtil.isViewSelected(createRouteData(), vorgangView); + VorgangNavigationUtil.getVorgangView(routeData); - expect(isSelected).toBeTruthy(); - }) + expect(utilSpy).toHaveBeenCalledWith(routeData, 1); + }); - it('should return false on NON matching VorgangView', () => { - const vorgangView: VorgangView = VorgangView.ANGENOMMEN; - jest.spyOn(VorgangNavigationUtil, 'getVorgangView').mockReturnValue(VorgangView.NEU); + it('should call isUebersichtsSeite', () => { + const utilSpy = jest.spyOn(VorgangNavigationUtil, 'isUebersichtsSeite'); + const routeData: RouteData = createRouteData(); - const isSelected: boolean = VorgangNavigationUtil.isViewSelected(createRouteData(), vorgangView); + VorgangNavigationUtil.getVorgangView(routeData); - expect(isSelected).toBeFalsy(); - }) - }) + expect(utilSpy).toHaveBeenCalledWith(routeData); + }); - describe('getVorgangView', () => { + it('should return VorgangView.VORGANG_LIST if routeData has no view', () => { + const urlSegments = [<any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] }]; + const routeData: RouteData = { ...createRouteData(), urlSegments }; - it('should call getRouteUrlSegment', () => { - const utilSpy = jest.spyOn(VorgangNavigationUtil, 'getRouteUrlSegment'); - const routeData: RouteData = createRouteData(); + const vorgangView: VorgangView = VorgangNavigationUtil.getVorgangView(routeData); - VorgangNavigationUtil.getVorgangView(routeData); + expect(vorgangView).toBe(6); + }); - expect(utilSpy).toHaveBeenCalledWith(routeData, 1); - }) + it('should return VorgangView.NEU if routeData contains this view', () => { + const urlSegments = [ + <any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] }, + <any>{ path: VorgangNavigationUtil.NEU_ROUTE_PARAM }, + ]; + const routeData: RouteData = { ...createRouteData(), urlSegments }; - it('should call isUebersichtsSeite', () => { - const utilSpy = jest.spyOn(VorgangNavigationUtil, 'isUebersichtsSeite'); - const routeData: RouteData = createRouteData(); + const vorgangView: VorgangView = VorgangNavigationUtil.getVorgangView(routeData); - VorgangNavigationUtil.getVorgangView(routeData); + expect(vorgangView).toBe(0); + }); + }); - expect(utilSpy).toHaveBeenCalledWith(routeData); - }) + describe('isUebersichtsSeite', () => { + it('should return true on Alle VorgangFilter', () => { + const routeData: RouteData = buildWithRouteParam(VorgangFilter.ALLE); - it('should return VorgangView.VORGANG_LIST if routeData has no view', () => { - const urlSegments = [<any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] }]; - const routeData: RouteData ={ ...createRouteData(), urlSegments }; + const isUebersichtsSeite: boolean = VorgangNavigationUtil.isUebersichtsSeite(routeData); - const vorgangView: VorgangView = VorgangNavigationUtil.getVorgangView(routeData); + expect(isUebersichtsSeite).toBeTruthy(); + }); - expect(vorgangView).toBe(6); - }) + it('should return true on Meine Vorgänge VorgangFilter', () => { + const routeData: RouteData = buildWithRouteParam(VorgangFilter.MEINE_VORGAENGE); - it('should return VorgangView.NEU if routeData contains this view', () => { - const urlSegments = [ - <any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] }, - <any>{ path: VorgangNavigationUtil.NEU_ROUTE_PARAM } - ]; - const routeData: RouteData ={ ...createRouteData(), urlSegments }; + const isUebersichtsSeite: boolean = VorgangNavigationUtil.isUebersichtsSeite(routeData); - const vorgangView: VorgangView = VorgangNavigationUtil.getVorgangView(routeData); + expect(isUebersichtsSeite).toBeTruthy(); + }); - expect(vorgangView).toBe(0); - }) - }) + it('should return true on Nicht zugewiesen VorgangFilter', () => { + const routeData: RouteData = buildWithRouteParam(VorgangFilter.NICHT_ZUGEWIESEN); - describe('isUebersichtsSeite', () => { + const isUebersichtsSeite: boolean = VorgangNavigationUtil.isUebersichtsSeite(routeData); - it('should return true on Alle VorgangFilter', () => { - const routeData: RouteData = buildWithRouteParam(VorgangFilter.ALLE); + expect(isUebersichtsSeite).toBeTruthy(); + }); - const isUebersichtsSeite: boolean = VorgangNavigationUtil.isUebersichtsSeite(routeData); + it('should return false on other "vorgang" routeParam', () => { + const urlSegments: UrlSegment[] = [<any>{ path: 'vorgang' }]; + const routeData: RouteData = { ...createRouteData(), urlSegments }; - expect(isUebersichtsSeite).toBeTruthy(); - }) + const isUebersichtsSeite: boolean = VorgangNavigationUtil.isUebersichtsSeite(routeData); - it('should return true on Meine Vorgänge VorgangFilter', () => { - const routeData: RouteData = buildWithRouteParam(VorgangFilter.MEINE_VORGAENGE); + expect(isUebersichtsSeite).toBeFalsy(); + }); + }); - const isUebersichtsSeite: boolean = VorgangNavigationUtil.isUebersichtsSeite(routeData); + describe('buildBackButtonUrl', () => { + describe('by state if differs from localStorage', () => { + it('should call buildPathSegmentsFromLocalStorage', () => { + jest.spyOn(VorgangNavigationUtil, 'isStateEqualLocalStorage').mockReturnValue(false); + const utilSpy = jest.spyOn(VorgangNavigationUtil, 'buildPathSegmentsFromLocalStorage'); - expect(isUebersichtsSeite).toBeTruthy(); - }) + VorgangNavigationUtil.buildBackButtonUrl(initialState); - it('should return true on Nicht zugewiesen VorgangFilter', () => { - const routeData: RouteData = buildWithRouteParam(VorgangFilter.NICHT_ZUGEWIESEN); + expect(utilSpy).toHaveBeenCalled(); + }); - const isUebersichtsSeite: boolean = VorgangNavigationUtil.isUebersichtsSeite(routeData); + it('should build by given filter and view', () => { + jest + .spyOn(Storage, 'getViewFromLocalStorage') + .mockReturnValue(ROUTE_PARAM_BY_VORGANG_VIEW[VorgangView.ANGENOMMEN]); + jest + .spyOn(Storage, 'getFilterFromLocalStorage') + .mockReturnValue(ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.MEINE_VORGAENGE]); - expect(isUebersichtsSeite).toBeTruthy(); - }) + const url: string = VorgangNavigationUtil.buildBackButtonUrl(initialState); - it('should return false on other "vorgang" routeParam', () => { - const urlSegments: UrlSegment[] = [<any>{ path: 'vorgang' }]; - const routeData: RouteData ={ ...createRouteData(), urlSegments }; + expect(url).toBe(`/meine/angenommen`); + }); - const isUebersichtsSeite: boolean = VorgangNavigationUtil.isUebersichtsSeite(routeData); + it('should build by given filter only', () => { + jest.spyOn(Storage, 'getViewFromLocalStorage').mockReturnValue(EMPTY_STRING); + jest + .spyOn(Storage, 'getFilterFromLocalStorage') + .mockReturnValue(ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.MEINE_VORGAENGE]); - expect(isUebersichtsSeite).toBeFalsy(); - }) - }) + const url: string = VorgangNavigationUtil.buildBackButtonUrl(initialState); - describe('buildBackButtonUrl', () => { + expect(url).toBe(`/meine`); + }); + }); - describe('by state if differs from localStorage', () => { + describe('by state if equals localStorage', () => { + it('should call buildVorgangListRouteWithVorgangFilter', () => { + jest.spyOn(VorgangNavigationUtil, 'isStateEqualLocalStorage').mockReturnValue(true); + const utilSpy = jest.spyOn(VorgangNavigationUtil, 'buildVorgangListRouteWithVorgangFilter'); - it('should call buildPathSegmentsFromLocalStorage', () => { - jest.spyOn(VorgangNavigationUtil, 'isStateEqualLocalStorage').mockReturnValue(false); - const utilSpy = jest.spyOn(VorgangNavigationUtil, 'buildPathSegmentsFromLocalStorage'); + VorgangNavigationUtil.buildBackButtonUrl(initialState); - VorgangNavigationUtil.buildBackButtonUrl(initialState); + expect(utilSpy).toHaveBeenCalledWith(initialState, initialState.vorgangFilter); + }); - expect(utilSpy).toHaveBeenCalled(); - }) + it('should build by given filter', () => { + jest.spyOn(Storage, 'getViewFromLocalStorage').mockReturnValue(EMPTY_STRING); + jest.spyOn(Storage, 'getFilterFromLocalStorage').mockReturnValue('alle'); - it('should build by given filter and view', () => { - jest.spyOn(Storage, 'getViewFromLocalStorage').mockReturnValue(ROUTE_PARAM_BY_VORGANG_VIEW[VorgangView.ANGENOMMEN]); - jest.spyOn(Storage, 'getFilterFromLocalStorage').mockReturnValue(ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.MEINE_VORGAENGE]); + const url: string = VorgangNavigationUtil.buildBackButtonUrl(initialState); - const url: string = VorgangNavigationUtil.buildBackButtonUrl(initialState); + expect(url).toBe('/alle'); + }); - expect(url).toBe(`/meine/angenommen`); - }) + it('should build by given filter and view', () => { + jest.spyOn(Storage, 'getViewFromLocalStorage').mockReturnValue('angenommen'); + jest.spyOn(Storage, 'getFilterFromLocalStorage').mockReturnValue('meine'); - it('should build by given filter only', () => { - jest.spyOn(Storage, 'getViewFromLocalStorage').mockReturnValue(EMPTY_STRING); - jest.spyOn(Storage, 'getFilterFromLocalStorage').mockReturnValue(ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.MEINE_VORGAENGE]); + const url: string = VorgangNavigationUtil.buildBackButtonUrl({ + ...initialState, + vorgangFilter: VorgangFilter.MEINE_VORGAENGE, + vorgangView: VorgangView.ANGENOMMEN, + }); - const url: string = VorgangNavigationUtil.buildBackButtonUrl(initialState); + expect(url).toBe('/meine/angenommen'); + }); + }); + }); - expect(url).toBe(`/meine`); - }) - }) + describe('buildVorgangListRoutePathWithFilter', () => { + it('should call "buildVorgangListRouteWithVorgangFilter"', () => { + const utilSpy = jest.spyOn(VorgangNavigationUtil, 'buildVorgangListRouteWithVorgangFilter'); + const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + + VorgangNavigationUtil.buildVorgangListRoutePathWithFilter(initialState, vorgangFilter); - describe('by state if equals localStorage', () => { + expect(utilSpy).toHaveBeenCalledWith(initialState, vorgangFilter); + }); + }); + + describe('buildVorgangListRouteWithVorgangFilter', () => { + it('should build by alle filter and vorgangList view', () => { + const state: VorgangState = { ...initialState, vorgangView: VorgangView.VORGANG_LIST }; + const routePath: string = buildVorgangListRouteWithVorgangFilter(state, VorgangFilter.ALLE); + + expect(routePath).toEqual('/alle'); + }); + + it('should build by meine vorgänge filter and view', () => { + const state: VorgangState = { ...initialState, vorgangView: VorgangView.NEU }; + const routePath: string = buildVorgangListRouteWithVorgangFilter( + state, + VorgangFilter.MEINE_VORGAENGE, + ); - it('should call buildVorgangListRouteWithVorgangFilter', () => { - jest.spyOn(VorgangNavigationUtil, 'isStateEqualLocalStorage').mockReturnValue(true); - const utilSpy = jest.spyOn(VorgangNavigationUtil, 'buildVorgangListRouteWithVorgangFilter'); + expect(routePath).toEqual('/meine/neu'); + }); - VorgangNavigationUtil.buildBackButtonUrl(initialState); + it('should build by filter search view and existing searchString', () => { + const state: VorgangState = { + ...initialState, + vorgangView: VorgangView.SEARCH, + searchString: 'testSearchString', + }; + const routePath: string = buildVorgangListRouteWithVorgangFilter( + state, + VorgangFilter.MEINE_VORGAENGE, + ); + + expect(routePath).toEqual('/meine/search/testSearchString'); + }); + + it('should build by filter other view than search and existing searchString', () => { + const state: VorgangState = { + ...initialState, + vorgangView: VorgangView.ANGENOMMEN, + searchString: 'testSearchString', + }; + const routePath: string = buildVorgangListRouteWithVorgangFilter( + state, + VorgangFilter.MEINE_VORGAENGE, + ); + + expect(routePath).toEqual('/meine/angenommen'); + }); + }); + + describe('buildLinkRel', () => { + describe('on non vorgangList View', () => { + it('return linkRel for Alle Filter', () => { + const linkRel: string = buildLinkRel(VorgangFilter.ALLE, VorgangView.NEU); + + expect(linkRel).toBe('vorgaenge_neu_all'); + }); - expect(utilSpy).toHaveBeenCalledWith(initialState, initialState.vorgangFilter); - }) + it('return linkRel for Meine Vorgänge Filter', () => { + const linkRel: string = buildLinkRel(VorgangFilter.MEINE_VORGAENGE, VorgangView.NEU); - it('should build by given filter', () => { - jest.spyOn(Storage, 'getViewFromLocalStorage').mockReturnValue(EMPTY_STRING); - jest.spyOn(Storage, 'getFilterFromLocalStorage').mockReturnValue('alle'); + expect(linkRel).toBe('vorgaenge_neu_my'); + }); + + it('return linkRel for Nicht zugewiesen Filter', () => { + const linkRel: string = buildLinkRel(VorgangFilter.NICHT_ZUGEWIESEN, VorgangView.NEU); + + expect(linkRel).toBe('vorgaenge_neu_unassigned'); + }); + }); - const url: string = VorgangNavigationUtil.buildBackButtonUrl(initialState); + describe('on vorgangList View', () => { + it('return linkRel for Alle Filter', () => { + const linkRel: string = buildLinkRel(VorgangFilter.ALLE, VorgangView.VORGANG_LIST); + + expect(linkRel).toBe('vorgaenge_all'); + }); + + it('return linkRel for Meine Vorgänge Filter', () => { + const linkRel: string = buildLinkRel( + VorgangFilter.MEINE_VORGAENGE, + VorgangView.VORGANG_LIST, + ); - expect(url).toBe('/alle'); - }) + expect(linkRel).toBe('vorgaenge_my'); + }); - it('should build by given filter and view', () => { - jest.spyOn(Storage, 'getViewFromLocalStorage').mockReturnValue('angenommen'); - jest.spyOn(Storage, 'getFilterFromLocalStorage').mockReturnValue('meine'); + it('return linkRel for Nicht Zugewiesen Filter', () => { + const linkRel: string = buildLinkRel( + VorgangFilter.NICHT_ZUGEWIESEN, + VorgangView.VORGANG_LIST, + ); - const url: string = VorgangNavigationUtil.buildBackButtonUrl({ ...initialState, vorgangFilter: VorgangFilter.MEINE_VORGAENGE, vorgangView: VorgangView.ANGENOMMEN }); + expect(linkRel).toBe('vorgaenge_unassigned'); + }); + }); + }); - expect(url).toBe('/meine/angenommen'); - }) + describe('buildLinkRelFromPathSegments', () => { + it('should return linkRel with view', () => { + const pathSegments: string[] = ['meine', 'neu']; - }) - }) + const linkRel: string = buildLinkRelFromPathSegments(pathSegments); + + expect(linkRel).toBe('vorgaenge_neu_my'); + }); + + it('should return linkRel without view', () => { + const pathSegments: string[] = ['meine']; + + const linkRel: string = buildLinkRelFromPathSegments(pathSegments); + + expect(linkRel).toBe('vorgaenge_my'); + }); + + it('should return search linkRel', () => { + const pathSegments: string[] = ['meine', 'search']; + + const linkRel: string = buildLinkRelFromPathSegments(pathSegments); + + expect(linkRel).toBe('search_my'); + }); + }); + + describe('buildVorgangFilterViewRoutePath', () => { + const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + const vorgangView: VorgangView = VorgangView.NEU; - describe('buildVorgangListRoutePathWithFilter', () => { + it('should return routePath of view and filter', () => { + const routePath: string = buildVorgangFilterViewRoutePath( + vorgangFilter, + vorgangView, + EMPTY_STRING, + ); - it('should call "buildVorgangListRouteWithVorgangFilter"', () => { - const utilSpy = jest.spyOn(VorgangNavigationUtil, 'buildVorgangListRouteWithVorgangFilter'); - const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; + expect(routePath).toBe('/alle/neu'); + }); - VorgangNavigationUtil.buildVorgangListRoutePathWithFilter(initialState, vorgangFilter); + it('should return routePath of view and filter and searchString', () => { + const routePath: string = buildVorgangFilterViewRoutePath( + vorgangFilter, + vorgangView, + 'searchString', + ); - expect(utilSpy).toHaveBeenCalledWith(initialState, vorgangFilter); - }) - }) + expect(routePath).toBe('/alle/neu/searchString'); + }); + }); - describe('buildVorgangListRouteWithVorgangFilter', () => { + describe('buildPathSegmentsFromLocalStorage', () => { + it('should build on existing filter only', () => { + const storageSpy = jest.spyOn(Storage, 'getFilterFromLocalStorage'); + storageSpy.mockReturnValue('meine'); - it('should build by alle filter and vorgangList view', () => { - const state: VorgangState = { ...initialState, vorgangView: VorgangView.VORGANG_LIST }; - const routePath: string = buildVorgangListRouteWithVorgangFilter(state, VorgangFilter.ALLE); + jest.spyOn(Storage, 'getViewFromLocalStorage').mockReturnValue(EMPTY_STRING); - expect(routePath).toEqual('/alle'); - }) + const pathSegments: string[] = buildPathSegmentsFromLocalStorage(); - it('should build by meine vorgänge filter and view', () => { - const state: VorgangState = { ...initialState, vorgangView: VorgangView.NEU }; - const routePath: string = buildVorgangListRouteWithVorgangFilter(state, VorgangFilter.MEINE_VORGAENGE); + expect(pathSegments[0]).toBe('meine'); + }); - expect(routePath).toEqual('/meine/neu'); - }) + it('should build on existing filter and view', () => { + const filterSpy = jest.spyOn(Storage, 'getFilterFromLocalStorage'); + filterSpy.mockReturnValue('meine'); - it('should build by filter search view and existing searchString', () => { - const state: VorgangState = { ...initialState, vorgangView: VorgangView.SEARCH, searchString: 'testSearchString' }; - const routePath: string = buildVorgangListRouteWithVorgangFilter(state, VorgangFilter.MEINE_VORGAENGE); + const viewSpy = jest.spyOn(Storage, 'getViewFromLocalStorage'); + viewSpy.mockReturnValue('neu'); - expect(routePath).toEqual('/meine/search/testSearchString'); - }) + const pathSegments: string[] = buildPathSegmentsFromLocalStorage(); - it('should build by filter other view than search and existing searchString', () => { - const state: VorgangState = { ...initialState, vorgangView: VorgangView.ANGENOMMEN, searchString: 'testSearchString' }; - const routePath: string = buildVorgangListRouteWithVorgangFilter(state, VorgangFilter.MEINE_VORGAENGE); + expect(pathSegments[0]).toBe('meine'); + expect(pathSegments[1]).toBe('neu'); + }); - expect(routePath).toEqual('/meine/angenommen'); - }) - }) + it('should build on missing filter and view', () => { + const filterSpy = jest.spyOn(Storage, 'getFilterFromLocalStorage'); + filterSpy.mockReturnValue(EMPTY_STRING); - describe('buildLinkRel', () => { + const viewSpy = jest.spyOn(Storage, 'getViewFromLocalStorage'); + viewSpy.mockReturnValue(EMPTY_STRING); - describe('on non vorgangList View', () => { + const pathSegments: string[] = buildPathSegmentsFromLocalStorage(); - it('return linkRel for Alle Filter', () => { - const linkRel: string = buildLinkRel(VorgangFilter.ALLE, VorgangView.NEU); + expect(pathSegments[0]).toBe('alle'); + }); + }); - expect(linkRel).toBe('vorgaenge_neu_all'); - }) + function buildWithRouteParam(vorgangFilter: VorgangFilter): RouteData { + const urlSegments: UrlSegment[] = [<any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[vorgangFilter] }]; + return { ...createRouteData(), urlSegments }; + } - it('return linkRel for Meine Vorgänge Filter', () => { - const linkRel: string = buildLinkRel(VorgangFilter.MEINE_VORGAENGE, VorgangView.NEU); + describe('isVorgangPage', () => { + it('should return true on matching param and segment length', () => { + const is: boolean = isVorgangPage(buildVorgangPageRouteData()); - expect(linkRel).toBe('vorgaenge_neu_my'); - }) + expect(is).toBeTruthy(); + }); - it('return linkRel for Nicht zugewiesen Filter', () => { - const linkRel: string = buildLinkRel(VorgangFilter.NICHT_ZUGEWIESEN, VorgangView.NEU); - - expect(linkRel).toBe('vorgaenge_neu_unassigned'); - }) - }) - - describe('on vorgangList View', () => { - - it('return linkRel for Alle Filter', () => { - const linkRel: string = buildLinkRel(VorgangFilter.ALLE, VorgangView.VORGANG_LIST); - - expect(linkRel).toBe('vorgaenge_all'); - }) - - it('return linkRel for Meine Vorgänge Filter', () => { - const linkRel: string = buildLinkRel(VorgangFilter.MEINE_VORGAENGE, VorgangView.VORGANG_LIST); - - expect(linkRel).toBe('vorgaenge_my'); - }) - - it('return linkRel for Nicht Zugewiesen Filter', () => { - const linkRel: string = buildLinkRel(VorgangFilter.NICHT_ZUGEWIESEN, VorgangView.VORGANG_LIST); - - expect(linkRel).toBe('vorgaenge_unassigned'); - }) - }) - }) - - describe('buildLinkRelFromPathSegments', () => { - it('should return linkRel with view', () => { - const pathSegments: string[] = ['meine', 'neu']; - - const linkRel: string = buildLinkRelFromPathSegments(pathSegments); - - expect(linkRel).toBe('vorgaenge_neu_my'); - }) - - it('should return linkRel without view', () => { - const pathSegments: string[] = ['meine']; - - const linkRel: string = buildLinkRelFromPathSegments(pathSegments); - - expect(linkRel).toBe('vorgaenge_my'); - }) - - it('should return search linkRel', () => { - const pathSegments: string[] = ['meine', 'search']; - - const linkRel: string = buildLinkRelFromPathSegments(pathSegments); - - expect(linkRel).toBe('search_my'); - }) - }) - - describe('buildVorgangFilterViewRoutePath', () => { - - const vorgangFilter: VorgangFilter = VorgangFilter.ALLE; - const vorgangView: VorgangView = VorgangView.NEU; - - it('should return routePath of view and filter', () => { - const routePath: string = buildVorgangFilterViewRoutePath(vorgangFilter, vorgangView, EMPTY_STRING); - - expect(routePath).toBe('/alle/neu'); - }) - - it('should return routePath of view and filter and searchString', () => { - const routePath: string = buildVorgangFilterViewRoutePath(vorgangFilter, vorgangView, 'searchString'); - - expect(routePath).toBe('/alle/neu/searchString'); - }) - }) - - describe('buildPathSegmentsFromLocalStorage', () => { - - it('should build on existing filter only', () => { - const storageSpy = jest.spyOn(Storage, 'getFilterFromLocalStorage'); - storageSpy.mockReturnValue('meine'); - - jest.spyOn(Storage, 'getViewFromLocalStorage').mockReturnValue(EMPTY_STRING); - - const pathSegments: string[] = buildPathSegmentsFromLocalStorage(); - - expect(pathSegments[0]).toBe('meine'); - }) - - it('should build on existing filter and view', () => { - const filterSpy = jest.spyOn(Storage, 'getFilterFromLocalStorage'); - filterSpy.mockReturnValue('meine'); - - const viewSpy = jest.spyOn(Storage, 'getViewFromLocalStorage'); - viewSpy.mockReturnValue('neu'); - - const pathSegments: string[] = buildPathSegmentsFromLocalStorage(); - - expect(pathSegments[0]).toBe('meine'); - expect(pathSegments[1]).toBe('neu'); - }) - - it('should build on missing filter and view', () => { - const filterSpy = jest.spyOn(Storage, 'getFilterFromLocalStorage'); - filterSpy.mockReturnValue(EMPTY_STRING); - - const viewSpy = jest.spyOn(Storage, 'getViewFromLocalStorage'); - viewSpy.mockReturnValue(EMPTY_STRING); - - const pathSegments: string[] = buildPathSegmentsFromLocalStorage(); - - expect(pathSegments[0]).toBe('alle'); - }) - }) - - function buildWithRouteParam(vorgangFilter: VorgangFilter): RouteData { - const urlSegments: UrlSegment[] = [<any>{ path: ROUTE_PARAM_BY_VORGANG_FILTER[vorgangFilter] }]; - return { ...createRouteData(), urlSegments }; - } - - describe('isVorgangPage', () => { - - it('should return true on matching param and segment length', () => { - const is: boolean = isVorgangPage(buildVorgangPageRouteData()); - - expect(is).toBeTruthy(); - }) - - function buildVorgangPageRouteData(): RouteData { - return { ...createRouteData(), urlSegments: [], queryParameter: { [VorgangNavigationUtil.VORGANG_WITH_EINGANG_ROUTE_PARAM]: faker.internet.url() } }; - } - }) -}) \ No newline at end of file + function buildVorgangPageRouteData(): RouteData { + return { + ...createRouteData(), + urlSegments: [], + queryParameter: { + [VorgangNavigationUtil.VORGANG_WITH_EINGANG_ROUTE_PARAM]: faker.internet.url(), + }, + }; + } + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts index 608d1d44fa6d71a13ff044403ec88332e4bfc58f..67f6e3da2c32b30e3fe1140a25047b97196b193e 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-navigation.util.ts @@ -41,179 +41,206 @@ export const IN_BEARBEITUNG_ROUTE_PARAM: string = 'in_bearbeitung'; export const BESCHIEDEN_ROUTE_PARAM: string = 'beschieden'; export const ABGESCHLOSSEN_ROUTE_PARAM: string = 'abgeschlossen'; export const VERWORFEN_ROUTE_PARAM: string = 'verworfen'; -export const WIEDERVORLAGEN_ROUTE_PARAM: string = 'wiedervorlagen' -export const ZU_LOESCHEN_ROUTE_PARAM: string = 'zu_loeschen' +export const WIEDERVORLAGEN_ROUTE_PARAM: string = 'wiedervorlagen'; +export const ZU_LOESCHEN_ROUTE_PARAM: string = 'zu_loeschen'; export const SEARCH_ROUTE_PARAM: string = 'search'; export const VORGANG_WITH_EINGANG_ROUTE_PARAM: string = 'vorgangWithEingangUrl'; export const ROUTE_PARAM_BY_VORGANG_VIEW: { [view: string]: string } = { - [VorgangView.NEU]: NEU_ROUTE_PARAM, - [VorgangView.ANGENOMMEN]: ANGENOMMEN_ROUTE_PARAM, - [VorgangView.IN_BEARBEITUNG]: IN_BEARBEITUNG_ROUTE_PARAM, - [VorgangView.BESCHIEDEN]: BESCHIEDEN_ROUTE_PARAM, - [VorgangView.ABGESCHLOSSEN]: ABGESCHLOSSEN_ROUTE_PARAM, - [VorgangView.VERWORFEN]: VERWORFEN_ROUTE_PARAM, - [VorgangView.VORGANG_LIST]: EMPTY_STRING, - [VorgangView.WIEDERVORLAGEN]: WIEDERVORLAGEN_ROUTE_PARAM, - [VorgangView.ZU_LOESCHEN]: ZU_LOESCHEN_ROUTE_PARAM, - [VorgangView.SEARCH]: SEARCH_ROUTE_PARAM -} + [VorgangView.NEU]: NEU_ROUTE_PARAM, + [VorgangView.ANGENOMMEN]: ANGENOMMEN_ROUTE_PARAM, + [VorgangView.IN_BEARBEITUNG]: IN_BEARBEITUNG_ROUTE_PARAM, + [VorgangView.BESCHIEDEN]: BESCHIEDEN_ROUTE_PARAM, + [VorgangView.ABGESCHLOSSEN]: ABGESCHLOSSEN_ROUTE_PARAM, + [VorgangView.VERWORFEN]: VERWORFEN_ROUTE_PARAM, + [VorgangView.VORGANG_LIST]: EMPTY_STRING, + [VorgangView.WIEDERVORLAGEN]: WIEDERVORLAGEN_ROUTE_PARAM, + [VorgangView.ZU_LOESCHEN]: ZU_LOESCHEN_ROUTE_PARAM, + [VorgangView.SEARCH]: SEARCH_ROUTE_PARAM, +}; export const VORGANG_VIEW_BY_ROUTE_PARAM: { [routeParam: string]: VorgangView } = { - [NEU_ROUTE_PARAM]: VorgangView.NEU, - [ANGENOMMEN_ROUTE_PARAM]: VorgangView.ANGENOMMEN, - [IN_BEARBEITUNG_ROUTE_PARAM]: VorgangView.IN_BEARBEITUNG, - [BESCHIEDEN_ROUTE_PARAM]: VorgangView.BESCHIEDEN, - [ABGESCHLOSSEN_ROUTE_PARAM]: VorgangView.ABGESCHLOSSEN, - [VERWORFEN_ROUTE_PARAM]: VorgangView.VERWORFEN, - [WIEDERVORLAGEN_ROUTE_PARAM]: VorgangView.WIEDERVORLAGEN, - [ZU_LOESCHEN_ROUTE_PARAM]: VorgangView.ZU_LOESCHEN, - [SEARCH_ROUTE_PARAM]: VorgangView.SEARCH -} + [NEU_ROUTE_PARAM]: VorgangView.NEU, + [ANGENOMMEN_ROUTE_PARAM]: VorgangView.ANGENOMMEN, + [IN_BEARBEITUNG_ROUTE_PARAM]: VorgangView.IN_BEARBEITUNG, + [BESCHIEDEN_ROUTE_PARAM]: VorgangView.BESCHIEDEN, + [ABGESCHLOSSEN_ROUTE_PARAM]: VorgangView.ABGESCHLOSSEN, + [VERWORFEN_ROUTE_PARAM]: VorgangView.VERWORFEN, + [WIEDERVORLAGEN_ROUTE_PARAM]: VorgangView.WIEDERVORLAGEN, + [ZU_LOESCHEN_ROUTE_PARAM]: VorgangView.ZU_LOESCHEN, + [SEARCH_ROUTE_PARAM]: VorgangView.SEARCH, +}; export const ROUTE_PARAM_BY_VORGANG_FILTER: { [filter: string]: string } = { - [VorgangFilter.ALLE]: ALLE_ROUTE_PARAM, - [VorgangFilter.MEINE_VORGAENGE]: MEINE_ROUTE_PARAM, - [VorgangFilter.NICHT_ZUGEWIESEN]: UNASSIGNED_ROUTE_PARAM -} + [VorgangFilter.ALLE]: ALLE_ROUTE_PARAM, + [VorgangFilter.MEINE_VORGAENGE]: MEINE_ROUTE_PARAM, + [VorgangFilter.NICHT_ZUGEWIESEN]: UNASSIGNED_ROUTE_PARAM, +}; export const VORGANG_FILTER_BY_ROUTE_PARAM: { [routeParam: string]: VorgangFilter } = { - [ALLE_ROUTE_PARAM]: VorgangFilter.ALLE, - [MEINE_ROUTE_PARAM]: VorgangFilter.MEINE_VORGAENGE, - [UNASSIGNED_ROUTE_PARAM]: VorgangFilter.NICHT_ZUGEWIESEN -} + [ALLE_ROUTE_PARAM]: VorgangFilter.ALLE, + [MEINE_ROUTE_PARAM]: VorgangFilter.MEINE_VORGAENGE, + [UNASSIGNED_ROUTE_PARAM]: VorgangFilter.NICHT_ZUGEWIESEN, +}; const SEARCH_LINK_BY_VORGANG_FILTER: { [filter: string]: string } = { - [VorgangFilter.MEINE_VORGAENGE]: ApiRootLinkRel.SEARCH_MEINE, - [VorgangFilter.ALLE]: ApiRootLinkRel.SEARCH_ALLE, - [VorgangFilter.NICHT_ZUGEWIESEN]: ApiRootLinkRel.SEARCH_UNASSIGNED -} + [VorgangFilter.MEINE_VORGAENGE]: ApiRootLinkRel.SEARCH_MEINE, + [VorgangFilter.ALLE]: ApiRootLinkRel.SEARCH_ALLE, + [VorgangFilter.NICHT_ZUGEWIESEN]: ApiRootLinkRel.SEARCH_UNASSIGNED, +}; export function getSearchString(routeData: RouteData): string { - const searchString: string = VorgangNavigationUtil.getRouteUrlSegment(routeData, 2); - return isUndefined(searchString) ? EMPTY_STRING : decodeURIComponent(searchString); + const searchString: string = VorgangNavigationUtil.getRouteUrlSegment(routeData, 2); + return isUndefined(searchString) ? EMPTY_STRING : decodeURIComponent(searchString); } export function getSearchLinkRel(vorgangFilter: VorgangFilter): string { - return SEARCH_LINK_BY_VORGANG_FILTER[vorgangFilter]; + return SEARCH_LINK_BY_VORGANG_FILTER[vorgangFilter]; } export function getVorgangFilter(routeData: RouteData): VorgangFilter { - return VorgangNavigationUtil.isUebersichtsSeite(routeData) ? VORGANG_FILTER_BY_ROUTE_PARAM[getRouteUrlSegment(routeData, 0)] : undefined; + return VorgangNavigationUtil.isUebersichtsSeite(routeData) ? + VORGANG_FILTER_BY_ROUTE_PARAM[getRouteUrlSegment(routeData, 0)] + : undefined; } export function isViewSelected(routeData: RouteData, vorgangView: VorgangView): boolean { - return VorgangNavigationUtil.getVorgangView(routeData) === vorgangView; + return VorgangNavigationUtil.getVorgangView(routeData) === vorgangView; } export function getVorgangView(routeData: RouteData): VorgangView { - const vorgangViewValue: string = VorgangNavigationUtil.getRouteUrlSegment(routeData, 1); - if (VorgangNavigationUtil.isUebersichtsSeite(routeData)) { - return isNotUndefined(vorgangViewValue) - ? VORGANG_VIEW_BY_ROUTE_PARAM[vorgangViewValue] - : VorgangView.VORGANG_LIST; - } - return undefined; + const vorgangViewValue: string = VorgangNavigationUtil.getRouteUrlSegment(routeData, 1); + if (VorgangNavigationUtil.isUebersichtsSeite(routeData)) { + return isNotUndefined(vorgangViewValue) ? + VORGANG_VIEW_BY_ROUTE_PARAM[vorgangViewValue] + : VorgangView.VORGANG_LIST; + } + return undefined; } export function isUebersichtsSeite(routeData: RouteData): boolean { - const filter: string = VorgangNavigationUtil.getRouteUrlSegment(routeData, 0); - return isNotUndefined(filter) && (filter === ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] || filter === ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.MEINE_VORGAENGE] || filter === ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.NICHT_ZUGEWIESEN]); + const filter: string = VorgangNavigationUtil.getRouteUrlSegment(routeData, 0); + return ( + isNotUndefined(filter) && + (filter === ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] || + filter === ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.MEINE_VORGAENGE] || + filter === ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.NICHT_ZUGEWIESEN]) + ); } export function getRouteUrlSegment(routeData: RouteData, num: number): string { - return routeData.urlSegments.length > num ? routeData.urlSegments[num].path.toString() : undefined; + return routeData.urlSegments.length > num ? + routeData.urlSegments[num].path.toString() + : undefined; } export function buildBackButtonUrl(state: VorgangState): string { - if (VorgangNavigationUtil.isStateEqualLocalStorage(state)) { - return VorgangNavigationUtil.buildVorgangListRouteWithVorgangFilter(state, state.vorgangFilter); - } + if (VorgangNavigationUtil.isStateEqualLocalStorage(state)) { + return VorgangNavigationUtil.buildVorgangListRouteWithVorgangFilter(state, state.vorgangFilter); + } - return '/' + VorgangNavigationUtil.buildPathSegmentsFromLocalStorage().join('/'); + return '/' + VorgangNavigationUtil.buildPathSegmentsFromLocalStorage().join('/'); } export function isStateEqualLocalStorage(state: VorgangState): boolean { - return getFilterFromLocalStorage() === ROUTE_PARAM_BY_VORGANG_FILTER[state.vorgangFilter] && getViewFromLocalStorage() === ROUTE_PARAM_BY_VORGANG_VIEW[state.vorgangView]; + return ( + getFilterFromLocalStorage() === ROUTE_PARAM_BY_VORGANG_FILTER[state.vorgangFilter] && + getViewFromLocalStorage() === ROUTE_PARAM_BY_VORGANG_VIEW[state.vorgangView] + ); } -export function buildVorgangListRoutePathWithFilter(state: VorgangState, filter: VorgangFilter): string { - return VorgangNavigationUtil.buildVorgangListRouteWithVorgangFilter(state, filter); +export function buildVorgangListRoutePathWithFilter( + state: VorgangState, + filter: VorgangFilter, +): string { + return VorgangNavigationUtil.buildVorgangListRouteWithVorgangFilter(state, filter); } -export function buildVorgangListRouteWithVorgangFilter(state: VorgangState, filter: VorgangFilter): string { - let route = '/' + ROUTE_PARAM_BY_VORGANG_FILTER[filter]; +export function buildVorgangListRouteWithVorgangFilter( + state: VorgangState, + filter: VorgangFilter, +): string { + let route = '/' + ROUTE_PARAM_BY_VORGANG_FILTER[filter]; - if(state.vorgangView !== VorgangView.VORGANG_LIST) { - route += '/' + ROUTE_PARAM_BY_VORGANG_VIEW[state.vorgangView]; - } - if(state.vorgangView === VorgangView.SEARCH && isNotEmpty(state.searchString)) { - route += '/' + encodeURIComponent(state.searchString); - } - return route; + if (state.vorgangView !== VorgangView.VORGANG_LIST) { + route += '/' + ROUTE_PARAM_BY_VORGANG_VIEW[state.vorgangView]; + } + if (state.vorgangView === VorgangView.SEARCH && isNotEmpty(state.searchString)) { + route += '/' + encodeURIComponent(state.searchString); + } + return route; } const VORGANG_LIST_LINK_REL_SUFFIX: { [filter: string]: string } = { - [VorgangFilter.MEINE_VORGAENGE]: 'my', - [VorgangFilter.ALLE]: 'all', - [VorgangFilter.NICHT_ZUGEWIESEN]: 'unassigned' -} + [VorgangFilter.MEINE_VORGAENGE]: 'my', + [VorgangFilter.ALLE]: 'all', + [VorgangFilter.NICHT_ZUGEWIESEN]: 'unassigned', +}; export function buildLinkRel(vorgangFilter: VorgangFilter, vorgangView: VorgangView): string { - const filterParam: string = VORGANG_LIST_LINK_REL_SUFFIX[vorgangFilter]; + const filterParam: string = VORGANG_LIST_LINK_REL_SUFFIX[vorgangFilter]; - if(vorgangView !== VorgangView.VORGANG_LIST){ - return `vorgaenge_${ROUTE_PARAM_BY_VORGANG_VIEW[vorgangView]}_${filterParam}`; - } - return `vorgaenge_${filterParam}`; + if (vorgangView !== VorgangView.VORGANG_LIST) { + return `vorgaenge_${ROUTE_PARAM_BY_VORGANG_VIEW[vorgangView]}_${filterParam}`; + } + return `vorgaenge_${filterParam}`; } export function buildLinkRelFromPathSegments(pathSegments: string[]): string { - const vorgangFilter: VorgangFilter = VORGANG_FILTER_BY_ROUTE_PARAM[pathSegments[0]]; + const vorgangFilter: VorgangFilter = VORGANG_FILTER_BY_ROUTE_PARAM[pathSegments[0]]; - if (pathSegments[1] === SEARCH_ROUTE_PARAM) { - return getSearchLinkRel(vorgangFilter); - } + if (pathSegments[1] === SEARCH_ROUTE_PARAM) { + return getSearchLinkRel(vorgangFilter); + } - const vorgangView: VorgangView = isEmpty(pathSegments[1]) - ? VorgangView.VORGANG_LIST - : VORGANG_VIEW_BY_ROUTE_PARAM[pathSegments[1]]; + const vorgangView: VorgangView = + isEmpty(pathSegments[1]) ? + VorgangView.VORGANG_LIST + : VORGANG_VIEW_BY_ROUTE_PARAM[pathSegments[1]]; - return buildLinkRel(vorgangFilter, vorgangView); + return buildLinkRel(vorgangFilter, vorgangView); } -export function buildVorgangFilterViewRoutePath(vorgangFilter: VorgangFilter, vorgangView: VorgangView, searchString: string): string { - let baseRoutePath: string = '/' + ROUTE_PARAM_BY_VORGANG_FILTER[vorgangFilter] + '/' + ROUTE_PARAM_BY_VORGANG_VIEW[vorgangView]; - if(isNotEmpty(searchString)){ - return baseRoutePath + '/' + searchString; - } - return baseRoutePath; +export function buildVorgangFilterViewRoutePath( + vorgangFilter: VorgangFilter, + vorgangView: VorgangView, + searchString: string, +): string { + let baseRoutePath: string = + '/' + + ROUTE_PARAM_BY_VORGANG_FILTER[vorgangFilter] + + '/' + + ROUTE_PARAM_BY_VORGANG_VIEW[vorgangView]; + if (isNotEmpty(searchString)) { + return baseRoutePath + '/' + searchString; + } + return baseRoutePath; } export function buildPathSegmentsFromLocalStorage(): string[] { - const pathSegments: string[] = []; - const view: string = getViewFromLocalStorage(); - let filter: string = getFilterFromLocalStorage(); + const pathSegments: string[] = []; + const view: string = getViewFromLocalStorage(); + let filter: string = getFilterFromLocalStorage(); - filter = isEmpty(filter) ? ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] : filter; - pathSegments.push(filter); + filter = isEmpty(filter) ? ROUTE_PARAM_BY_VORGANG_FILTER[VorgangFilter.ALLE] : filter; + pathSegments.push(filter); - if (isNotEmpty(view)) { - pathSegments.push(view); - } + if (isNotEmpty(view)) { + pathSegments.push(view); + } - return pathSegments; + return pathSegments; } export function isVorgangPage(routeData: RouteData): boolean { - return hasSegements(routeData, 0) && hasVorgangParam(routeData); + return hasSegements(routeData, 0) && hasVorgangParam(routeData); } function hasVorgangParam(routeData: RouteData): boolean { - return isNotNull(routeData.queryParameter[VORGANG_WITH_EINGANG_ROUTE_PARAM]); + return isNotNull(routeData.queryParameter[VORGANG_WITH_EINGANG_ROUTE_PARAM]); } function hasSegements(routeData: RouteData, numberOfSegements: number): boolean { - return routeData.urlSegments.length === numberOfSegements; + return routeData.urlSegments.length === numberOfSegements; } diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.spec.ts index 2020d54c757db1b9850a16a397ca81f9837d88b6..bd67691f41ffd392e10ce6eee7bcd8b77d530d3e 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.spec.ts @@ -25,13 +25,13 @@ import { VorgangSharedModule } from './vorgang-shared.module'; import { TestBed } from '@angular/core/testing'; describe('VorgangSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [VorgangSharedModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [VorgangSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(VorgangSharedModule).toBeDefined(); - }); + it('should create', () => { + expect(VorgangSharedModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.ts index 8b17ab522914556809152eaa2afaa32d4080c129..bd174181a92a6f388285f69b90633265699066e5 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang-shared.module.ts @@ -39,23 +39,20 @@ import { VorgangHttpErrorService } from './vorgang-http-error.service'; import * as fromVorgang from './+state/vorgang.reducer'; @NgModule({ - imports: [ - CommonModule, - RestModule, - TechSharedModule, - CommandSharedModule, - BinaryFileSharedModule, - PostfachSharedModule, - RouterModule, - StoreModule.forFeature( - fromVorgang.VORGANG_FEATURE_KEY, - fromVorgang.reducer - ), - EffectsModule.forFeature([VorgangEffects]), - NavigationSharedModule - ], - providers: [VorgangFacade], + imports: [ + CommonModule, + RestModule, + TechSharedModule, + CommandSharedModule, + BinaryFileSharedModule, + PostfachSharedModule, + RouterModule, + StoreModule.forFeature(fromVorgang.VORGANG_FEATURE_KEY, fromVorgang.reducer), + EffectsModule.forFeature([VorgangEffects]), + NavigationSharedModule, + ], + providers: [VorgangFacade], }) export class VorgangSharedModule { - constructor(private vorgangErrorSevice: VorgangHttpErrorService) { } + constructor(private vorgangErrorSevice: VorgangHttpErrorService) {} } diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts index 12e9ac952f6e265e1cfd39e7124a19229c80c9dc..2a47bbc6e3df382353b5e58466f534832b53f39b 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.linkrel.ts @@ -22,46 +22,46 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum VorgangListLinkRel { - VORGANG_HEADER_LIST = 'vorgangHeaderList', - NEXT = 'next', + VORGANG_HEADER_LIST = 'vorgangHeaderList', + NEXT = 'next', } export enum VorgangHeaderLinkRel { - VORGANG_WITH_EINGANG = 'vorgang-mit-eingang', - ASSIGN = 'assign', - WIEDERVORLAGEN = 'wiedervorlagen', - KOMMENTARE = 'kommentare', - ASSIGNED_TO = 'assignedTo', - POSTFACH_MAILS = 'postfachMails', + VORGANG_WITH_EINGANG = 'vorgang-mit-eingang', + ASSIGN = 'assign', + WIEDERVORLAGEN = 'wiedervorlagen', + KOMMENTARE = 'kommentare', + ASSIGNED_TO = 'assignedTo', + POSTFACH_MAILS = 'postfachMails', } export enum VorgangWithEingangLinkRel { - ANNEHMEN = 'annehmen', - VERWERFEN = 'verwerfen', - ZURUECKHOLEN = 'zurueckholen', - BEARBEITEN = 'bearbeiten', - BESCHEIDEN = 'bescheiden', - ZURUECKSTELLEN = 'zurueckstellen', - ABSCHLIESSEN = 'abschliessen', - WIEDEREROEFFNEN = 'wiedereroeffnen', - LOESCHEN_ANFORDERN = 'loeschen_anfordern', - LOESCH_ANFORDERUNG = 'loesch_anforderung', + ANNEHMEN = 'annehmen', + VERWERFEN = 'verwerfen', + ZURUECKHOLEN = 'zurueckholen', + BEARBEITEN = 'bearbeiten', + BESCHEIDEN = 'bescheiden', + ZURUECKSTELLEN = 'zurueckstellen', + ABSCHLIESSEN = 'abschliessen', + WIEDEREROEFFNEN = 'wiedereroeffnen', + LOESCHEN_ANFORDERN = 'loeschen_anfordern', + LOESCH_ANFORDERUNG = 'loesch_anforderung', - ATTACHMENTS = 'attachments', - FORWARD = 'forward', - FORWARDING = 'forwarding', - PENDING_COMMANDS = 'pending-commands', - ASSIGN = 'assign', - REPRESENTATIONS = 'representations', - HISTORIE = 'historie', - SEARCH_USER_PROFILES = 'search-user-profiles', - EXPORT = 'export', - CREATE_BESCHEID = 'createBescheid', - PROCESS_VORGANG = 'processVorgang', + ATTACHMENTS = 'attachments', + FORWARD = 'forward', + FORWARDING = 'forwarding', + PENDING_COMMANDS = 'pending-commands', + ASSIGN = 'assign', + REPRESENTATIONS = 'representations', + HISTORIE = 'historie', + SEARCH_USER_PROFILES = 'search-user-profiles', + EXPORT = 'export', + CREATE_BESCHEID = 'createBescheid', + PROCESS_VORGANG = 'processVorgang', - SET_AKTENZEICHEN = 'set_aktenzeichen', + SET_AKTENZEICHEN = 'set_aktenzeichen', } export enum LoeschAnforderungLinkRel { - EXECUTE_LOESCHEN = 'execute_loeschen' -} \ No newline at end of file + EXECUTE_LOESCHEN = 'execute_loeschen', +} diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.messages.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.messages.ts index 2cacc8b1a8c74e7806d2d59ae5c5b308f4ec6968..729c04e5ddb964934f4286d5f5403b8135aa06fc 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.messages.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.messages.ts @@ -22,17 +22,17 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum VorgangStatusLabel { - NEU = 'Neu', - ANGENOMMEN = 'Angenommen', - VERWORFEN = 'Verworfen', - IN_BEARBEITUNG = 'In Bearbeitung', - BESCHIEDEN = 'Beschieden', - ZURUECKGESTELLT = 'Zurückgestellt', - ABGESCHLOSSEN = 'Abgeschlossen', - WEITERGELEITET = 'Weitergeleitet', - ZU_LOESCHEN = 'Zu Löschen' + NEU = 'Neu', + ANGENOMMEN = 'Angenommen', + VERWORFEN = 'Verworfen', + IN_BEARBEITUNG = 'In Bearbeitung', + BESCHIEDEN = 'Beschieden', + ZURUECKGESTELLT = 'Zurückgestellt', + ABGESCHLOSSEN = 'Abgeschlossen', + WEITERGELEITET = 'Weitergeleitet', + ZU_LOESCHEN = 'Zu Löschen', } export enum VorgangMessages { - SEARCH_UNAVAILABLE = 'Die Suche ist vorübergehen nicht verfügbar. Versuchen Sie es zu einem späteren Zeitpunkt erneut.' + SEARCH_UNAVAILABLE = 'Die Suche ist vorübergehen nicht verfügbar. Versuchen Sie es zu einem späteren Zeitpunkt erneut.', } diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts index 06dedec138f60a1e35efe835387c8720b179370b..41b412c9839bb98940bbdd55ea74e8fcd1e47cb3 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.model.ts @@ -25,154 +25,158 @@ import { HttpErrorResponse } from '@angular/common/http'; import { ListResource, StateResource } from '@alfa-client/tech-shared'; import { TypedAction } from '@ngrx/store/src/models'; import { Resource, ResourceUri } from '@ngxp/rest'; -import { CommandOrder, CommandResource, CreateCommand } from '../../../command-shared/src/lib/command.model'; +import { + CommandOrder, + CommandResource, + CreateCommand, +} from '../../../command-shared/src/lib/command.model'; export interface Vorgang { - status: VorgangStatus, - aktenzeichen: string, - nummer: string, - createdAt: Date, - name: string, - nextFrist: Date, - hasPostfachNachricht: boolean, - hasNewPostfachNachricht: boolean + status: VorgangStatus; + aktenzeichen: string; + nummer: string; + createdAt: Date; + name: string; + nextFrist: Date; + hasPostfachNachricht: boolean; + hasNewPostfachNachricht: boolean; } export interface VorgangWithEingang extends Vorgang { - eingang: Eingang + eingang: Eingang; } export interface Eingang { - id: string, - antragsteller: Antragsteller, - zustaendigeStelle: ZustaendigeStelle, - header: EingangHeader, - formData: ReadonlyMap<string, object> | object | Array<string> - numberOfAttachments: number; - numberOfRepresentations: number; + id: string; + antragsteller: Antragsteller; + zustaendigeStelle: ZustaendigeStelle; + header: EingangHeader; + formData: ReadonlyMap<string, object> | object | Array<string>; + numberOfAttachments: number; + numberOfRepresentations: number; } export interface Antragsteller { - anrede: string, - geburtsdatum: string, - geburtsname: string, - geburtsort: string, - nachname: string, - vorname: string, - email: string, - telefon: string, - strasse: string, - hausnummer: string, - plz: string, - ort: string, - otherData: ReadonlyMap<string, object> + anrede: string; + geburtsdatum: string; + geburtsname: string; + geburtsort: string; + nachname: string; + vorname: string; + email: string; + telefon: string; + strasse: string; + hausnummer: string; + plz: string; + ort: string; + otherData: ReadonlyMap<string, object>; } export interface ZustaendigeStelle { - email: string + email: string; } export interface EingangHeader { - client: string, - clientId: string, - createdAt: string, - customer: string, - customerId: string, - formId: string, - formName: string, - requestId: string, - sender: string + client: string; + clientId: string; + createdAt: string; + customer: string; + customerId: string; + formId: string; + formName: string; + requestId: string; + sender: string; } export enum VorgangStatus { - NEU = 'NEU', - ANGENOMMEN = 'ANGENOMMEN', - VERWORFEN = 'VERWORFEN', - IN_BEARBEITUNG = 'IN_BEARBEITUNG', - BESCHIEDEN = 'BESCHIEDEN', - ABGESCHLOSSEN = 'ABGESCHLOSSEN', - WEITERGELEITET = 'WEITERGELEITET', - ZU_LOESCHEN = 'ZU_LOESCHEN' + NEU = 'NEU', + ANGENOMMEN = 'ANGENOMMEN', + VERWORFEN = 'VERWORFEN', + IN_BEARBEITUNG = 'IN_BEARBEITUNG', + BESCHIEDEN = 'BESCHIEDEN', + ABGESCHLOSSEN = 'ABGESCHLOSSEN', + WEITERGELEITET = 'WEITERGELEITET', + ZU_LOESCHEN = 'ZU_LOESCHEN', } -export interface VorgangResource extends Vorgang, Resource { } +export interface VorgangResource extends Vorgang, Resource {} export interface VorgangListResource extends ListResource { - statistic: VorgangStatistic + statistic: VorgangStatistic; } export interface VorgangStatistic { - byStatus: ByStatus; - wiedervorlagen: number; - existsWiedervorlageOverdue: boolean; + byStatus: ByStatus; + wiedervorlagen: number; + existsWiedervorlageOverdue: boolean; } export interface ByStatus { - neu: number; - angenommen: number; - inBearbeitung: number; - beschieden: number; - abgeschlossen: number; - verworfen: number; - zuLoeschen: number; + neu: number; + angenommen: number; + inBearbeitung: number; + beschieden: number; + abgeschlossen: number; + verworfen: number; + zuLoeschen: number; } -export interface VorgangWithEingangResource extends VorgangWithEingang, Resource { } +export interface VorgangWithEingangResource extends VorgangWithEingang, Resource {} export interface VorgangDetailSnackBarData { - message: string, - showRevokeButton: boolean + message: string; + showRevokeButton: boolean; } export interface CreateForwardCommand extends CreateCommand { - order: CommandOrder, - redirectRequest: ForwardRequest + order: CommandOrder; + redirectRequest: ForwardRequest; } export interface ForwardRequest { - email: string, - password: string + email: string; + password: string; } export interface CreateAssignUserCommand extends CreateCommand { - body: AssignUserBody + body: AssignUserBody; } export interface AssignUserBody { - assignedTo: ResourceUri + assignedTo: ResourceUri; } export enum VorgangFilter { - ALLE, - MEINE_VORGAENGE, - NICHT_ZUGEWIESEN + ALLE, + MEINE_VORGAENGE, + NICHT_ZUGEWIESEN, } export enum VorgangView { - NEU, - ANGENOMMEN, - IN_BEARBEITUNG, - BESCHIEDEN, - ABGESCHLOSSEN, - VERWORFEN, - VORGANG_LIST, - WIEDERVORLAGEN, - SEARCH, - ZU_LOESCHEN + NEU, + ANGENOMMEN, + IN_BEARBEITUNG, + BESCHIEDEN, + ABGESCHLOSSEN, + VERWORFEN, + VORGANG_LIST, + WIEDERVORLAGEN, + SEARCH, + ZU_LOESCHEN, } export interface StatusCommandMap { - [CommandOrder.VORGANG_ABSCHLIESSEN]: StateResource<CommandResource>, - [CommandOrder.VORGANG_ANNEHMEN]: StateResource<CommandResource>, - [CommandOrder.VORGANG_BEARBEITEN]: StateResource<CommandResource>, - [CommandOrder.VORGANG_BESCHEIDEN]: StateResource<CommandResource>, - [CommandOrder.VORGANG_VERWERFEN]: StateResource<CommandResource>, - [CommandOrder.VORGANG_WIEDEREROEFFNEN]: StateResource<CommandResource>, - [CommandOrder.VORGANG_ZURUECKHOLEN]: StateResource<CommandResource>, - [CommandOrder.VORGANG_ZURUECKSTELLEN]: StateResource<CommandResource> + [CommandOrder.VORGANG_ABSCHLIESSEN]: StateResource<CommandResource>; + [CommandOrder.VORGANG_ANNEHMEN]: StateResource<CommandResource>; + [CommandOrder.VORGANG_BEARBEITEN]: StateResource<CommandResource>; + [CommandOrder.VORGANG_BESCHEIDEN]: StateResource<CommandResource>; + [CommandOrder.VORGANG_VERWERFEN]: StateResource<CommandResource>; + [CommandOrder.VORGANG_WIEDEREROEFFNEN]: StateResource<CommandResource>; + [CommandOrder.VORGANG_ZURUECKHOLEN]: StateResource<CommandResource>; + [CommandOrder.VORGANG_ZURUECKSTELLEN]: StateResource<CommandResource>; } export interface AdditionalActions { - additionalSuccessAction: () => TypedAction<string>, - additionalFailureAction: (error: HttpErrorResponse) => TypedAction<string> + additionalSuccessAction: () => TypedAction<string>; + additionalFailureAction: (error: HttpErrorResponse) => TypedAction<string>; } diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts index 8589b4ce25416f21cec81fdd86255dda54754a69..f0d268a743ec890a3357fb82d3d04b8db76a7481 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts @@ -23,10 +23,20 @@ */ import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared'; import { BinaryFileListResource } from '@alfa-client/binary-file-shared'; -import { CommandOrder, CommandResource, CommandService, CreateCommandProps } from '@alfa-client/command-shared'; +import { + CommandOrder, + CommandResource, + CommandService, + CreateCommandProps, +} from '@alfa-client/command-shared'; import { Environment } from '@alfa-client/environment-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { EMPTY_STRING, StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + EMPTY_STRING, + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { HttpErrorResponse } from '@angular/common/http'; import { ResourceUri, getUrl } from '@ngxp/rest'; @@ -47,466 +57,484 @@ import faker from '@faker-js/faker'; import * as VorgangNavigationUtil from './vorgang-navigation.util'; describe('VorgangService', () => { - let service: VorgangService; - let navigationService: Mock<NavigationService>; - let facade: Mock<VorgangFacade>; - let apiRootService: Mock<ApiRootService>; - let commandService: Mock<CommandService>; - let envConfig: Environment = <any>{ processorNames: ['dummyProcessorName'] }; + let service: VorgangService; + let navigationService: Mock<NavigationService>; + let facade: Mock<VorgangFacade>; + let apiRootService: Mock<ApiRootService>; + let commandService: Mock<CommandService>; + let envConfig: Environment = <any>{ processorNames: ['dummyProcessorName'] }; + + beforeEach(() => { + navigationService = { ...mock(NavigationService) }; + facade = mock(VorgangFacade); + apiRootService = mock(ApiRootService); + commandService = mock(CommandService); + navigationService.urlChanged = jest.fn(); + navigationService.urlChanged.mockReturnValue(of({})); + + service = new VorgangService( + useFromMock(navigationService), + useFromMock(facade), + useFromMock(apiRootService), + useFromMock(commandService), + envConfig, + ); + }); + + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource> = + createStateResource(vorgangWithEingang); + + describe('getVorgangWithEingang', () => { + const apiRootStateResource: StateResource<ApiRootResource> = + createStateResource(createApiRootResource()); + + beforeEach(() => { + apiRootService.getApiRoot.mockReturnValue(of(apiRootStateResource)); + }); + + it('should get vorgangWithEingang', () => { + service.getVorgangWithEingang(); + + expect(facade.getVorgangWithEingang).toBeCalled(); + }); + + it('should get getApiRoot', () => { + service.getVorgangWithEingang(); + + expect(apiRootService.getApiRoot).toBeCalled(); + }); + + describe('initial', () => { + beforeEach(() => { + apiRootService.getApiRoot.mockReturnValue(hot('-a', { a: apiRootStateResource })); + facade.getVorgangWithEingang.mockReturnValue( + hot('-a', { a: vorgangWithEingangStateResource }), + ); + }); + + it('should return value', () => { + const vorgangList = service.getVorgangWithEingang(); + + expect(vorgangList).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: vorgangWithEingangStateResource }), + ); + }); + }); + + describe('loadVorgangWithEingang', () => { + it('should be called if loading required', () => { + facade.getVorgangWithEingang.mockReturnValue(of(createEmptyStateResource())); + + service.getVorgangWithEingang().subscribe(); + + expect(facade.loadVorgangWithEingang).toHaveBeenCalled(); + }); + + it('should NOT be called if already loaded', () => { + facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); + + service.getVorgangWithEingang().subscribe(); - beforeEach(() => { - navigationService = { ...mock(NavigationService) }; - facade = mock(VorgangFacade); - apiRootService = mock(ApiRootService); - commandService = mock(CommandService); - navigationService.urlChanged = jest.fn(); - navigationService.urlChanged.mockReturnValue(of({})); + expect(facade.loadVorgangWithEingang).not.toHaveBeenCalled(); + }); + }); + }); + + describe('getVorgangWithEingangUri', () => { + it('should call facade', () => { + service.getVorgangWithEingangUri(); + + expect(navigationService.getDecodedParam).toHaveBeenCalledWith( + VorgangService.VORGANG_WITH_EINGANG_URL, + ); + }); + }); + + describe('getAttachments', () => { + const binaryFile: BinaryFileListResource = createBinaryFileListResource(); + const binaryFileStateResource: StateResource<BinaryFileListResource> = + createStateResource(binaryFile); - service = new VorgangService(useFromMock(navigationService), useFromMock(facade), useFromMock(apiRootService), useFromMock(commandService), envConfig); - }) + beforeEach(() => { + facade.getAttachmentList.mockReturnValue(of(binaryFileStateResource)); + facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); + }); - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(vorgangWithEingang); + it('should get AttachmentList by facade', () => { + service.getAttachments(); - describe('getVorgangWithEingang', () => { + expect(facade.getAttachmentList).toHaveBeenCalled(); + }); - const apiRootStateResource: StateResource<ApiRootResource> = createStateResource(createApiRootResource()); + it('should get vorgangWithEingang by facade', () => { + service.getAttachments(); - beforeEach(() => { - apiRootService.getApiRoot.mockReturnValue(of(apiRootStateResource)); - }) + expect(facade.getVorgangWithEingang).toHaveBeenCalled(); + }); - it('should get vorgangWithEingang', () => { - service.getVorgangWithEingang(); + describe('initial', () => { + beforeEach(() => { + facade.getAttachmentList.mockReturnValue(hot('-a', { a: binaryFileStateResource })); + facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); + }); - expect(facade.getVorgangWithEingang).toBeCalled(); - }) + it('should return value', () => { + const vorgangList = service.getAttachments(); - it('should get getApiRoot', () => { - service.getVorgangWithEingang(); + expect(vorgangList).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: binaryFileStateResource }), + ); + }); + }); - expect(apiRootService.getApiRoot).toBeCalled(); - }) + describe('loadAttachments', () => { + it('should be called if loading required', () => { + facade.getAttachmentList.mockReturnValue(of(createEmptyStateResource())); - describe('initial', () => { + service.getAttachments().subscribe(); - beforeEach(() => { - apiRootService.getApiRoot.mockReturnValue(hot('-a', { a: apiRootStateResource })); - facade.getVorgangWithEingang.mockReturnValue(hot('-a', { a: vorgangWithEingangStateResource })); - }) + expect(facade.loadAttachmentList).toHaveBeenCalledWith(vorgangWithEingang); + }); - it('should return value', () => { - const vorgangList = service.getVorgangWithEingang(); + it('should NOT be called if already loaded', () => { + service.getAttachments().subscribe(); - expect(vorgangList).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: vorgangWithEingangStateResource })); - }) - }) + expect(facade.loadAttachmentList).not.toHaveBeenCalled(); + }); - describe('loadVorgangWithEingang', () => { + it('should NOT be called if vorgangWithEingang is not loaded', () => { + facade.getVorgangWithEingang.mockReturnValue(of(createEmptyStateResource())); - it('should be called if loading required', () => { - facade.getVorgangWithEingang.mockReturnValue(of(createEmptyStateResource())); + service.getAttachments().subscribe(); - service.getVorgangWithEingang().subscribe(); + expect(facade.loadAttachmentList).not.toHaveBeenCalled(); + }); + }); + }); - expect(facade.loadVorgangWithEingang).toHaveBeenCalled(); - }) + describe('getRepresentations', () => { + const binaryFile: BinaryFileListResource = createBinaryFileListResource(); + const binaryFileStateResource: StateResource<BinaryFileListResource> = + createStateResource(binaryFile); - it('should NOT be called if already loaded', () => { - facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); + beforeEach(() => { + facade.getRepresentationList.mockReturnValue(of(binaryFileStateResource)); + facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); + }); - service.getVorgangWithEingang().subscribe(); + it('should get RepresentationList by facade', () => { + service.getRepresentations(); - expect(facade.loadVorgangWithEingang).not.toHaveBeenCalled(); - }) - }) - }) + expect(facade.getRepresentationList).toHaveBeenCalled(); + }); - describe('getVorgangWithEingangUri', () => { + it('should get vorgangWithEingang by facade', () => { + service.getRepresentations(); - it('should call facade', () => { - service.getVorgangWithEingangUri(); + expect(facade.getVorgangWithEingang).toHaveBeenCalled(); + }); - expect(navigationService.getDecodedParam).toHaveBeenCalledWith(VorgangService.VORGANG_WITH_EINGANG_URL); - }) - }) + describe('initial', () => { + beforeEach(() => { + facade.getRepresentationList.mockReturnValue(hot('-a', { a: binaryFileStateResource })); + facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); + }); - describe('getAttachments', () => { + it('should return value', () => { + const vorgangList = service.getRepresentations(); - const binaryFile: BinaryFileListResource = createBinaryFileListResource(); - const binaryFileStateResource: StateResource<BinaryFileListResource> = createStateResource(binaryFile); + expect(vorgangList).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: binaryFileStateResource }), + ); + }); + }); - beforeEach(() => { - facade.getAttachmentList.mockReturnValue(of(binaryFileStateResource)); - facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); - }) + describe('loadRepresentationList', () => { + it('should be called if loading required', () => { + facade.getRepresentationList.mockReturnValue(of(createEmptyStateResource())); - it('should get AttachmentList by facade', () => { - service.getAttachments(); + service.getRepresentations().subscribe(); - expect(facade.getAttachmentList).toHaveBeenCalled(); - }) + expect(facade.loadRepresentationList).toHaveBeenCalledWith(vorgangWithEingang); + }); - it('should get vorgangWithEingang by facade', () => { - service.getAttachments(); + it('should NOT be called if already loaded', () => { + service.getRepresentations().subscribe(); - expect(facade.getVorgangWithEingang).toHaveBeenCalled(); - }) + expect(facade.loadRepresentationList).not.toHaveBeenCalled(); + }); - describe('initial', () => { + it('should NOT be called if vorgangWithEingang is not loaded', () => { + facade.getVorgangWithEingang.mockReturnValue(of(createEmptyStateResource())); - beforeEach(() => { - facade.getAttachmentList.mockReturnValue(hot('-a', { a: binaryFileStateResource })); - facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); - }) + service.getRepresentations().subscribe(); - it('should return value', () => { - const vorgangList = service.getAttachments(); + expect(facade.loadRepresentationList).not.toHaveBeenCalled(); + }); + }); + }); - expect(vorgangList).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: binaryFileStateResource })); - }) - }) + describe('clearVorgang', () => { + it('should call facade', () => { + service.clearVorgang(); - describe('loadAttachments', () => { + expect(facade.clearVorgangWithEingang).toHaveBeenCalled(); + }); + }); - it('should be called if loading required', () => { - facade.getAttachmentList.mockReturnValue(of(createEmptyStateResource())); + describe('setPendingForwardSingleCommandLoading', () => { + it('should call facade', () => { + service.setPendingForwardSingleCommandLoading(); - service.getAttachments().subscribe(); + expect(facade.setForwardSingleCommandLoading).toHaveBeenCalled(); + }); + }); - expect(facade.loadAttachmentList).toHaveBeenCalledWith(vorgangWithEingang) - }) + describe('getForwardPendingCommand', () => { + beforeEach(() => { + facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); + facade.getForwardPendingCommand.mockReturnValue(of(createEmptyStateResource())); + }); - it('should NOT be called if already loaded', () => { - service.getAttachments().subscribe(); + it('should call facade', () => { + service.getPendingForwardCommand(); - expect(facade.loadAttachmentList).not.toHaveBeenCalled(); - }) + expect(facade.getForwardPendingCommand).toHaveBeenCalled(); + }); + }); - it('should NOT be called if vorgangWithEingang is not loaded', () => { - facade.getVorgangWithEingang.mockReturnValue(of(createEmptyStateResource())); + describe('setPendingForwardSingleCommand', () => { + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); - service.getAttachments().subscribe(); + it('should call facade', () => { + service.setPendingForwardSingleCommand(commandStateResource); - expect(facade.loadAttachmentList).not.toHaveBeenCalled(); - }) - }) - }) + expect(facade.setForwardSingleCommand).toHaveBeenCalledWith(commandStateResource); + }); + }); - describe('getRepresentations', () => { + describe('setPendingForwardSingleCommandLoading', () => { + it('should call facade', () => { + service.setPendingForwardSingleCommandLoading(); - const binaryFile: BinaryFileListResource = createBinaryFileListResource(); - const binaryFileStateResource: StateResource<BinaryFileListResource> = createStateResource(binaryFile); + expect(facade.setForwardSingleCommandLoading).toHaveBeenCalled(); + }); + }); - beforeEach(() => { - facade.getRepresentationList.mockReturnValue(of(binaryFileStateResource)); - facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); - }) + describe('getPendingSendPostfachMailCommand', () => { + beforeEach(() => { + facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); + facade.getSendPostfachNachrichtPendingCommand.mockReturnValue(of(createEmptyStateResource())); + }); - it('should get RepresentationList by facade', () => { - service.getRepresentations(); + it('should call facade', () => { + service.getPendingSendPostfachMailCommand(); - expect(facade.getRepresentationList).toHaveBeenCalled(); - }) + expect(facade.getSendPostfachNachrichtPendingCommand).toHaveBeenCalled(); + }); + }); + + describe('setPendingForwardSingleCommand', () => { + const commandStateResource: StateResource<CommandResource> = + createStateResource(createCommandResource()); - it('should get vorgangWithEingang by facade', () => { - service.getRepresentations(); + it('should call facade', () => { + service.setPendingForwardSingleCommand(commandStateResource); - expect(facade.getVorgangWithEingang).toHaveBeenCalled(); - }) + expect(facade.setForwardSingleCommand).toHaveBeenCalledWith(commandStateResource); + }); + }); - describe('initial', () => { + describe('reloadCurrentVorgang', () => { + beforeEach(() => { + navigationService.getDecodedParam.mockReturnValue('decodedParameterUrlForTest'); + }); - beforeEach(() => { - facade.getRepresentationList.mockReturnValue(hot('-a', { a: binaryFileStateResource })); - facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); - }) + it('should call navigation service', () => { + service.reloadCurrentVorgang(); - it('should return value', () => { - const vorgangList = service.getRepresentations(); + expect(navigationService.getDecodedParam).toHaveBeenCalledWith( + VorgangService.VORGANG_WITH_EINGANG_URL, + ); + }); - expect(vorgangList).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: binaryFileStateResource })); - }) - }) + it('should call loadVorgangWithEingang', () => { + service.reloadCurrentVorgang(); - describe('loadRepresentationList', () => { + expect(facade.loadVorgangWithEingang).toHaveBeenCalled(); + }); + }); - it('should be called if loading required', () => { - facade.getRepresentationList.mockReturnValue(of(createEmptyStateResource())); + describe('reloadCurrentVorgangWithAddtionalActions', () => { + const additionalActions: AdditionalActions = { + additionalSuccessAction: () => null, + additionalFailureAction: (error: HttpErrorResponse) => null, + }; - service.getRepresentations().subscribe(); + beforeEach(() => { + navigationService.getDecodedParam.mockReturnValue('decodedParameterUrlForTest'); + }); - expect(facade.loadRepresentationList).toHaveBeenCalledWith(vorgangWithEingang) - }) + it('should call navigation service', () => { + service.reloadCurrentVorgangWithAddtionalActions(additionalActions); - it('should NOT be called if already loaded', () => { - service.getRepresentations().subscribe(); + expect(navigationService.getDecodedParam).toHaveBeenCalledWith( + VorgangService.VORGANG_WITH_EINGANG_URL, + ); + }); - expect(facade.loadRepresentationList).not.toHaveBeenCalled(); - }) + it('should call loadVorgangWithEingangWithAdditionalActions', () => { + const vorgangUri: string = faker.internet.url(); + service.getVorgangWithEingangUri = jest.fn().mockReturnValue(vorgangUri); - it('should NOT be called if vorgangWithEingang is not loaded', () => { - facade.getVorgangWithEingang.mockReturnValue(of(createEmptyStateResource())); + service.reloadCurrentVorgangWithAddtionalActions(additionalActions); - service.getRepresentations().subscribe(); + expect(facade.loadVorgangWithEingangWithAdditionalActions).toHaveBeenCalledWith( + vorgangUri, + additionalActions, + ); + }); + }); - expect(facade.loadRepresentationList).not.toHaveBeenCalled(); - }) - }) - }) + describe('getAssignUserCommand', () => { + it('should call facade', () => { + service.getAssignUserCommand(); - describe('clearVorgang', () => { + expect(facade.getAssignUserCommand).toHaveBeenCalled(); + }); + }); - it('should call facade', () => { - service.clearVorgang(); + describe('assignUser', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const assignedTo: ResourceUri = faker.internet.url(); - expect(facade.clearVorgangWithEingang).toHaveBeenCalled(); - }) - }) + it.skip('should call facade', () => { + // facade.assignUser = jest.fn(); + // service.assignUser(vorgangWithEingang, assignedTo); + // expect(facade.assignUser).toHaveBeenCalledWith(vorgangWithEingang, <CreateCommand>{ order: CommandOrder.ASSIGN_USER, body: { assignedTo }}); + }); + }); - describe('setPendingForwardSingleCommandLoading', () => { + describe('reloadVorgang', () => { + const command: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); - it('should call facade', () => { - service.setPendingForwardSingleCommandLoading(); + it('should call facade', () => { + service.reloadVorgang(command); - expect(facade.setForwardSingleCommandLoading).toHaveBeenCalled(); - }) - }) + expect(facade.loadVorgangWithEingang).toHaveBeenCalledWith( + getUrl(command, CommandLinkRel.EFFECTED_RESOURCE), + ); + }); + }); - describe('getForwardPendingCommand', () => { + describe('getBackButtonUrl', () => { + it('should call facade', () => { + service.getBackButtonUrl(); - beforeEach(() => { - facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); - facade.getForwardPendingCommand.mockReturnValue(of(createEmptyStateResource())); - }) + expect(facade.getBackButtonUrl).toHaveBeenCalled(); + }); + }); + + describe('canNavigateToPathSegements', () => { + const apiRootStateResource: StateResource<ApiRootResource> = createStateResource( + createApiRootResource([ApiRootLinkRel.ALLE_VORGAENGE_ABGESCHLOSSEN]), + ); + + beforeEach(() => { + apiRootService.getApiRoot.mockReturnValue(hot('a', { a: apiRootStateResource })); + }); + + it('should apiRoot', () => { + service.canNavigateToPathSegements(EMPTY_STRING); + + expect(apiRootService.getApiRoot).toHaveBeenCalled(); + }); - it('should call facade', () => { - service.getPendingForwardCommand(); + it('should call buildLinkRelFromPathSegments', () => { + const spy = jest.spyOn(VorgangNavigationUtil, 'buildLinkRelFromPathSegments'); + + service.canNavigateToPathSegements(EMPTY_STRING); + + expect(spy).toHaveBeenCalled(); + }); - expect(facade.getForwardPendingCommand).toHaveBeenCalled(); - }) - }) + it('should return false as Observable if linkRel not available', () => { + const path: string = '/alle/angenommen'; + + const result: Observable<boolean> = service.canNavigateToPathSegements(path); + + expect(result).toBeObservable(cold('a', { a: false })); + }); + + it('should return true as Observable if linkRel available', () => { + const path: string = '/alle/abgeschlossen'; + + const result: Observable<boolean> = service.canNavigateToPathSegements(path); - describe('setPendingForwardSingleCommand', () => { + expect(result).toBeObservable(cold('a', { a: true })); + }); + }); - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); + describe('getVorgangExport', () => { + it('should call facade', () => { + service.getVorgangExport(); + + expect(facade.getVorgangExport).toHaveBeenCalled(); + }); + }); - it('should call facade', () => { - service.setPendingForwardSingleCommand(commandStateResource); + describe('export', () => { + it('should call facade', () => { + service.export(vorgangWithEingang); - expect(facade.setForwardSingleCommand).toHaveBeenCalledWith(commandStateResource); - }) - }) + expect(facade.export).toHaveBeenCalledWith(vorgangWithEingang); + }); + }); + + describe('processVorgang', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); + const command: CommandResource = createCommandResource(); + const commandStateResource: StateResource<CommandResource> = createStateResource(command); - describe('setPendingForwardSingleCommandLoading', () => { + beforeEach(() => { + commandService.createCommandByProps.mockReturnValue(hot('a', { a: commandStateResource })); + }); - it('should call facade', () => { - service.setPendingForwardSingleCommandLoading(); + it('should call commandService', () => { + service.processVorgang(vorgangWithEingang); - expect(facade.setForwardSingleCommandLoading).toHaveBeenCalled(); - }) - }) + const expectedProps: CreateCommandProps = { + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.PROCESS_VORGANG, + command: { + order: CommandOrder.PROCESS_VORGANG, + body: { processorNames: ['dummyProcessorName'] }, + }, + }; + expect(commandService.createCommandByProps).toHaveBeenCalledWith(expectedProps); + }); - describe('getPendingSendPostfachMailCommand', () => { + it('should return command', () => { + const processVorgangCommand: Observable<StateResource<CommandResource>> = + service.processVorgang(vorgangWithEingang); - beforeEach(() => { - facade.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); - facade.getSendPostfachNachrichtPendingCommand.mockReturnValue(of(createEmptyStateResource())); - }) + expect(processVorgangCommand).toBeObservable(cold('a', { a: commandStateResource })); + }); + }); - it('should call facade', () => { - service.getPendingSendPostfachMailCommand(); + describe('setAktenzeichen', () => { + it('should call command service', () => { + const aktenzeichen = '12345'; - expect(facade.getSendPostfachNachrichtPendingCommand).toHaveBeenCalled(); - }) - }) + service.setAktenzeichen(vorgangWithEingang, aktenzeichen); - describe('setPendingForwardSingleCommand', () => { - - const commandStateResource: StateResource<CommandResource> = createStateResource(createCommandResource()); - - it('should call facade', () => { - service.setPendingForwardSingleCommand(commandStateResource); - - expect(facade.setForwardSingleCommand).toHaveBeenCalledWith(commandStateResource); - }) - }) - - describe('reloadCurrentVorgang', () => { - - beforeEach(() => { - navigationService.getDecodedParam.mockReturnValue('decodedParameterUrlForTest'); - }) - - it('should call navigation service', () => { - service.reloadCurrentVorgang(); - - expect(navigationService.getDecodedParam).toHaveBeenCalledWith(VorgangService.VORGANG_WITH_EINGANG_URL); - }) - - it('should call loadVorgangWithEingang', () => { - service.reloadCurrentVorgang(); - - expect(facade.loadVorgangWithEingang).toHaveBeenCalled(); - }) - }) - - describe('reloadCurrentVorgangWithAddtionalActions', () => { - - const additionalActions: AdditionalActions = { additionalSuccessAction: () => null, additionalFailureAction: (error: HttpErrorResponse) => null }; - - beforeEach(() => { - navigationService.getDecodedParam.mockReturnValue('decodedParameterUrlForTest'); - }) - - it('should call navigation service', () => { - service.reloadCurrentVorgangWithAddtionalActions(additionalActions); - - expect(navigationService.getDecodedParam).toHaveBeenCalledWith(VorgangService.VORGANG_WITH_EINGANG_URL); - }) - - it('should call loadVorgangWithEingangWithAdditionalActions', () => { - const vorgangUri: string = faker.internet.url(); - service.getVorgangWithEingangUri = jest.fn().mockReturnValue(vorgangUri); - - service.reloadCurrentVorgangWithAddtionalActions(additionalActions); - - expect(facade.loadVorgangWithEingangWithAdditionalActions).toHaveBeenCalledWith(vorgangUri, additionalActions); - }) - }) - - describe('getAssignUserCommand', () => { - - it('should call facade', () => { - service.getAssignUserCommand(); - - expect(facade.getAssignUserCommand).toHaveBeenCalled(); - }) - }) - - describe('assignUser', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const assignedTo: ResourceUri = faker.internet.url(); - - it.skip('should call facade', () => { - // facade.assignUser = jest.fn(); - - // service.assignUser(vorgangWithEingang, assignedTo); - - // expect(facade.assignUser).toHaveBeenCalledWith(vorgangWithEingang, <CreateCommand>{ order: CommandOrder.ASSIGN_USER, body: { assignedTo }}); - }) - }) - - describe('reloadVorgang', () => { - - const command: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); - - it('should call facade', () => { - service.reloadVorgang(command); - - expect(facade.loadVorgangWithEingang).toHaveBeenCalledWith(getUrl(command, CommandLinkRel.EFFECTED_RESOURCE)); - }) - }) - - describe('getBackButtonUrl', () => { - - it('should call facade', () => { - service.getBackButtonUrl(); - - expect(facade.getBackButtonUrl).toHaveBeenCalled(); - }) - }) - - describe('canNavigateToPathSegements', () => { - const apiRootStateResource: StateResource<ApiRootResource> = createStateResource(createApiRootResource([ApiRootLinkRel.ALLE_VORGAENGE_ABGESCHLOSSEN])); - - beforeEach(() => { - apiRootService.getApiRoot.mockReturnValue(hot('a', { a: apiRootStateResource })); - }) - - it('should apiRoot', () => { - service.canNavigateToPathSegements(EMPTY_STRING); - - expect(apiRootService.getApiRoot).toHaveBeenCalled(); - }) - - it('should call buildLinkRelFromPathSegments', () => { - const spy = jest.spyOn(VorgangNavigationUtil, 'buildLinkRelFromPathSegments'); - - service.canNavigateToPathSegements(EMPTY_STRING); - - expect(spy).toHaveBeenCalled(); - }) - - it('should return false as Observable if linkRel not available', () => { - const path: string = '/alle/angenommen'; - - const result: Observable<boolean> = service.canNavigateToPathSegements(path); - - expect(result).toBeObservable(cold('a', { a: false })); - }) - - it('should return true as Observable if linkRel available', () => { - const path: string = '/alle/abgeschlossen'; - - const result: Observable<boolean> = service.canNavigateToPathSegements(path); - - expect(result).toBeObservable(cold('a', { a: true })); - }) - }) - - describe('getVorgangExport', () => { - - it('should call facade', () => { - service.getVorgangExport(); - - expect(facade.getVorgangExport).toHaveBeenCalled(); - }) - }) - - describe('export', () => { - - it('should call facade', () => { - service.export(vorgangWithEingang); - - expect(facade.export).toHaveBeenCalledWith(vorgangWithEingang); - }) - }) - - describe('processVorgang', () => { - - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource(); - const command: CommandResource = createCommandResource(); - const commandStateResource: StateResource<CommandResource> = createStateResource(command); - - beforeEach(() => { - commandService.createCommandByProps.mockReturnValue(hot('a', { a: commandStateResource })); - }) - - it('should call commandService', () => { - service.processVorgang(vorgangWithEingang); - - const expectedProps: CreateCommandProps = { resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.PROCESS_VORGANG, command: { order: CommandOrder.PROCESS_VORGANG, body: { processorNames: ['dummyProcessorName']} }}; - expect(commandService.createCommandByProps).toHaveBeenCalledWith(expectedProps); - }) - - it('should return command', () => { - const processVorgangCommand: Observable<StateResource<CommandResource>> = service.processVorgang(vorgangWithEingang); - - expect(processVorgangCommand).toBeObservable(cold('a', { a: commandStateResource })); - }) - }) - - describe('setAktenzeichen', () => { - - it('should call command service', () => { - const aktenzeichen = '12345'; - - service.setAktenzeichen(vorgangWithEingang, aktenzeichen); - - expect(commandService.createCommand).toHaveBeenCalledWith(vorgangWithEingang, VorgangWithEingangLinkRel.SET_AKTENZEICHEN, - { order: CommandOrder.SET_AKTENZEICHEN, body: { aktenzeichen } }); - }) - }) -}) + expect(commandService.createCommand).toHaveBeenCalledWith( + vorgangWithEingang, + VorgangWithEingangLinkRel.SET_AKTENZEICHEN, + { order: CommandOrder.SET_AKTENZEICHEN, body: { aktenzeichen } }, + ); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.ts index 8e813ae7cd2bd0ecaecec5c0348bb5fa963b94c7..a22ea644a4e518739625cb6ab37156ba6855a210 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.service.ts @@ -23,10 +23,20 @@ */ import { ApiRootService } from '@alfa-client/api-root-shared'; import { BinaryFileListResource } from '@alfa-client/binary-file-shared'; -import { CommandOrder, CommandResource, CommandService, CreateCommandProps } from '@alfa-client/command-shared'; +import { + CommandOrder, + CommandResource, + CommandService, + CreateCommandProps, +} from '@alfa-client/command-shared'; import { ENVIRONMENT_CONFIG, Environment } from '@alfa-client/environment-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { StateResource, createEmptyStateResource, doIfLoadingRequired, isNotNull } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + doIfLoadingRequired, + isNotNull, +} from '@alfa-client/tech-shared'; import { Inject, Injectable } from '@angular/core'; import { ResourceUri, getUrl, hasLink } from '@ngxp/rest'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; @@ -40,133 +50,168 @@ import { createAssignUserCommand, createProcessVorgangCommand } from './vorgang. @Injectable({ providedIn: 'root' }) export class VorgangService { - - public static readonly VORGANG_WITH_EINGANG_URL: string = 'vorgangWithEingangUrl'; - - constructor( - private navigationService: NavigationService, - private facade: VorgangFacade, - private apiRootService: ApiRootService, - private commandService: CommandService, - @Inject(ENVIRONMENT_CONFIG) private envConfig: Environment) { } - - public getVorgangWithEingang(): Observable<StateResource<VorgangWithEingangResource>> { - return combineLatest([this.facade.getVorgangWithEingang(), this.apiRootService.getApiRoot()]).pipe( - tap(([vorgangWithEingang, apiRoot]) => { - if(isNotNull(apiRoot.resource)) doIfLoadingRequired(vorgangWithEingang, () => this.facade.loadVorgangWithEingang(this.getVorgangWithEingangUri())); - }), - map(([vorgangWithEingang,]) => vorgangWithEingang), - startWith(createEmptyStateResource<VorgangWithEingangResource>(true))); - } - - public getAttachments(): Observable<StateResource<BinaryFileListResource>> { - return this.facade.getAttachmentList().pipe( - withLatestFrom(this.facade.getVorgangWithEingang()), - tap(([attachmentList, vorgangWithEingang]) => doIfLoadingRequired(attachmentList, () => this.facade.loadAttachmentList(vorgangWithEingang.resource))), - map(([attachmentList, ]) => attachmentList), - startWith(createEmptyStateResource<BinaryFileListResource>(true))); - } - - public getRepresentations(): Observable<StateResource<BinaryFileListResource>> { - return this.facade.getRepresentationList().pipe( - withLatestFrom(this.facade.getVorgangWithEingang()), - tap(([representationList, vorgangWithEingang]) => doIfLoadingRequired(representationList, () => this.facade.loadRepresentationList(vorgangWithEingang.resource))), - map(([representationList, ]) => representationList), - startWith(createEmptyStateResource<BinaryFileListResource>(true))); - } - - public clearVorgang(): void { - this.facade.clearVorgangWithEingang(); - } - - - public setPendingSendPostfachMailCommand(command: StateResource<CommandResource>) { - this.facade.setPendingSendPostfachMailSingleCommand(command); - } - public setPendingSendPostfachMailSingleCommandLoading(): void { - this.facade.setPendingSendPostfachMailSingleCommandLoading(); - } - public getPendingSendPostfachMailCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getSendPostfachNachrichtPendingCommand(); - } - - - public setPendingForwardSingleCommandLoading(): void { - this.facade.setForwardSingleCommandLoading(); - } - public getPendingForwardCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getForwardPendingCommand(); - } - public setPendingForwardSingleCommand(command: StateResource<CommandResource>): void { - this.facade.setForwardSingleCommand(command); - } - - public reloadCurrentVorgang(): void { - this.facade.loadVorgangWithEingang(this.getVorgangWithEingangUri()); - } - - public reloadCurrentVorgangWithAddtionalActions(additionalActions: AdditionalActions): void { - this.facade.loadVorgangWithEingangWithAdditionalActions(this.getVorgangWithEingangUri(), additionalActions); - } - - getVorgangWithEingangUri(): ResourceUri { - return this.navigationService.getDecodedParam(VorgangService.VORGANG_WITH_EINGANG_URL); - } - - public assignUser(userUri: ResourceUri): Observable<StateResource<CommandResource>> { - this.facade.initAssignUser(); - - return this.getAssignUserCommand().pipe( - withLatestFrom(this.facade.getVorgangWithEingang()), - tap(([assignCommand, vorgangWithEingang]) => { - if(assignCommand.reload && !assignCommand.loading) { - this.facade.assignUser(vorgangWithEingang.resource, createAssignUserCommand(userUri)); - } - }), - map(([assignCommand, ]) => assignCommand), - ); - } - - getAssignUserCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getAssignUserCommand(); - } - - public reloadVorgang(commandResource: CommandResource): void { - this.facade.loadVorgangWithEingang(getUrl(commandResource, CommandLinkRel.EFFECTED_RESOURCE)); - } - - public getBackButtonUrl(): Observable<string> { - return this.facade.getBackButtonUrl(); - } - - public canNavigateToPathSegements(path: string): Observable<boolean> { - const pathSegments: string[] = path.substring(1).split('/'); - const linkRel: string = buildLinkRelFromPathSegments(pathSegments); - - return this.apiRootService.getApiRoot().pipe( - filter(apiRoot => isNotNull(apiRoot.resource)), - map(apiRoot => hasLink(apiRoot.resource, linkRel)) - ); - } - - public getVorgangExport(): Observable<StateResource<boolean>> { - return this.facade.getVorgangExport(); - } - - public export(vorgangWithEingang: VorgangWithEingangResource): void { - this.facade.export(vorgangWithEingang); - } - - public processVorgang(vorgangWithEingang: VorgangWithEingangResource): Observable<StateResource<CommandResource>> { - return this.commandService.createCommandByProps(this.createProcessVorgangCommandProps(vorgangWithEingang)); - } - - private createProcessVorgangCommandProps(vorgangWithEingang: VorgangWithEingangResource): CreateCommandProps { - return { resource: vorgangWithEingang, linkRel: VorgangWithEingangLinkRel.PROCESS_VORGANG, command: createProcessVorgangCommand(this.envConfig.processorNames) }; - } - - public setAktenzeichen(vorgang: VorgangWithEingangResource, aktenzeichen: string): Observable<StateResource<CommandResource>> { - const createCommand = { order: CommandOrder.SET_AKTENZEICHEN, body: { aktenzeichen } }; - return this.commandService.createCommand(vorgang, VorgangWithEingangLinkRel.SET_AKTENZEICHEN, createCommand); - } + public static readonly VORGANG_WITH_EINGANG_URL: string = 'vorgangWithEingangUrl'; + + constructor( + private navigationService: NavigationService, + private facade: VorgangFacade, + private apiRootService: ApiRootService, + private commandService: CommandService, + @Inject(ENVIRONMENT_CONFIG) private envConfig: Environment, + ) {} + + public getVorgangWithEingang(): Observable<StateResource<VorgangWithEingangResource>> { + return combineLatest([ + this.facade.getVorgangWithEingang(), + this.apiRootService.getApiRoot(), + ]).pipe( + tap(([vorgangWithEingang, apiRoot]) => { + if (isNotNull(apiRoot.resource)) + doIfLoadingRequired(vorgangWithEingang, () => + this.facade.loadVorgangWithEingang(this.getVorgangWithEingangUri()), + ); + }), + map(([vorgangWithEingang]) => vorgangWithEingang), + startWith(createEmptyStateResource<VorgangWithEingangResource>(true)), + ); + } + + public getAttachments(): Observable<StateResource<BinaryFileListResource>> { + return this.facade.getAttachmentList().pipe( + withLatestFrom(this.facade.getVorgangWithEingang()), + tap(([attachmentList, vorgangWithEingang]) => + doIfLoadingRequired(attachmentList, () => + this.facade.loadAttachmentList(vorgangWithEingang.resource), + ), + ), + map(([attachmentList]) => attachmentList), + startWith(createEmptyStateResource<BinaryFileListResource>(true)), + ); + } + + public getRepresentations(): Observable<StateResource<BinaryFileListResource>> { + return this.facade.getRepresentationList().pipe( + withLatestFrom(this.facade.getVorgangWithEingang()), + tap(([representationList, vorgangWithEingang]) => + doIfLoadingRequired(representationList, () => + this.facade.loadRepresentationList(vorgangWithEingang.resource), + ), + ), + map(([representationList]) => representationList), + startWith(createEmptyStateResource<BinaryFileListResource>(true)), + ); + } + + public clearVorgang(): void { + this.facade.clearVorgangWithEingang(); + } + + public setPendingSendPostfachMailCommand(command: StateResource<CommandResource>) { + this.facade.setPendingSendPostfachMailSingleCommand(command); + } + public setPendingSendPostfachMailSingleCommandLoading(): void { + this.facade.setPendingSendPostfachMailSingleCommandLoading(); + } + public getPendingSendPostfachMailCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getSendPostfachNachrichtPendingCommand(); + } + + public setPendingForwardSingleCommandLoading(): void { + this.facade.setForwardSingleCommandLoading(); + } + public getPendingForwardCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getForwardPendingCommand(); + } + public setPendingForwardSingleCommand(command: StateResource<CommandResource>): void { + this.facade.setForwardSingleCommand(command); + } + + public reloadCurrentVorgang(): void { + this.facade.loadVorgangWithEingang(this.getVorgangWithEingangUri()); + } + + public reloadCurrentVorgangWithAddtionalActions(additionalActions: AdditionalActions): void { + this.facade.loadVorgangWithEingangWithAdditionalActions( + this.getVorgangWithEingangUri(), + additionalActions, + ); + } + + getVorgangWithEingangUri(): ResourceUri { + return this.navigationService.getDecodedParam(VorgangService.VORGANG_WITH_EINGANG_URL); + } + + public assignUser(userUri: ResourceUri): Observable<StateResource<CommandResource>> { + this.facade.initAssignUser(); + + return this.getAssignUserCommand().pipe( + withLatestFrom(this.facade.getVorgangWithEingang()), + tap(([assignCommand, vorgangWithEingang]) => { + if (assignCommand.reload && !assignCommand.loading) { + this.facade.assignUser(vorgangWithEingang.resource, createAssignUserCommand(userUri)); + } + }), + map(([assignCommand]) => assignCommand), + ); + } + + getAssignUserCommand(): Observable<StateResource<CommandResource>> { + return this.facade.getAssignUserCommand(); + } + + public reloadVorgang(commandResource: CommandResource): void { + this.facade.loadVorgangWithEingang(getUrl(commandResource, CommandLinkRel.EFFECTED_RESOURCE)); + } + + public getBackButtonUrl(): Observable<string> { + return this.facade.getBackButtonUrl(); + } + + public canNavigateToPathSegements(path: string): Observable<boolean> { + const pathSegments: string[] = path.substring(1).split('/'); + const linkRel: string = buildLinkRelFromPathSegments(pathSegments); + + return this.apiRootService.getApiRoot().pipe( + filter((apiRoot) => isNotNull(apiRoot.resource)), + map((apiRoot) => hasLink(apiRoot.resource, linkRel)), + ); + } + + public getVorgangExport(): Observable<StateResource<boolean>> { + return this.facade.getVorgangExport(); + } + + public export(vorgangWithEingang: VorgangWithEingangResource): void { + this.facade.export(vorgangWithEingang); + } + + public processVorgang( + vorgangWithEingang: VorgangWithEingangResource, + ): Observable<StateResource<CommandResource>> { + return this.commandService.createCommandByProps( + this.createProcessVorgangCommandProps(vorgangWithEingang), + ); + } + + private createProcessVorgangCommandProps( + vorgangWithEingang: VorgangWithEingangResource, + ): CreateCommandProps { + return { + resource: vorgangWithEingang, + linkRel: VorgangWithEingangLinkRel.PROCESS_VORGANG, + command: createProcessVorgangCommand(this.envConfig.processorNames), + }; + } + + public setAktenzeichen( + vorgang: VorgangWithEingangResource, + aktenzeichen: string, + ): Observable<StateResource<CommandResource>> { + const createCommand = { order: CommandOrder.SET_AKTENZEICHEN, body: { aktenzeichen } }; + return this.commandService.createCommand( + vorgang, + VorgangWithEingangLinkRel.SET_AKTENZEICHEN, + createCommand, + ); + } } diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.util.spec.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.util.spec.ts index 6ba9a7051c2d6e5794682208f813207515911e71..776eb27881031345d454185f5566d9d8036e61a8 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.util.spec.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.util.spec.ts @@ -22,129 +22,141 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { CommandOrder, CreateCommand } from '@alfa-client/command-shared'; -import { createVorgangForwardRequest, createVorgangListResource } from 'libs/vorgang-shared/test/vorgang'; +import { + createVorgangForwardRequest, + createVorgangListResource, +} from 'libs/vorgang-shared/test/vorgang'; import { VorgangListLinkRel } from './vorgang.linkrel'; import { ForwardRequest, VorgangResource } from './vorgang.model'; -import { createAbschliessenCommand, createAnnehmenCommand, createAssignUserCommand, createBearbeitenCommand, createBescheidenCommand, createForwardCommand, createProcessVorgangCommand, createVerwerfenCommand, createZurueckholenCommand, createZurueckstellenCommand, getVorgaengeFromList } from './vorgang.util'; +import { + createAbschliessenCommand, + createAnnehmenCommand, + createAssignUserCommand, + createBearbeitenCommand, + createBescheidenCommand, + createForwardCommand, + createProcessVorgangCommand, + createVerwerfenCommand, + createZurueckholenCommand, + createZurueckstellenCommand, + getVorgaengeFromList, +} from './vorgang.util'; import faker from '@faker-js/faker'; describe('VorgangUtil', () => { + describe('create ZurueckholenCommand', () => { + it('should return command', () => { + const command: CreateCommand = createZurueckholenCommand(); + + expect(command.order).toBe(CommandOrder.VORGANG_ZURUECKHOLEN); + }); + }); + + describe('create AnnehmenCommand', () => { + it('should return command', () => { + const command: CreateCommand = createAnnehmenCommand(); - describe('create ZurueckholenCommand', () => { + expect(command.order).toBe(CommandOrder.VORGANG_ANNEHMEN); + }); + }); - it('should return command', () => { - const command: CreateCommand = createZurueckholenCommand(); + describe('create VerwerfenCommand', () => { + it('should return command', () => { + const command: CreateCommand = createVerwerfenCommand(); - expect(command.order).toBe(CommandOrder.VORGANG_ZURUECKHOLEN); - }) - }) + expect(command.order).toBe(CommandOrder.VORGANG_VERWERFEN); + }); + }); - describe('create AnnehmenCommand', () => { + describe('create BearbeitenCommand', () => { + it('should return command', () => { + const command: CreateCommand = createBearbeitenCommand(); - it('should return command', () => { - const command: CreateCommand = createAnnehmenCommand(); + expect(command.order).toBe(CommandOrder.VORGANG_BEARBEITEN); + }); + }); - expect(command.order).toBe(CommandOrder.VORGANG_ANNEHMEN); - }) - }) + describe('create BescheidenCommand', () => { + it('should return command', () => { + const command: CreateCommand = createBescheidenCommand(); - describe('create VerwerfenCommand', () => { + expect(command.order).toBe(CommandOrder.VORGANG_BESCHEIDEN); + }); + }); - it('should return command', () => { - const command: CreateCommand = createVerwerfenCommand(); + describe('create ZurückstellenCommand', () => { + it('should return command', () => { + const command: CreateCommand = createZurueckstellenCommand(); - expect(command.order).toBe(CommandOrder.VORGANG_VERWERFEN); - }) - }) + expect(command.order).toBe(CommandOrder.VORGANG_ZURUECKSTELLEN); + }); + }); - describe('create BearbeitenCommand', () => { + describe('create AbschliessenCommand', () => { + it('should return command', () => { + const command: CreateCommand = createAbschliessenCommand(); - it('should return command', () => { - const command: CreateCommand = createBearbeitenCommand(); + expect(command.order).toBe(CommandOrder.VORGANG_ABSCHLIESSEN); + }); + }); - expect(command.order).toBe(CommandOrder.VORGANG_BEARBEITEN); - }) - }) + describe('create ForwardCommand', () => { + it('should return command', () => { + const forwardRequest: ForwardRequest = createVorgangForwardRequest(); - describe('create BescheidenCommand', () => { + const result: CreateCommand = createForwardCommand(forwardRequest); - it('should return command', () => { - const command: CreateCommand = createBescheidenCommand(); + expect(result).toEqual({ + order: CommandOrder.REDIRECT_VORGANG, + redirectRequest: forwardRequest, + body: null, + }); + }); + }); - expect(command.order).toBe(CommandOrder.VORGANG_BESCHEIDEN); - }) - }) + describe('getVorgaengeFromList', () => { + it('should return empty array on null', () => { + const result: VorgangResource[] = getVorgaengeFromList(null); - describe('create ZurückstellenCommand', () => { + expect(result.length).toBe(0); + }); - it('should return command', () => { - const command: CreateCommand = createZurueckstellenCommand(); + it('should return content as array', () => { + const result: VorgangResource[] = getVorgaengeFromList( + createVorgangListResource([VorgangListLinkRel.VORGANG_HEADER_LIST]), + ); - expect(command.order).toBe(CommandOrder.VORGANG_ZURUECKSTELLEN); - }) - }) + expect(result.length).toBe(10); + }); + }); - describe('create AbschliessenCommand', () => { + describe('create createAssignUserCommand', () => { + const userProfileUri: string = faker.internet.url(); - it('should return command', () => { - const command: CreateCommand = createAbschliessenCommand(); + it('should return command', () => { + const result: CreateCommand = createAssignUserCommand(userProfileUri); - expect(command.order).toBe(CommandOrder.VORGANG_ABSCHLIESSEN); - }) - }) + expect(result).toEqual({ + order: CommandOrder.ASSIGN_USER, + body: { assignedTo: userProfileUri }, + }); + }); + }); - describe('create ForwardCommand', () => { + describe('create createProcessVorgangCommand', () => { + it('should have order', () => { + const command: CreateCommand = createProcessVorgangCommand([]); - it('should return command', () => { - const forwardRequest: ForwardRequest = createVorgangForwardRequest(); + expect(command.order).toBe(CommandOrder.PROCESS_VORGANG); + }); - const result: CreateCommand = createForwardCommand(forwardRequest); + it('should have processorNames', () => { + const processorNames: string[] = ['dummyProcessorName']; - expect(result).toEqual({ order: CommandOrder.REDIRECT_VORGANG, redirectRequest: forwardRequest, body: null }) - }) - }) + const command: CreateCommand = createProcessVorgangCommand(processorNames); - describe('getVorgaengeFromList', () => { - - it('should return empty array on null', () => { - const result: VorgangResource[] = getVorgaengeFromList(null); - - expect(result.length).toBe(0); - }) - - it('should return content as array', () => { - const result: VorgangResource[] = getVorgaengeFromList(createVorgangListResource([VorgangListLinkRel.VORGANG_HEADER_LIST])); - - expect(result.length).toBe(10); - }) - }) - - describe('create createAssignUserCommand', () => { - - const userProfileUri: string = faker.internet.url(); - - it('should return command', () => { - const result: CreateCommand = createAssignUserCommand(userProfileUri); - - expect(result).toEqual({ order: CommandOrder.ASSIGN_USER, body: { assignedTo: userProfileUri } }) - }) - }) - - describe('create createProcessVorgangCommand', () => { - - it('should have order', () => { - const command: CreateCommand = createProcessVorgangCommand([]); - - expect(command.order).toBe(CommandOrder.PROCESS_VORGANG); - }) - - it('should have processorNames', () => { - const processorNames: string[] = ['dummyProcessorName']; - - const command: CreateCommand = createProcessVorgangCommand(processorNames); - - expect(command.body.processorNames).toBe(processorNames); - }) - }) -}) \ No newline at end of file + expect(command.body.processorNames).toBe(processorNames); + }); + }); +}); diff --git a/alfa-client/libs/vorgang-shared/src/lib/vorgang.util.ts b/alfa-client/libs/vorgang-shared/src/lib/vorgang.util.ts index 8c8c7add2de7c18a8aede6d26ec01cdc6495aa24..5b1eab0037409caa86f309d707b3bfa35ccf8749 100644 --- a/alfa-client/libs/vorgang-shared/src/lib/vorgang.util.ts +++ b/alfa-client/libs/vorgang-shared/src/lib/vorgang.util.ts @@ -26,74 +26,83 @@ import { EMPTY_ARRAY, isNotNil } from '@alfa-client/tech-shared'; import { ResourceUri, getEmbeddedResource } from '@ngxp/rest'; import { isNull } from 'lodash-es'; import { VorgangListLinkRel } from './vorgang.linkrel'; -import { CreateAssignUserCommand, CreateForwardCommand, ForwardRequest, VorgangListResource, VorgangResource } from './vorgang.model'; +import { + CreateAssignUserCommand, + CreateForwardCommand, + ForwardRequest, + VorgangListResource, + VorgangResource, +} from './vorgang.model'; export function createZurueckholenCommand(): CreateCommand { - return { order: CommandOrder.VORGANG_ZURUECKHOLEN, body: null }; + return { order: CommandOrder.VORGANG_ZURUECKHOLEN, body: null }; } export function createAnnehmenCommand(): CreateCommand { - return { order: CommandOrder.VORGANG_ANNEHMEN, body: null }; + return { order: CommandOrder.VORGANG_ANNEHMEN, body: null }; } export function createVerwerfenCommand(): CreateCommand { - return { order: CommandOrder.VORGANG_VERWERFEN, body: null }; + return { order: CommandOrder.VORGANG_VERWERFEN, body: null }; } export function createBearbeitenCommand(): CreateCommand { - return { order: CommandOrder.VORGANG_BEARBEITEN, body: null }; + return { order: CommandOrder.VORGANG_BEARBEITEN, body: null }; } export function createBescheidenCommand(): CreateCommand { - return { order: CommandOrder.VORGANG_BESCHEIDEN, body: null }; + return { order: CommandOrder.VORGANG_BESCHEIDEN, body: null }; } export function createZurueckstellenCommand(): CreateCommand { - return { order: CommandOrder.VORGANG_ZURUECKSTELLEN, body: null }; + return { order: CommandOrder.VORGANG_ZURUECKSTELLEN, body: null }; } export function createAbschliessenCommand(): CreateCommand { - return { order: CommandOrder.VORGANG_ABSCHLIESSEN, body: null }; + return { order: CommandOrder.VORGANG_ABSCHLIESSEN, body: null }; } export function createWiedereroeffnenCommand(): CreateCommand { - return { order: CommandOrder.VORGANG_WIEDEREROEFFNEN, body: null }; + return { order: CommandOrder.VORGANG_WIEDEREROEFFNEN, body: null }; } export function createForwardCommand(redirectRequest: ForwardRequest): CreateForwardCommand { - return { order: CommandOrder.REDIRECT_VORGANG, redirectRequest, body: null }; + return { order: CommandOrder.REDIRECT_VORGANG, redirectRequest, body: null }; } export function getVorgaengeFromList(vorgangList: VorgangListResource): VorgangResource[] { - if (isNotNil(vorgangList)) { - const embeddedResource: VorgangResource[] = getEmbeddedResource(vorgangList, VorgangListLinkRel.VORGANG_HEADER_LIST); - return isNull(embeddedResource) ? EMPTY_ARRAY : embeddedResource; - } - return EMPTY_ARRAY; + if (isNotNil(vorgangList)) { + const embeddedResource: VorgangResource[] = getEmbeddedResource( + vorgangList, + VorgangListLinkRel.VORGANG_HEADER_LIST, + ); + return isNull(embeddedResource) ? EMPTY_ARRAY : embeddedResource; + } + return EMPTY_ARRAY; } export function createAssignUserCommand(assignedTo: ResourceUri): CreateAssignUserCommand { - return { order: CommandOrder.ASSIGN_USER, body: { assignedTo } }; + return { order: CommandOrder.ASSIGN_USER, body: { assignedTo } }; } export function isStatusCommand(order: CommandOrder): boolean { - return [ - CommandOrder.VORGANG_ANNEHMEN, - CommandOrder.VORGANG_BEARBEITEN, - CommandOrder.VORGANG_BESCHEIDEN, - CommandOrder.VORGANG_ABSCHLIESSEN, - CommandOrder.VORGANG_VERWERFEN, - CommandOrder.VORGANG_WIEDEREROEFFNEN, - CommandOrder.VORGANG_ZURUECKHOLEN, - CommandOrder.VORGANG_ZURUECKSTELLEN, - CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN - ].includes(order); + return [ + CommandOrder.VORGANG_ANNEHMEN, + CommandOrder.VORGANG_BEARBEITEN, + CommandOrder.VORGANG_BESCHEIDEN, + CommandOrder.VORGANG_ABSCHLIESSEN, + CommandOrder.VORGANG_VERWERFEN, + CommandOrder.VORGANG_WIEDEREROEFFNEN, + CommandOrder.VORGANG_ZURUECKHOLEN, + CommandOrder.VORGANG_ZURUECKSTELLEN, + CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN, + ].includes(order); } export function isAssignUserCommand(order: CommandOrder): boolean { - return order === CommandOrder.ASSIGN_USER; + return order === CommandOrder.ASSIGN_USER; } export function createProcessVorgangCommand(processorNames: string[]): CreateCommand { - return { order: CommandOrder.PROCESS_VORGANG, body: { processorNames } }; -} \ No newline at end of file + return { order: CommandOrder.PROCESS_VORGANG, body: { processorNames } }; +} diff --git a/alfa-client/libs/vorgang-shared/src/test-setup.ts b/alfa-client/libs/vorgang-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/vorgang-shared/src/test-setup.ts +++ b/alfa-client/libs/vorgang-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/vorgang-shared/test/vorgang.ts b/alfa-client/libs/vorgang-shared/test/vorgang.ts index 954e8df9f53cb3db1671b9edfe7785aa6cbcad57..743c5e65339cfc65091a3db158cdbf8664863b3c 100644 --- a/alfa-client/libs/vorgang-shared/test/vorgang.ts +++ b/alfa-client/libs/vorgang-shared/test/vorgang.ts @@ -22,130 +22,153 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { faker } from '@faker-js/faker'; -import { Antragsteller, ByStatus, Eingang, EingangHeader, ForwardRequest, Vorgang, VorgangListLinkRel, VorgangListResource, VorgangResource, VorgangStatistic, VorgangStatus, VorgangWithEingang, VorgangWithEingangResource, ZustaendigeStelle } from '@alfa-client/vorgang-shared'; +import { + Antragsteller, + ByStatus, + Eingang, + EingangHeader, + ForwardRequest, + Vorgang, + VorgangListLinkRel, + VorgangListResource, + VorgangResource, + VorgangStatistic, + VorgangStatus, + VorgangWithEingang, + VorgangWithEingangResource, + ZustaendigeStelle, +} from '@alfa-client/vorgang-shared'; import { toResource } from 'libs/tech-shared/test/resource'; import { times } from 'lodash-es'; export function createVorgang(): Vorgang { - return { - createdAt: faker.date.past(), - name: faker.lorem.word(), - status: faker.helpers.arrayElement([VorgangStatus.NEU, VorgangStatus.ABGESCHLOSSEN, VorgangStatus.BESCHIEDEN, VorgangStatus.VERWORFEN]), - aktenzeichen: faker.lorem.word(), - nummer: faker.lorem.word(), - nextFrist: faker.date.future(), - hasPostfachNachricht: faker.datatype.boolean(), - hasNewPostfachNachricht: faker.datatype.boolean() - } + return { + createdAt: faker.date.past(), + name: faker.lorem.word(), + status: faker.helpers.arrayElement([ + VorgangStatus.NEU, + VorgangStatus.ABGESCHLOSSEN, + VorgangStatus.BESCHIEDEN, + VorgangStatus.VERWORFEN, + ]), + aktenzeichen: faker.lorem.word(), + nummer: faker.lorem.word(), + nextFrist: faker.date.future(), + hasPostfachNachricht: faker.datatype.boolean(), + hasNewPostfachNachricht: faker.datatype.boolean(), + }; } export function createVorgangWithEingang(): VorgangWithEingang { - return { ...createVorgangResource(), eingang: createEingang() } + return { ...createVorgangResource(), eingang: createEingang() }; } export function createEingang(): Eingang { - return { - id: faker.datatype.uuid(), - antragsteller: createAntragsteller(), - zustaendigeStelle: createZustaendigeStelle(), - header: createHeader(), - formData: {}, - numberOfAttachments: getRandomNumber(1, 10), - numberOfRepresentations: getRandomNumber(1, 10), - } + return { + id: faker.datatype.uuid(), + antragsteller: createAntragsteller(), + zustaendigeStelle: createZustaendigeStelle(), + header: createHeader(), + formData: {}, + numberOfAttachments: getRandomNumber(1, 10), + numberOfRepresentations: getRandomNumber(1, 10), + }; } function getRandomNumber(min: number, max: number): number { - return faker.datatype.number({ 'min': min, 'max': max }); + return faker.datatype.number({ min: min, max: max }); } export function createAntragsteller(): Antragsteller { - return { - anrede: faker.lorem.word(), - geburtsdatum: faker.date.past().toDateString(), - geburtsname: faker.name.findName(), - geburtsort: faker.address.city(), - nachname: faker.name.lastName(), - vorname: faker.name.firstName(), - email: faker.internet.email(), - telefon: `+ ${faker.datatype.number(10)}`, - strasse: faker.address.streetName(), - hausnummer: `${faker.datatype.number(2)}a`, - plz: faker.address.countryCode(), - ort: faker.address.city(), - otherData: new Map() - } + return { + anrede: faker.lorem.word(), + geburtsdatum: faker.date.past().toDateString(), + geburtsname: faker.name.findName(), + geburtsort: faker.address.city(), + nachname: faker.name.lastName(), + vorname: faker.name.firstName(), + email: faker.internet.email(), + telefon: `+ ${faker.datatype.number(10)}`, + strasse: faker.address.streetName(), + hausnummer: `${faker.datatype.number(2)}a`, + plz: faker.address.countryCode(), + ort: faker.address.city(), + otherData: new Map(), + }; } export function createZustaendigeStelle(): ZustaendigeStelle { - return { - email: faker.internet.email() - } + return { + email: faker.internet.email(), + }; } export function createHeader(): EingangHeader { - return { - client: faker.lorem.word(), - clientId: faker.lorem.word(), - createdAt: faker.date.past().toDateString(), - customer: faker.lorem.word(), - customerId: faker.lorem.word(), - formId: faker.lorem.word(), - formName: faker.lorem.word(), - requestId: faker.lorem.word(), - sender: faker.lorem.word() - } + return { + client: faker.lorem.word(), + clientId: faker.lorem.word(), + createdAt: faker.date.past().toDateString(), + customer: faker.lorem.word(), + customerId: faker.lorem.word(), + formId: faker.lorem.word(), + formName: faker.lorem.word(), + requestId: faker.lorem.word(), + sender: faker.lorem.word(), + }; } export function createVorgangResource(linkRelations: string[] = []): VorgangResource { - return toResource(createVorgang(), linkRelations); + return toResource(createVorgang(), linkRelations); } export function createVorgangResources(linkRelations: string[] = []): VorgangResource[] { - return times(10, () => toResource(createVorgangResource(), [...linkRelations])); + return times(10, () => toResource(createVorgangResource(), [...linkRelations])); } export function createVorgangListResource(linkRelations: string[] = []): VorgangListResource { - return toResource({}, [...linkRelations], { - [VorgangListLinkRel.VORGANG_HEADER_LIST]: createVorgangResources([...linkRelations]) - }); + return toResource({}, [...linkRelations], { + [VorgangListLinkRel.VORGANG_HEADER_LIST]: createVorgangResources([...linkRelations]), + }); } - -export function createVorgangListResourceWithResource(resources: VorgangResource[], linkRelations: string[] = []): VorgangListResource { - return toResource({}, [...linkRelations], { - [VorgangListLinkRel.VORGANG_HEADER_LIST]: resources - }); +export function createVorgangListResourceWithResource( + resources: VorgangResource[], + linkRelations: string[] = [], +): VorgangListResource { + return toResource({}, [...linkRelations], { + [VorgangListLinkRel.VORGANG_HEADER_LIST]: resources, + }); } export function createVorgangStatistic(): VorgangStatistic { - return { - byStatus: createByStatus(), - wiedervorlagen: faker.datatype.number(), - existsWiedervorlageOverdue: false - }; + return { + byStatus: createByStatus(), + wiedervorlagen: faker.datatype.number(), + existsWiedervorlageOverdue: false, + }; } function createByStatus(): ByStatus { - return { - neu: faker.datatype.number(), - angenommen: faker.datatype.number(), - inBearbeitung: faker.datatype.number(), - beschieden: faker.datatype.number(), - abgeschlossen: faker.datatype.number(), - verworfen: faker.datatype.number(), - zuLoeschen: faker.datatype.number() - }; + return { + neu: faker.datatype.number(), + angenommen: faker.datatype.number(), + inBearbeitung: faker.datatype.number(), + beschieden: faker.datatype.number(), + abgeschlossen: faker.datatype.number(), + verworfen: faker.datatype.number(), + zuLoeschen: faker.datatype.number(), + }; } - -export function createVorgangWithEingangResource(linkRelations: string[] = []): VorgangWithEingangResource { - return toResource(createVorgangWithEingang(), linkRelations); +export function createVorgangWithEingangResource( + linkRelations: string[] = [], +): VorgangWithEingangResource { + return toResource(createVorgangWithEingang(), linkRelations); } export function createVorgangForwardRequest(): ForwardRequest { - return { - email: faker.internet.email(), - password: faker.internet.password() - } -} \ No newline at end of file + return { + email: faker.internet.email(), + password: faker.internet.password(), + }; +} diff --git a/alfa-client/libs/vorgang-shared/tsconfig.json b/alfa-client/libs/vorgang-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/vorgang-shared/tsconfig.json +++ b/alfa-client/libs/vorgang-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/vorgang-shared/tsconfig.lib.json b/alfa-client/libs/vorgang-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/vorgang-shared/tsconfig.lib.json +++ b/alfa-client/libs/vorgang-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/vorgang-shared/tsconfig.spec.json b/alfa-client/libs/vorgang-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/vorgang-shared/tsconfig.spec.json +++ b/alfa-client/libs/vorgang-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/vorgang/.eslintrc.json b/alfa-client/libs/vorgang/.eslintrc.json index 1681527f0b138727d0dd82a17172e50509baaf65..07ceb6eb1f7d34299016dadeedc8f8546f74158e 100644 --- a/alfa-client/libs/vorgang/.eslintrc.json +++ b/alfa-client/libs/vorgang/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": "../../.eslintrc.json", - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": "../../.eslintrc.json", + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/vorgang/jest.config.ts b/alfa-client/libs/vorgang/jest.config.ts index 76bf56f75c05d445d435c00c2d8829f8a8a59e82..8251d25b469793eed1cc51902d0fae7c49a101e8 100644 --- a/alfa-client/libs/vorgang/jest.config.ts +++ b/alfa-client/libs/vorgang/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'vorgang', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/vorgang', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'vorgang', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/vorgang', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/vorgang/project.json b/alfa-client/libs/vorgang/project.json index 375fb2b20abcd42844343ad60bf75ca080cfee10..1aa6148fe8812d74a6bcc5a67d55ee8544d56e89 100644 --- a/alfa-client/libs/vorgang/project.json +++ b/alfa-client/libs/vorgang/project.json @@ -1,34 +1,31 @@ { - "name": "vorgang", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/vorgang/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/vorgang/src/**/*.ts", - "libs/vorgang/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "options": { - "tsConfig": "libs/vorgang/tsconfig.spec.json", - "jestConfig": "libs/vorgang/jest.config.ts", - "passWithNoTests": true - }, - "outputs": ["{workspaceRoot}/coverage/libs/vorgang"] - } - }, - "generators": { - "@schematics/angular:component": { - "style": "scss" - } - }, - "tags": [] + "name": "vorgang", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/vorgang/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/vorgang/src/**/*.ts", "libs/vorgang/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "options": { + "tsConfig": "libs/vorgang/tsconfig.spec.json", + "jestConfig": "libs/vorgang/jest.config.ts", + "passWithNoTests": true + }, + "outputs": ["{workspaceRoot}/coverage/libs/vorgang"] + } + }, + "generators": { + "@schematics/angular:component": { + "style": "scss" + } + }, + "tags": [] } diff --git a/alfa-client/libs/vorgang/src/index.ts b/alfa-client/libs/vorgang/src/index.ts index ba188ab931ec8d049818851a01d77acd02f30e9d..e87a375ded7e66202e35dde49f0f92f875fed535 100644 --- a/alfa-client/libs/vorgang/src/index.ts +++ b/alfa-client/libs/vorgang/src/index.ts @@ -24,4 +24,3 @@ export * from './lib/vorgang-list-container/vorgang-list-container.component'; export * from './lib/vorgang-list-container/vorgang-list/vorgang-list.component'; export * from './lib/vorgang.module'; - diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-filter-view.guard.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-filter-view.guard.spec.ts index 64ca3c5da2f7c36df2f6e8a644db11537b4d2b51..a1b6af5bde377625e6c73d74f1244596e81a77d5 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-filter-view.guard.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-filter-view.guard.spec.ts @@ -1,5 +1,10 @@ import { TestBed } from '@angular/core/testing'; -import { ActivatedRouteSnapshot, CanActivateFn, RouterStateSnapshot, UrlSegment } from '@angular/router'; +import { + ActivatedRouteSnapshot, + CanActivateFn, + RouterStateSnapshot, + UrlSegment, +} from '@angular/router'; import { AuthService } from '@alfa-client/app-shared'; import { mock } from '@alfa-client/test-utils'; import { VorgangService } from '@alfa-client/vorgang-shared'; @@ -11,117 +16,124 @@ import * as Guard from './vorgang-filter-view.guard'; jest.mock('@angular/router', () => mockAsEsModule('@angular/router')); const next: ActivatedRouteSnapshot = {} as unknown as ActivatedRouteSnapshot; -const state: RouterStateSnapshot = { root: { url: [<UrlSegment>{}] } } as unknown as RouterStateSnapshot; - +const state: RouterStateSnapshot = { + root: { url: [<UrlSegment>{}] }, +} as unknown as RouterStateSnapshot; function mockAsEsModule(module: string) { - return { - __esModule: true, - ...jest.requireActual(module) - }; + return { + __esModule: true, + ...jest.requireActual(module), + }; } describe('vorgangFilterViewGuard', () => { - const vorgangService = mock(VorgangService); - const authService = mock(AuthService); - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - { - provide: VorgangService, - useValue: vorgangService - }, - { - provide: AuthService, - useValue: authService - } - ] - }); - - jest.spyOn(vorgangService, 'canNavigateToPathSegements').mockReturnValue(of(false)); - }); - - - it('should be created', () => { - const guard = TestBed.runInInjectionContext(() => Guard.vorgangFilterViewGuard(next, state)) as unknown as CanActivateFn; - - expect(guard).toBeTruthy(); - }); - - describe('vorgangFilterViewGuard', () => { - it('should call authService.hasNoValidToken', () => { - const spy = jest.spyOn(authService, 'hasNoValidToken'); - - TestBed.runInInjectionContext(() => Guard.vorgangFilterViewGuard(next, state)) as unknown as CanActivateFn; - - expect(spy).toHaveBeenCalled(); - }) - - describe('access token is valid', () => { - beforeEach(() => { - jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(false); - }) - - it('should call vorgangService.canNavigateToPathSegements', () => { - const spy = jest.spyOn(vorgangService, 'canNavigateToPathSegements'); - - TestBed.runInInjectionContext(() => Guard.vorgangFilterViewGuard(next, state)) as unknown as CanActivateFn; - - expect(spy).toHaveBeenCalled(); - }) - - it('should call createUrlTreeFromSnapshot', () => { - const createUrlTreeFromSnapshot = jest.spyOn(RouterHelper, 'createUrlTreeFromSnapshot'); - jest.spyOn(vorgangService, 'canNavigateToPathSegements').mockReturnValue(of(false)); - - TestBed.runInInjectionContext(() => ( - Guard.vorgangFilterViewGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe() - ) as unknown as CanActivateFn; - - expect(createUrlTreeFromSnapshot).toHaveBeenCalled(); - }) - - it.skip('should return UrlTree', (done) => { - jest.spyOn(vorgangService, 'canNavigateToPathSegements').mockReturnValue(of(false)); - - TestBed.runInInjectionContext(() => ( - Guard.vorgangFilterViewGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe( - result => { - expect(result).toBeInstanceOf(RouterHelper.UrlTree); - done(); - } - ) - ) as unknown as CanActivateFn; - - }) - - it('should return true', (done) => { - jest.spyOn(vorgangService, 'canNavigateToPathSegements').mockReturnValue(of(true)); - - TestBed.runInInjectionContext(() => ( - Guard.vorgangFilterViewGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe( - result => { - expect(result).toBeTruthy(); - done(); - } - ) - ) as unknown as CanActivateFn; - }) - - }) - - describe('access token is not valid', () => { - beforeEach(() => { - jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(true); - }) - - it('should return true', () => { - const result = TestBed.runInInjectionContext(() => Guard.vorgangFilterViewGuard(next, state)) as unknown as CanActivateFn; - - expect(result).toBeTruthy(); - }) - }) - }) - + const vorgangService = mock(VorgangService); + const authService = mock(AuthService); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + { + provide: VorgangService, + useValue: vorgangService, + }, + { + provide: AuthService, + useValue: authService, + }, + ], + }); + + jest.spyOn(vorgangService, 'canNavigateToPathSegements').mockReturnValue(of(false)); + }); + + it('should be created', () => { + const guard = TestBed.runInInjectionContext(() => + Guard.vorgangFilterViewGuard(next, state), + ) as unknown as CanActivateFn; + + expect(guard).toBeTruthy(); + }); + + describe('vorgangFilterViewGuard', () => { + it('should call authService.hasNoValidToken', () => { + const spy = jest.spyOn(authService, 'hasNoValidToken'); + + TestBed.runInInjectionContext(() => + Guard.vorgangFilterViewGuard(next, state), + ) as unknown as CanActivateFn; + + expect(spy).toHaveBeenCalled(); + }); + + describe('access token is valid', () => { + beforeEach(() => { + jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(false); + }); + + it('should call vorgangService.canNavigateToPathSegements', () => { + const spy = jest.spyOn(vorgangService, 'canNavigateToPathSegements'); + + TestBed.runInInjectionContext(() => + Guard.vorgangFilterViewGuard(next, state), + ) as unknown as CanActivateFn; + + expect(spy).toHaveBeenCalled(); + }); + + it('should call createUrlTreeFromSnapshot', () => { + const createUrlTreeFromSnapshot = jest.spyOn(RouterHelper, 'createUrlTreeFromSnapshot'); + jest.spyOn(vorgangService, 'canNavigateToPathSegements').mockReturnValue(of(false)); + + TestBed.runInInjectionContext(() => + ( + Guard.vorgangFilterViewGuard(next, state) as Observable<RouterHelper.UrlTree> + ).subscribe(), + ) as unknown as CanActivateFn; + + expect(createUrlTreeFromSnapshot).toHaveBeenCalled(); + }); + + it.skip('should return UrlTree', (done) => { + jest.spyOn(vorgangService, 'canNavigateToPathSegements').mockReturnValue(of(false)); + + TestBed.runInInjectionContext(() => + (Guard.vorgangFilterViewGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe( + (result) => { + expect(result).toBeInstanceOf(RouterHelper.UrlTree); + done(); + }, + ), + ) as unknown as CanActivateFn; + }); + + it('should return true', (done) => { + jest.spyOn(vorgangService, 'canNavigateToPathSegements').mockReturnValue(of(true)); + + TestBed.runInInjectionContext(() => + (Guard.vorgangFilterViewGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe( + (result) => { + expect(result).toBeTruthy(); + done(); + }, + ), + ) as unknown as CanActivateFn; + }); + }); + + describe('access token is not valid', () => { + beforeEach(() => { + jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(true); + }); + + it('should return true', () => { + const result = TestBed.runInInjectionContext(() => + Guard.vorgangFilterViewGuard(next, state), + ) as unknown as CanActivateFn; + + expect(result).toBeTruthy(); + }); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-filter-view.guard.ts b/alfa-client/libs/vorgang/src/lib/vorgang-filter-view.guard.ts index 684654a2df055f073be8c13f1693a3f5d52ed3ab..6dc1095bece6ae636636c07df10660f502a0022a 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-filter-view.guard.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-filter-view.guard.ts @@ -22,20 +22,30 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { inject } from '@angular/core'; -import { ActivatedRouteSnapshot, CanActivateFn, RouterStateSnapshot, createUrlTreeFromSnapshot } from '@angular/router'; +import { + ActivatedRouteSnapshot, + CanActivateFn, + RouterStateSnapshot, + createUrlTreeFromSnapshot, +} from '@angular/router'; import { AuthService } from '@alfa-client/app-shared'; import { ALLE_ROUTE_PARAM, VorgangService } from '@alfa-client/vorgang-shared'; import { map } from 'rxjs'; -export const vorgangFilterViewGuard: CanActivateFn = (next: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { - const vorgangService = inject(VorgangService) - const authService = inject(AuthService); +export const vorgangFilterViewGuard: CanActivateFn = ( + next: ActivatedRouteSnapshot, + state: RouterStateSnapshot, +) => { + const vorgangService = inject(VorgangService); + const authService = inject(AuthService); - if (authService.hasNoValidToken()) { - return true; - } + if (authService.hasNoValidToken()) { + return true; + } - return vorgangService.canNavigateToPathSegements(state.url).pipe( - map(hasLink => hasLink ? true : createUrlTreeFromSnapshot(next, ['/', ALLE_ROUTE_PARAM])) - ); + return vorgangService + .canNavigateToPathSegements(state.url) + .pipe( + map((hasLink) => (hasLink ? true : createUrlTreeFromSnapshot(next, ['/', ALLE_ROUTE_PARAM]))), + ); }; diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.html index 6effb6866d198965b5d6e209dfa8f5b1594ebc89..cf927e2bacf4d6005e3200b3bbcd87a79736ba74 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.html @@ -23,19 +23,21 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ng-container class="list" *ngIf="{ - vorgaenge: vorgaenge$ | async, - vorgangListPageResource: vorgangListPageResource$ | async - } as vorgangListData"> - - <alfa-vorgang-list - class="l-scroll-area--full" - [vorgangListPageResource]="vorgangListData.vorgangListPageResource" - [vorgaenge]="vorgangListData.vorgaenge" - [searchString]="searchString$ | async" - [apiRootStateResource]="apiRootStateResource$ | async" - (nextPage)="loadNextPage()" - data-test-id="vorgang-list"> - </alfa-vorgang-list> - +<ng-container + class="list" + *ngIf="{ + vorgaenge: vorgaenge$ | async, + vorgangListPageResource: vorgangListPageResource$ | async + } as vorgangListData" +> + <alfa-vorgang-list + class="l-scroll-area--full" + [vorgangListPageResource]="vorgangListData.vorgangListPageResource" + [vorgaenge]="vorgangListData.vorgaenge" + [searchString]="searchString$ | async" + [apiRootStateResource]="apiRootStateResource$ | async" + (nextPage)="loadNextPage()" + data-test-id="vorgang-list" + > + </alfa-vorgang-list> </ng-container> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.scss index fa9adb8102de18d014deee2f304c37a0b039d480..9a08a5aabce6cc4cdbb268c4190a8d67f82f19e5 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.scss @@ -20,4 +20,4 @@ * ausdrücklich oder stillschweigend - verbreitet. * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. - */ \ No newline at end of file + */ diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.spec.ts index 143bff2dbb546f4609491f2842dc22ef53408150..274ee0f1deb6fccd28aaa7354b845b09e54296d9 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.spec.ts @@ -32,75 +32,73 @@ import { VorgangListContainerComponent } from './vorgang-list-container.componen import { VorgangListComponent } from './vorgang-list/vorgang-list.component'; describe('VorgangListContainerComponent', () => { - let component: VorgangListContainerComponent; - let fixture: ComponentFixture<VorgangListContainerComponent>; - - const searchString: string = EMPTY_STRING; - const apiRootService: Mock<ApiRootService> = mock(ApiRootService); - const vorgangListService = { ...mock(VorgangListService), getSearchString: jest.fn().mockReturnValue(of(searchString)) }; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangListContainerComponent, - MockComponent(VorgangListComponent) - ], - providers: [ - { - provide: ApiRootService, - useValue: apiRootService - }, - { - provide: VorgangListService, - useValue: vorgangListService - } - ] - }) - }); - - beforeEach(() => { - fixture = TestBed.createComponent(VorgangListContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call apiRootService to get apiRoot', () => { - component.ngOnInit(); - - expect(apiRootService.getApiRoot).toHaveBeenCalled(); - }) - - it('should call vorgang list service to get vorgaenge', () => { - component.ngOnInit(); - - expect(vorgangListService.getVorgaenge).toHaveBeenCalled(); - }) - - it('should call vorgang list service to get vorgangList', () => { - component.ngOnInit(); - - expect(vorgangListService.getVorgangList).toHaveBeenCalled(); - }) - - it('should call vorgang list service to get searchString', () => { - component.ngOnInit(); - - expect(vorgangListService.getSearchString).toHaveBeenCalled(); - }) - }) - - describe('load next page', () => { - - it('should call facade loadNextPage', () => { - component.loadNextPage(); - - expect(vorgangListService.loadNextPage).toHaveBeenCalled(); - }) - }) + let component: VorgangListContainerComponent; + let fixture: ComponentFixture<VorgangListContainerComponent>; + + const searchString: string = EMPTY_STRING; + const apiRootService: Mock<ApiRootService> = mock(ApiRootService); + const vorgangListService = { + ...mock(VorgangListService), + getSearchString: jest.fn().mockReturnValue(of(searchString)), + }; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VorgangListContainerComponent, MockComponent(VorgangListComponent)], + providers: [ + { + provide: ApiRootService, + useValue: apiRootService, + }, + { + provide: VorgangListService, + useValue: vorgangListService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangListContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call apiRootService to get apiRoot', () => { + component.ngOnInit(); + + expect(apiRootService.getApiRoot).toHaveBeenCalled(); + }); + + it('should call vorgang list service to get vorgaenge', () => { + component.ngOnInit(); + + expect(vorgangListService.getVorgaenge).toHaveBeenCalled(); + }); + + it('should call vorgang list service to get vorgangList', () => { + component.ngOnInit(); + + expect(vorgangListService.getVorgangList).toHaveBeenCalled(); + }); + + it('should call vorgang list service to get searchString', () => { + component.ngOnInit(); + + expect(vorgangListService.getSearchString).toHaveBeenCalled(); + }); + }); + + describe('load next page', () => { + it('should call facade loadNextPage', () => { + component.loadNextPage(); + + expect(vorgangListService.loadNextPage).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.ts index 2c0835d3c03dbed459d4696882bbd05ca12829d9..bb74408f3ca0a4cb49eab1831cbc25c171929914 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list-container.component.ts @@ -24,33 +24,39 @@ import { Component, OnInit } from '@angular/core'; import { ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared'; import { StateResource } from '@alfa-client/tech-shared'; -import { VorgangListResource, VorgangListService, VorgangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangListResource, + VorgangListService, + VorgangResource, +} from '@alfa-client/vorgang-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-list-container', - templateUrl: './vorgang-list-container.component.html', - styleUrls: ['./vorgang-list-container.component.scss'] + selector: 'alfa-vorgang-list-container', + templateUrl: './vorgang-list-container.component.html', + styleUrls: ['./vorgang-list-container.component.scss'], }) export class VorgangListContainerComponent implements OnInit { + public apiRootStateResource$: Observable<StateResource<ApiRootResource>>; - public apiRootStateResource$: Observable<StateResource<ApiRootResource>>; + public vorgangListPageResource$: Observable<StateResource<VorgangListResource>>; + public vorgaenge$: Observable<VorgangResource[]>; + public searchString$: Observable<string>; - public vorgangListPageResource$: Observable<StateResource<VorgangListResource>>; - public vorgaenge$: Observable<VorgangResource[]> - public searchString$: Observable<string>; + constructor( + private vorgangListService: VorgangListService, + private apiRootService: ApiRootService, + ) {} - constructor(private vorgangListService: VorgangListService, private apiRootService: ApiRootService) { } + ngOnInit(): void { + this.apiRootStateResource$ = this.apiRootService.getApiRoot(); - ngOnInit(): void { - this.apiRootStateResource$ = this.apiRootService.getApiRoot(); + this.vorgaenge$ = this.vorgangListService.getVorgaenge(); + this.vorgangListPageResource$ = this.vorgangListService.getVorgangList(); + this.searchString$ = this.vorgangListService.getSearchString(); + } - this.vorgaenge$ = this.vorgangListService.getVorgaenge(); - this.vorgangListPageResource$ = this.vorgangListService.getVorgangList(); - this.searchString$ = this.vorgangListService.getSearchString(); - } - - loadNextPage(): void { - this.vorgangListService.loadNextPage(); - } + loadNextPage(): void { + this.vorgangListService.loadNextPage(); + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.html index e3cea44fcda5a845f769580c91435ba15e6ace27..73e479922ecc7ce9a6a1512263e624b4325ad828 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.html @@ -24,10 +24,10 @@ --> <div role="status" aria-live="assertive" *ngIf="searchString; else emptyDatabase"> - <h3 data-test-id="empty-list-text">Es wurden keine Treffer für „{{ searchString }}“ gefunden</h3> - <p>Versuchen Sie es mit einem anderen Suchbegriff oder prüfen Sie die Schreibweise.</p> + <h3 data-test-id="empty-list-text">Es wurden keine Treffer für „{{ searchString }}“ gefunden</h3> + <p>Versuchen Sie es mit einem anderen Suchbegriff oder prüfen Sie die Schreibweise.</p> </div> <ng-template #emptyDatabase> - <h3 data-test-id="empty-database-text">Es sind keine Vorgänge vorhanden</h3> -</ng-template> \ No newline at end of file + <h3 data-test-id="empty-database-text">Es sind keine Vorgänge vorhanden</h3> +</ng-template> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.scss index 96f1bfbdc782eb6b7daeabe9527f630edb7da0e9..536fd860a7e00090aac1b7868250154e178dbbea 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.scss @@ -22,11 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: block; - padding: 24px 32px; + display: block; + padding: 24px 32px; } h3 { - font-size: 18px; - margin-bottom: 4px; + font-size: 18px; + margin-bottom: 4px; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.spec.ts index 165796ee68288cefac7d67386909ef15329e1888..4e75ae44631868edf08281b05e17eeb38cb7d06b 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.spec.ts @@ -27,44 +27,42 @@ import { EmptyListComponent } from './empty-list.component'; import { of } from 'rxjs'; describe('EmptyListComponent', () => { - let component: EmptyListComponent; - let fixture: ComponentFixture<EmptyListComponent>; + let component: EmptyListComponent; + let fixture: ComponentFixture<EmptyListComponent>; - const emptyDatabaseText: string = '[data-test-id="empty-database-text"]'; - const emptyListText: string = '[data-test-id="empty-list-text"]'; + const emptyDatabaseText: string = '[data-test-id="empty-database-text"]'; + const emptyListText: string = '[data-test-id="empty-list-text"]'; + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [EmptyListComponent], + }).compileComponents(); + }); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [EmptyListComponent] - }) - .compileComponents(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(EmptyListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(EmptyListComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + describe('should show', () => { + it('empty database text', () => { + const element = fixture.nativeElement.querySelector(emptyDatabaseText); - describe('should show', () => { - it('empty database text', () => { - const element = fixture.nativeElement.querySelector(emptyDatabaseText); + expect(element).toBeInstanceOf(HTMLElement); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) + it('empty list when searched', () => { + component.searchString = 'aktenzeichen'; + fixture.detectChanges(); - it('empty list when searched', () => { - component.searchString = 'aktenzeichen'; - fixture.detectChanges(); + const element = fixture.nativeElement.querySelector(emptyListText); - const element = fixture.nativeElement.querySelector(emptyListText); - - expect(element).toBeInstanceOf(HTMLElement); - }) - }) + expect(element).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.ts index 17b24322895a12881f0025169ecb68c0e171f884..81f4f0a5c7f3246e105afae9e29944af730c59c1 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/empty-list/empty-list.component.ts @@ -24,11 +24,10 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'alfa-empty-list', - templateUrl: './empty-list.component.html', - styleUrls: ['./empty-list.component.scss'] + selector: 'alfa-empty-list', + templateUrl: './empty-list.component.html', + styleUrls: ['./empty-list.component.scss'], }) export class EmptyListComponent { - - @Input() searchString: string; + @Input() searchString: string; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.html index daff9aa1838baed19bf19203157b659139bc8c02..406066f022f4c800e5ab1e5500ee1c97dd010876 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.html @@ -23,7 +23,7 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<div matTooltip="Eingang: {{vorgang.createdAt | formatDateWithTimePipe }}"> - <mat-icon svgIcon="incoming"></mat-icon> - <span data-test-id="created-at">{{ vorgang.createdAt | formatDateWithoutYearWithTime }}</span> +<div matTooltip="Eingang: {{ vorgang.createdAt | formatDateWithTimePipe }}"> + <mat-icon svgIcon="incoming"></mat-icon> + <span data-test-id="created-at">{{ vorgang.createdAt | formatDateWithoutYearWithTime }}</span> </div> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.scss index d708e2e398703649ea6e44516a9533c452136f54..f427af13731ee317d2eb28d9b836d7436c9a8ff3 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.scss @@ -22,11 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ div { - display: flex; - align-items: center; - white-space: nowrap; + display: flex; + align-items: center; + white-space: nowrap; } mat-icon { - margin-right: 6px; + margin-right: 6px; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.spec.ts index 5877a0be2d6f092e4bd4d89fd531aafd8bce81d8..fe86ab911f7be375089bdf63f8c35b0d9cae286c 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.spec.ts @@ -26,7 +26,11 @@ import localeDe from '@angular/common/locales/de'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatIcon } from '@angular/material/icon'; import { MatIconTestingModule } from '@angular/material/icon/testing'; -import { FormatDateWithTimePipe, FormatDateWithoutYearWithTimePipe, formatDateWithoutYearWithTime } from '@alfa-client/tech-shared'; +import { + FormatDateWithTimePipe, + FormatDateWithoutYearWithTimePipe, + formatDateWithoutYearWithTime, +} from '@alfa-client/tech-shared'; import { getElementFromFixture } from '@alfa-client/test-utils'; import { VorgangResource } from '@alfa-client/vorgang-shared'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -37,43 +41,40 @@ import { VorgangCreatedAtComponent } from './vorgang-created-at.component'; registerLocaleData(localeDe); describe('VorgangCreatedAtComponent', () => { - let component: VorgangCreatedAtComponent; - let fixture: ComponentFixture<VorgangCreatedAtComponent>; + let component: VorgangCreatedAtComponent; + let fixture: ComponentFixture<VorgangCreatedAtComponent>; - const vorgang: VorgangResource = createVorgangResource(); - const createdAt: string = getDataTestIdOf('created-at'); + const vorgang: VorgangResource = createVorgangResource(); + const createdAt: string = getDataTestIdOf('created-at'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MatIcon, - MatTooltipDirective, - FormatDateWithoutYearWithTimePipe, - FormatDateWithTimePipe, - VorgangCreatedAtComponent - ], - imports: [ - MatIconTestingModule - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + MatIcon, + MatTooltipDirective, + FormatDateWithoutYearWithTimePipe, + FormatDateWithTimePipe, + VorgangCreatedAtComponent, + ], + imports: [MatIconTestingModule], + }).compileComponents(); - fixture = TestBed.createComponent(VorgangCreatedAtComponent); - component = fixture.componentInstance; - component.vorgang = vorgang; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(VorgangCreatedAtComponent); + component = fixture.componentInstance; + component.vorgang = vorgang; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('created-at', () => { - it('should show vorgang.createdAt', () => { - const text: HTMLElement = getElementFromFixture(fixture, createdAt); - const vorgangCreatedAtFormatted: string = formatDateWithoutYearWithTime(vorgang.createdAt); - - expect(text.textContent).toBe(vorgangCreatedAtFormatted); - }); - }); + describe('created-at', () => { + it('should show vorgang.createdAt', () => { + const text: HTMLElement = getElementFromFixture(fixture, createdAt); + const vorgangCreatedAtFormatted: string = formatDateWithoutYearWithTime(vorgang.createdAt); + expect(text.textContent).toBe(vorgangCreatedAtFormatted); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.ts index a7bae205dbbf8ce86df6573e550e91a3b0e24c5a..73212315e91029635a3cba94bab1818f377a4bcf 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-created-at/vorgang-created-at.component.ts @@ -25,12 +25,10 @@ import { Component, Input } from '@angular/core'; import { VorgangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-vorgang-created-at', - templateUrl: './vorgang-created-at.component.html', - styleUrls: ['./vorgang-created-at.component.scss'], + selector: 'alfa-vorgang-created-at', + templateUrl: './vorgang-created-at.component.html', + styleUrls: ['./vorgang-created-at.component.scss'], }) export class VorgangCreatedAtComponent { - - @Input() vorgang: VorgangResource; - + @Input() vorgang: VorgangResource; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.html index 3c7d3096c197d259cd7bbb915d254a9d9c9e0247..c1f10059b3e808a0d4f1f5686c47071801e6c898 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.html @@ -23,43 +23,59 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<a class="list-item" [attr.aria-label]="ariaLabel" - routerLink="/vorgang/{{ vorgang | toResourceUri: vorgangLinkRel.VORGANG_WITH_EINGANG }}" - [attr.data-test-id]="'vorgang-list-item-' + vorgang.name | convertForDataTest"> +<a + class="list-item" + [attr.aria-label]="ariaLabel" + routerLink="/vorgang/{{ vorgang | toResourceUri: vorgangLinkRel.VORGANG_WITH_EINGANG }}" + [attr.data-test-id]="'vorgang-list-item-' + vorgang.name | convertForDataTest" +> + <div class="status"> + <alfa-vorgang-status-dot + [status]="vorgang.status" + diameter="12" + data-test-class="status-dot" + class="status-dot" + ></alfa-vorgang-status-dot> - <div class="status"> - <alfa-vorgang-status-dot [status]="vorgang.status" diameter="12" data-test-class="status-dot" - class="status-dot"></alfa-vorgang-status-dot> + <alfa-vorgang-status-text + [status]="vorgang.status" + data-test-class="status-text" + class="status-text" + ></alfa-vorgang-status-text> + </div> - <alfa-vorgang-status-text [status]="vorgang.status" data-test-class="status-text" - class="status-text"></alfa-vorgang-status-text> - </div> + <ozgcloud-postfach-icon + data-test-class="postfach-icon" + *ngIf="vorgang.hasPostfachNachricht === true" + [showBadge]="vorgang.hasNewPostfachNachricht" + class="postfach-icon" + > + </ozgcloud-postfach-icon> - <ozgcloud-postfach-icon data-test-class="postfach-icon" - *ngIf="vorgang.hasPostfachNachricht === true" - [showBadge]="vorgang.hasNewPostfachNachricht" - class="postfach-icon"> - </ozgcloud-postfach-icon> + <alfa-vorgang-created-at class="eingang" [vorgang]="vorgang"></alfa-vorgang-created-at> - <alfa-vorgang-created-at class="eingang" [vorgang]="vorgang"></alfa-vorgang-created-at> + <div class="name"> + <div class="ellipsis">{{ vorgang.name }}</div> + </div> - <div class="name"> - <div class="ellipsis">{{ vorgang.name }}</div> - </div> + <alfa-vorgang-nummer class="vorgang-nummer" [vorgang]="vorgang"></alfa-vorgang-nummer> - <alfa-vorgang-nummer class="vorgang-nummer" [vorgang]="vorgang"></alfa-vorgang-nummer> + <div class="aktenzeichen"> + <mat-icon svgIcon="az"></mat-icon> + <span class="ellipsis" alfa-aktenzeichen [vorgang]="vorgang"></span> + </div> - <div class="aktenzeichen"> - <mat-icon svgIcon="az"></mat-icon> - <span class="ellipsis" alfa-aktenzeichen [vorgang]="vorgang"></span> - </div> + <alfa-vorgang-next-frist-button + *ngIf="vorgang | hasLink: vorgangLinkRel.WIEDERVORLAGEN" + [vorgang]="vorgang" + class="wiedervorlagen" + ></alfa-vorgang-next-frist-button> - <alfa-vorgang-next-frist-button *ngIf="vorgang | hasLink: vorgangLinkRel.WIEDERVORLAGEN" [vorgang]="vorgang" - class="wiedervorlagen"></alfa-vorgang-next-frist-button> - - <alfa-user-profile-in-vorgang-list-item-container *ngIf="vorgang | hasLink: vorgangLinkRel.ASSIGN" - data-test-id="vorgang-user-icon" - [vorgang]="vorgang" - class="user-icon"> - </alfa-user-profile-in-vorgang-list-item-container> + <alfa-user-profile-in-vorgang-list-item-container + *ngIf="vorgang | hasLink: vorgangLinkRel.ASSIGN" + data-test-id="vorgang-user-icon" + [vorgang]="vorgang" + class="user-icon" + > + </alfa-user-profile-in-vorgang-list-item-container> </a> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.scss index 58f2e62534d96ddfa365d3ae4b2b1c2e1c802513..d39ab32c6e605324286c3b4dae3c994647abb8cb 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.scss @@ -26,118 +26,125 @@ @import 'variables'; .list-item { - display: grid; - grid-template-columns: 35fr 15fr 40fr 10fr; - grid-template-areas: - "status postfach-icon wiedervorlagen eingang" - "name name name name" - "vorgang-nummer vorgang-nummer aktenzeichen user-icon"; - gap: 8px; - align-items: center; - padding: 16px 24px; + display: grid; + grid-template-columns: 35fr 15fr 40fr 10fr; + grid-template-areas: + 'status postfach-icon wiedervorlagen eingang' + 'name name name name' + 'vorgang-nummer vorgang-nummer aktenzeichen user-icon'; + gap: 8px; + align-items: center; + padding: 16px 24px; - .status { - grid-area: status; - display: flex; - align-items: center; - } - .postfach-icon { - grid-area: postfach-icon; - display: flex; - align-items: center; - } - .wiedervorlagen { - grid-area: wiedervorlagen; - white-space: nowrap; - } - .eingang { - grid-area: eingang; - justify-self: end; - } - .name { - grid-area: name; - } - .aktenzeichen { - grid-area: aktenzeichen; - display: flex; - align-items: center; - mat-icon { - min-height: 1.5rem; - min-width: 1.5rem; - } - } - .vorgang-nummer { - grid-area: vorgang-nummer; - } - .user-icon { - grid-area: user-icon; - justify-self: end; - align-self: center; - } + .status { + grid-area: status; + display: flex; + align-items: center; + } + .postfach-icon { + grid-area: postfach-icon; + display: flex; + align-items: center; + } + .wiedervorlagen { + grid-area: wiedervorlagen; + white-space: nowrap; + } + .eingang { + grid-area: eingang; + justify-self: end; + } + .name { + grid-area: name; + } + .aktenzeichen { + grid-area: aktenzeichen; + display: flex; + align-items: center; + mat-icon { + min-height: 1.5rem; + min-width: 1.5rem; + } + } + .vorgang-nummer { + grid-area: vorgang-nummer; + } + .user-icon { + grid-area: user-icon; + justify-self: end; + align-self: center; + } - @include media('>desktop') { - grid-template-columns: 23fr 25fr 30fr 12fr 10fr; - grid-template-areas: - "status postfach-icon vorgang-nummer eingang user-icon" - "name name aktenzeichen wiedervorlagen user-icon"; - padding: 16px 24px; + @include media('>desktop') { + grid-template-columns: 23fr 25fr 30fr 12fr 10fr; + grid-template-areas: + 'status postfach-icon vorgang-nummer eingang user-icon' + 'name name aktenzeichen wiedervorlagen user-icon'; + padding: 16px 24px; - .eingang { - justify-self: start; - } - } + .eingang { + justify-self: start; + } + } - @include media('>xxlDesktop') { - grid-template-columns: 14fr 4fr 18fr 17fr 22fr 10fr 12fr 3fr; - grid-template-areas: - "status postfach-icon name vorgang-nummer aktenzeichen wiedervorlagen eingang user-icon"; + @include media('>xxlDesktop') { + grid-template-columns: 14fr 4fr 18fr 17fr 22fr 10fr 12fr 3fr; + grid-template-areas: 'status postfach-icon name vorgang-nummer aktenzeichen wiedervorlagen eingang user-icon'; - .name { - margin-right: 24px; - } - .eingang { - justify-self: start; - } - .vorgang-nummer { - margin-right: 1rem; - } - } + .name { + margin-right: 24px; + } + .eingang { + justify-self: start; + } + .vorgang-nummer { + margin-right: 1rem; + } + } - box-shadow: inset 0 -1px 0 0 rgba(0, 0, 0, 0.08); - position: relative; - color: inherit; - text-decoration: none; - background-color: inherit; - min-width: 370px; + box-shadow: inset 0 -1px 0 0 rgba(0, 0, 0, 0.08); + position: relative; + color: inherit; + text-decoration: none; + background-color: inherit; + min-width: 370px; - &:hover, - &:focus-within { - box-shadow: inset 0 -1px 0 0 rgba(0, 0, 0, 0.16), inset 1px 0 0 rgba(0, 0, 0, 0.16), inset -1px 0 0 rgba(0, 0, 0, 0.16), 0 1px 2px 1px rgba(0, 0, 0, 0.08); - z-index: 1; - outline: 0; - } + &:hover, + &:focus-within { + box-shadow: + inset 0 -1px 0 0 rgba(0, 0, 0, 0.16), + inset 1px 0 0 rgba(0, 0, 0, 0.16), + inset -1px 0 0 rgba(0, 0, 0, 0.16), + 0 1px 2px 1px rgba(0, 0, 0, 0.08); + z-index: 1; + outline: 0; + } - > * { - min-width: 0px; - } + > * { + min-width: 0px; + } } -body.dark :host .list-item { - box-shadow: inset 0 -1px 0 0 rgba(255, 255, 255, 0.08); - &:hover, - &:focus-within { - box-shadow: inset 0 -1px 0 0 rgba(255, 255, 255, 0.16), inset 1px 0 0 rgba(255, 255, 255, 0.16), inset -1px 0 0 rgba(255, 255, 255, 0.16), 0 1px 2px 1px rgba(255, 255, 255, 0.16); - z-index: 1; - outline: 0; - } +body.dark :host .list-item { + box-shadow: inset 0 -1px 0 0 rgba(255, 255, 255, 0.08); + &:hover, + &:focus-within { + box-shadow: + inset 0 -1px 0 0 rgba(255, 255, 255, 0.16), + inset 1px 0 0 rgba(255, 255, 255, 0.16), + inset -1px 0 0 rgba(255, 255, 255, 0.16), + 0 1px 2px 1px rgba(255, 255, 255, 0.16); + z-index: 1; + outline: 0; + } } .ellipsis { - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } mat-icon { - margin-right: 4px; + margin-right: 4px; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.spec.ts index 4a79c1070a7c961b7e8baa91355c25dd60a7e3e6..383ed79eee5197d452a13b09a1f5a9cd421fd5ac 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.spec.ts @@ -30,12 +30,23 @@ import { MAT_DATE_LOCALE } from '@angular/material/core'; import { MatIcon } from '@angular/material/icon'; import { MatIconTestingModule } from '@angular/material/icon/testing'; import { RouterTestingModule } from '@angular/router/testing'; -import { ConvertForDataTestPipe, EnumToLabelPipe, HasLinkPipe, ToResourceUriPipe, convertForDataTest } from '@alfa-client/tech-shared'; +import { + ConvertForDataTestPipe, + EnumToLabelPipe, + HasLinkPipe, + ToResourceUriPipe, + convertForDataTest, +} from '@alfa-client/tech-shared'; import { getElementFromFixture } from '@alfa-client/test-utils'; import { PostfachIconComponent } from '@alfa-client/ui'; import { UserProfileInVorgangListItemContainerComponent } from '@alfa-client/user-profile'; import { VorgangHeaderLinkRel } from '@alfa-client/vorgang-shared'; -import { AktenzeichenComponent, VorgangNummerComponent, VorgangStatusDotComponent, VorgangStatusTextComponent } from '@alfa-client/vorgang-shared-ui'; +import { + AktenzeichenComponent, + VorgangNummerComponent, + VorgangStatusDotComponent, + VorgangStatusTextComponent, +} from '@alfa-client/vorgang-shared-ui'; import { WiedervorlageListInVorgangListContainerComponent } from '@alfa-client/wiedervorlage'; import { getDataTestClassOf, getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MatTooltipDirective } from 'libs/ui/src/lib/ui/mattooltip/mattooltip.directive'; @@ -48,160 +59,181 @@ import { VorgangNextFristButton } from './vorgang-next-frist-button/vorgang-next registerLocaleData(localeDe, 'de', localeDeExtra); describe('VorgangListItemComponent', () => { - let component: VorgangListItemComponent; - let fixture: ComponentFixture<VorgangListItemComponent>; - - const user: string = getDataTestIdOf('vorgang-user-icon'); - const postfachStatus: string = getDataTestClassOf('postfach-icon'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - RouterTestingModule, - MatIconTestingModule - ], - declarations: [ - VorgangListItemComponent, - MatIcon, - MatTooltipDirective, - EnumToLabelPipe, - ToResourceUriPipe, - HasLinkPipe, - ConvertForDataTestPipe, - MockComponent(AktenzeichenComponent), - MockComponent(VorgangNummerComponent), - MockComponent(PostfachIconComponent), - MockComponent(VorgangStatusDotComponent), - MockComponent(VorgangStatusTextComponent), - MockComponent(WiedervorlageListInVorgangListContainerComponent), - MockComponent(VorgangNextFristButton), - MockComponent(UserProfileInVorgangListItemContainerComponent), - MockComponent(VorgangCreatedAtComponent) - ], - providers: [ - { provide: LOCALE_ID, useValue: 'de' }, - { provide: MAT_DATE_LOCALE, useValue: 'de-DE' } - ], - }) - }); - - beforeEach(() => { - fixture = TestBed.createComponent(VorgangListItemComponent); - component = fixture.componentInstance; - component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('bearbeiter/user-icon', () => { - - it('should be visible', () => { - component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, VorgangHeaderLinkRel.ASSIGN]); - fixture.detectChanges(); - - const userElement = fixture.nativeElement.querySelector(user); - - expect(userElement).toBeInstanceOf(HTMLElement); - }) - - it('should NOT be visible', () => { - component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]); - fixture.detectChanges(); - - const userElement = fixture.nativeElement.querySelector(user); - - expect(userElement).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('Aria label', () => { - it('should contain Wiedervorlage', () => { - component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, VorgangHeaderLinkRel.WIEDERVORLAGEN]); - const listItem: string = getDataTestIdOf(`vorgang-list-item-${convertForDataTest(component.vorgang.name)}`); - component.ngOnInit(); - fixture.detectChanges(); - - const element: HTMLDivElement = fixture.nativeElement.querySelector(listItem); - const ariaLabel: string = element.getAttribute('aria-label'); - - expect(ariaLabel).toContain('Wiedervorlage'); - }) - - it('should not contain Wiedervorlage if no nextFrist but LinkRel.WIEDERVORLAGEN', () => { - component.vorgang = { ...createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, VorgangHeaderLinkRel.WIEDERVORLAGEN]), nextFrist: null }; - const listItem: string = getDataTestIdOf(`vorgang-list-item-${convertForDataTest(component.vorgang.name)}`); - component.ngOnInit(); - fixture.detectChanges(); - - const element: HTMLDivElement = fixture.nativeElement.querySelector(listItem); - const ariaLabel: string = element.getAttribute('aria-label'); - - expect(ariaLabel).not.toContain('Wiedervorlage'); - }) - - it('should not contain Wiedervorlage if no LinkRel.WIEDERVORLAGEN', () => { - component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]); - const listItem: string = getDataTestIdOf(`vorgang-list-item-${convertForDataTest(component.vorgang.name)}`); - component.ngOnInit(); - fixture.detectChanges(); - - const element: HTMLDivElement = fixture.nativeElement.querySelector(listItem); - const ariaLabel: string = element.getAttribute('aria-label'); - - expect(ariaLabel).not.toContain('Wiedervorlage'); - }) - - it('should contain hasPostfachnachricht text if vorgang has Postfachnachricht', () => { - component.vorgang.hasPostfachNachricht = true; - component.vorgang.hasNewPostfachNachricht = false; - const listItem: string = getDataTestIdOf(`vorgang-list-item-${convertForDataTest(component.vorgang.name)}`); - component.ngOnInit(); - fixture.detectChanges(); - - const element: HTMLDivElement = fixture.nativeElement.querySelector(listItem); - const ariaLabel: string = element.getAttribute('aria-label'); - - expect(ariaLabel).toContain('enthält Postfachnachrichten'); - }) - - it('should contain hasNewPostfachnachricht text if vorgang has new Postfachnachricht', () => { - component.vorgang.hasPostfachNachricht = true; - component.vorgang.hasNewPostfachNachricht = true; - const listItem: string = getDataTestIdOf(`vorgang-list-item-${convertForDataTest(component.vorgang.name)}`); - component.ngOnInit(); - fixture.detectChanges(); - - const element: HTMLDivElement = fixture.nativeElement.querySelector(listItem); - const ariaLabel: string = element.getAttribute('aria-label'); - - expect(ariaLabel).toContain('enthält neue Postfachnachrichten'); - }) - }) - - describe('mail icon', () => { - beforeEach(() => { - component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, VorgangHeaderLinkRel.POSTFACH_MAILS]); - }) - - it('should show mail icon if Vorgang has new Postfachnachricht', () => { - component.vorgang.hasPostfachNachricht = true; - fixture.detectChanges(); - - const statusElement = getElementFromFixture(fixture, postfachStatus); - - expect(statusElement).toBeInstanceOf(HTMLElement); - }) - - it('should not show mail icon if Vorgang has no new Postfachnachricht', () => { - component.vorgang.hasPostfachNachricht = false; - fixture.detectChanges(); - - const statusElement = getElementFromFixture(fixture, postfachStatus); - - expect(statusElement).not.toBeInstanceOf(HTMLElement); - }) - }) + let component: VorgangListItemComponent; + let fixture: ComponentFixture<VorgangListItemComponent>; + + const user: string = getDataTestIdOf('vorgang-user-icon'); + const postfachStatus: string = getDataTestClassOf('postfach-icon'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [RouterTestingModule, MatIconTestingModule], + declarations: [ + VorgangListItemComponent, + MatIcon, + MatTooltipDirective, + EnumToLabelPipe, + ToResourceUriPipe, + HasLinkPipe, + ConvertForDataTestPipe, + MockComponent(AktenzeichenComponent), + MockComponent(VorgangNummerComponent), + MockComponent(PostfachIconComponent), + MockComponent(VorgangStatusDotComponent), + MockComponent(VorgangStatusTextComponent), + MockComponent(WiedervorlageListInVorgangListContainerComponent), + MockComponent(VorgangNextFristButton), + MockComponent(UserProfileInVorgangListItemContainerComponent), + MockComponent(VorgangCreatedAtComponent), + ], + providers: [ + { provide: LOCALE_ID, useValue: 'de' }, + { provide: MAT_DATE_LOCALE, useValue: 'de-DE' }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangListItemComponent); + component = fixture.componentInstance; + component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('bearbeiter/user-icon', () => { + it('should be visible', () => { + component.vorgang = createVorgangResource([ + VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, + VorgangHeaderLinkRel.ASSIGN, + ]); + fixture.detectChanges(); + + const userElement = fixture.nativeElement.querySelector(user); + + expect(userElement).toBeInstanceOf(HTMLElement); + }); + + it('should NOT be visible', () => { + component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]); + fixture.detectChanges(); + + const userElement = fixture.nativeElement.querySelector(user); + + expect(userElement).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('Aria label', () => { + it('should contain Wiedervorlage', () => { + component.vorgang = createVorgangResource([ + VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, + VorgangHeaderLinkRel.WIEDERVORLAGEN, + ]); + const listItem: string = getDataTestIdOf( + `vorgang-list-item-${convertForDataTest(component.vorgang.name)}`, + ); + component.ngOnInit(); + fixture.detectChanges(); + + const element: HTMLDivElement = fixture.nativeElement.querySelector(listItem); + const ariaLabel: string = element.getAttribute('aria-label'); + + expect(ariaLabel).toContain('Wiedervorlage'); + }); + + it('should not contain Wiedervorlage if no nextFrist but LinkRel.WIEDERVORLAGEN', () => { + component.vorgang = { + ...createVorgangResource([ + VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, + VorgangHeaderLinkRel.WIEDERVORLAGEN, + ]), + nextFrist: null, + }; + const listItem: string = getDataTestIdOf( + `vorgang-list-item-${convertForDataTest(component.vorgang.name)}`, + ); + component.ngOnInit(); + fixture.detectChanges(); + + const element: HTMLDivElement = fixture.nativeElement.querySelector(listItem); + const ariaLabel: string = element.getAttribute('aria-label'); + + expect(ariaLabel).not.toContain('Wiedervorlage'); + }); + + it('should not contain Wiedervorlage if no LinkRel.WIEDERVORLAGEN', () => { + component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]); + const listItem: string = getDataTestIdOf( + `vorgang-list-item-${convertForDataTest(component.vorgang.name)}`, + ); + component.ngOnInit(); + fixture.detectChanges(); + + const element: HTMLDivElement = fixture.nativeElement.querySelector(listItem); + const ariaLabel: string = element.getAttribute('aria-label'); + + expect(ariaLabel).not.toContain('Wiedervorlage'); + }); + + it('should contain hasPostfachnachricht text if vorgang has Postfachnachricht', () => { + component.vorgang.hasPostfachNachricht = true; + component.vorgang.hasNewPostfachNachricht = false; + const listItem: string = getDataTestIdOf( + `vorgang-list-item-${convertForDataTest(component.vorgang.name)}`, + ); + component.ngOnInit(); + fixture.detectChanges(); + + const element: HTMLDivElement = fixture.nativeElement.querySelector(listItem); + const ariaLabel: string = element.getAttribute('aria-label'); + + expect(ariaLabel).toContain('enthält Postfachnachrichten'); + }); + + it('should contain hasNewPostfachnachricht text if vorgang has new Postfachnachricht', () => { + component.vorgang.hasPostfachNachricht = true; + component.vorgang.hasNewPostfachNachricht = true; + const listItem: string = getDataTestIdOf( + `vorgang-list-item-${convertForDataTest(component.vorgang.name)}`, + ); + component.ngOnInit(); + fixture.detectChanges(); + + const element: HTMLDivElement = fixture.nativeElement.querySelector(listItem); + const ariaLabel: string = element.getAttribute('aria-label'); + + expect(ariaLabel).toContain('enthält neue Postfachnachrichten'); + }); + }); + + describe('mail icon', () => { + beforeEach(() => { + component.vorgang = createVorgangResource([ + VorgangHeaderLinkRel.VORGANG_WITH_EINGANG, + VorgangHeaderLinkRel.POSTFACH_MAILS, + ]); + }); + + it('should show mail icon if Vorgang has new Postfachnachricht', () => { + component.vorgang.hasPostfachNachricht = true; + fixture.detectChanges(); + + const statusElement = getElementFromFixture(fixture, postfachStatus); + + expect(statusElement).toBeInstanceOf(HTMLElement); + }); + + it('should not show mail icon if Vorgang has no new Postfachnachricht', () => { + component.vorgang.hasPostfachNachricht = false; + fixture.detectChanges(); + + const statusElement = getElementFromFixture(fixture, postfachStatus); + + expect(statusElement).not.toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.ts index 8bef47c20359ddcfecff9ca5df841b68da55e98c..a0946fa853c51210068a318821112c10c5c9bb47 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-list-item.component.ts @@ -28,50 +28,52 @@ import { getAktenzeichenText } from '@alfa-client/vorgang-shared-ui'; import { hasLink } from '@ngxp/rest'; @Component({ - selector: 'alfa-vorgang-list-item', - templateUrl: './vorgang-list-item.component.html', - styleUrls: ['./vorgang-list-item.component.scss'] + selector: 'alfa-vorgang-list-item', + templateUrl: './vorgang-list-item.component.html', + styleUrls: ['./vorgang-list-item.component.scss'], }) export class VorgangListItemComponent implements OnInit { + @Input() vorgang: VorgangResource; - @Input() vorgang: VorgangResource; + readonly vorgangLinkRel = VorgangHeaderLinkRel; - readonly vorgangLinkRel = VorgangHeaderLinkRel; + public ariaLabel: string = ''; - public ariaLabel: string = ''; + ngOnInit(): void { + this.buildAriaLabel(); + } - ngOnInit(): void { - this.buildAriaLabel(); - } + buildAriaLabel() { + const name: string = this.vorgang.name; + const aktenzeichen: string = getAktenzeichenText(this.vorgang); + const nummer: string = this.vorgang.nummer; + const status: string = this.vorgang.status; + const createdAt: string = formatToPrettyDate(this.vorgang.createdAt); - buildAriaLabel() { - const name: string = this.vorgang.name; - const aktenzeichen: string = getAktenzeichenText(this.vorgang); - const nummer: string = this.vorgang.nummer - const status: string = this.vorgang.status; - const createdAt: string = formatToPrettyDate(this.vorgang.createdAt); + this.ariaLabel = `Vorgang: ${name}, Aktenzeichen: ${aktenzeichen}, Nummer: ${nummer} Status: ${status}, Eingang: ${createdAt}`; - this.ariaLabel = `Vorgang: ${name}, Aktenzeichen: ${aktenzeichen}, Nummer: ${nummer} Status: ${status}, Eingang: ${createdAt}`; + if ( + hasLink(this.vorgang, VorgangHeaderLinkRel.WIEDERVORLAGEN) && + this.vorgang.nextFrist !== null + ) { + this.ariaLabel += this.getWiedervorlageText(); + } - if (hasLink(this.vorgang, VorgangHeaderLinkRel.WIEDERVORLAGEN) && this.vorgang.nextFrist !== null) { - this.ariaLabel += this.getWiedervorlageText(); - } + if (this.vorgang.hasPostfachNachricht) { + this.ariaLabel += this.getPostfachNachricht(); + } + } - if (this.vorgang.hasPostfachNachricht) { - this.ariaLabel += this.getPostfachNachricht(); - } - } + getWiedervorlageText(): string { + const nextFrist: string = formatToPrettyDate(this.vorgang.nextFrist); + return `, Nächste Wiedervorlage am ${nextFrist}`; + } - getWiedervorlageText(): string { - const nextFrist: string = formatToPrettyDate(this.vorgang.nextFrist); - return `, Nächste Wiedervorlage am ${nextFrist}`; - } + getPostfachNachricht() { + if (this.vorgang.hasNewPostfachNachricht) { + return ', enthält neue Postfachnachrichten'; + } - getPostfachNachricht() { - if (this.vorgang.hasNewPostfachNachricht) { - return ', enthält neue Postfachnachrichten'; - } - - return ', enthält Postfachnachrichten'; - } + return ', enthält Postfachnachrichten'; + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.html index 020ca981a9e24e13e7ff9f3c08cf5aba5c5c7740..37b136c5f1d31d7d6f21f87df330bec6cce80a9c 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.html @@ -23,18 +23,23 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<div *ngIf="vorgang.nextFrist" class="frist" - (mouseenter)="showWiedervorlagen = true" - (focusin)="showWiedervorlagen = true" - (mouseleave)="showWiedervorlagen = false" - (focusout)="showWiedervorlagen = false"> +<div + *ngIf="vorgang.nextFrist" + class="frist" + (mouseenter)="showWiedervorlagen = true" + (focusin)="showWiedervorlagen = true" + (mouseleave)="showWiedervorlagen = false" + (focusout)="showWiedervorlagen = false" +> + <div class="date" [class.red]="isOverdue" data-test-class="wiedervorlage-next-frist"> + <alfa-wiedervorlage-icon [isOverdue]="isOverdue"></alfa-wiedervorlage-icon> + <span>{{ vorgang.nextFrist | formatToPrettyDate }}</span> + </div> - <div class="date" [class.red]="isOverdue" data-test-class="wiedervorlage-next-frist"> - <alfa-wiedervorlage-icon [isOverdue]="isOverdue"></alfa-wiedervorlage-icon> - <span>{{ vorgang.nextFrist | formatToPrettyDate }}</span> - </div> - - <alfa-wiedervorlage-list-in-vorgang-list-container *ngIf="showWiedervorlagen" data-test-class="wiedervorlagen-list-in-vorgang" - [vorgang]="vorgang"> - </alfa-wiedervorlage-list-in-vorgang-list-container> + <alfa-wiedervorlage-list-in-vorgang-list-container + *ngIf="showWiedervorlagen" + data-test-class="wiedervorlagen-list-in-vorgang" + [vorgang]="vorgang" + > + </alfa-wiedervorlage-list-in-vorgang-list-container> </div> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.scss index d7ab9c858d3cde9d7532e73487c5809f8a916e72..aa806fcb134fd31ffe3294c79892fccf159157fa 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.scss @@ -26,23 +26,23 @@ @import 'variables'; .frist { - background-color: inherit; - border: 0; - padding: 0; - color: inherit; - position: relative; + background-color: inherit; + border: 0; + padding: 0; + color: inherit; + position: relative; } .date { - display: flex; - align-items: center; - white-space: nowrap; + display: flex; + align-items: center; + white-space: nowrap; } .red { - color: mat.get-color-from-palette($warnPalette, darker); + color: mat.get-color-from-palette($warnPalette, darker); } body.dark :host .red { - color: red; + color: red; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.spec.ts index c05cd06e50fc6e3c180e5786b9da3044d5886b38..fdb11dc41d8f88b720e77c67589bbbce34e1e0f6 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.spec.ts @@ -39,42 +39,40 @@ import * as dateUtil from '../../../../../../../tech-shared/src/lib/date.util'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('VorgangNextFristButton', () => { - let component: VorgangNextFristButton; - let fixture: ComponentFixture<VorgangNextFristButton>; + let component: VorgangNextFristButton; + let fixture: ComponentFixture<VorgangNextFristButton>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangNextFristButton, - FormatToPrettyDatePipe, - HasLinkPipe, - MatIcon, - MockComponent(WiedervorlageListInVorgangListContainerComponent), - MockComponent(WiedervorlageIconComponent), - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangNextFristButton, + FormatToPrettyDatePipe, + HasLinkPipe, + MatIcon, + MockComponent(WiedervorlageListInVorgangListContainerComponent), + MockComponent(WiedervorlageIconComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangNextFristButton); - component = fixture.componentInstance; - component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangNextFristButton); + component = fixture.componentInstance; + component.vorgang = createVorgangResource([VorgangHeaderLinkRel.VORGANG_WITH_EINGANG]); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('OnInit', () => { - it('should call isISODateInPast', () => { - const isISODateInPast = jest.spyOn(dateUtil, 'isISODateInPast'); + describe('OnInit', () => { + it('should call isISODateInPast', () => { + const isISODateInPast = jest.spyOn(dateUtil, 'isISODateInPast'); - component.ngOnInit(); - - expect(isISODateInPast).toHaveBeenCalledWith(component.vorgang.nextFrist); - }) - }) + component.ngOnInit(); + expect(isISODateInPast).toHaveBeenCalledWith(component.vorgang.nextFrist); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.ts index 9556121c57e1cfe3b627160fdae98dcb9271c389..f552a5b278d5b8f2b42e1e04a35eac0a18bbe27c 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list-item/vorgang-next-frist-button/vorgang-next-frist-button.component.ts @@ -26,20 +26,19 @@ import { isISODateInPast } from '@alfa-client/tech-shared'; import { VorgangHeaderLinkRel, VorgangResource } from '@alfa-client/vorgang-shared'; @Component({ - selector: 'alfa-vorgang-next-frist-button', - templateUrl: './vorgang-next-frist-button.component.html', - styleUrls: ['./vorgang-next-frist-button.component.scss'] + selector: 'alfa-vorgang-next-frist-button', + templateUrl: './vorgang-next-frist-button.component.html', + styleUrls: ['./vorgang-next-frist-button.component.scss'], }) export class VorgangNextFristButton implements OnInit { + @Input() vorgang: VorgangResource; - @Input() vorgang: VorgangResource; + public showWiedervorlagen: boolean = false; + public isOverdue: boolean; - public showWiedervorlagen: boolean = false; - public isOverdue: boolean; + readonly vorgangLinkRel = VorgangHeaderLinkRel; - readonly vorgangLinkRel = VorgangHeaderLinkRel; - - ngOnInit() { - this.isOverdue = isISODateInPast(this.vorgang.nextFrist as unknown as string); - } + ngOnInit() { + this.isOverdue = isISODateInPast(this.vorgang.nextFrist as unknown as string); + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.html index 642835db13e0b2a81a475ab824006e5ce84b01d3..c84962d134f588ad2f37c089d3154bc0eeef66a9 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.html @@ -23,16 +23,24 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-vorgang-list-item *ngFor="let vorgang of vorgaenge" [vorgang]="vorgang"></alfa-vorgang-list-item> +<alfa-vorgang-list-item + *ngFor="let vorgang of vorgaenge" + [vorgang]="vorgang" +></alfa-vorgang-list-item> <ozgcloud-spinner diameter="60" [stateResource]="vorgangListPageResource"></ozgcloud-spinner> -<ng-container *ngIf="apiRootStateResource.resource | hasLink: apiRootLinkRel.HINTS; else emptyListResult"> - <alfa-hint-container data-test-id="hint-container"></alfa-hint-container> +<ng-container + *ngIf="apiRootStateResource.resource | hasLink: apiRootLinkRel.HINTS; else emptyListResult" +> + <alfa-hint-container data-test-id="hint-container"></alfa-hint-container> </ng-container> <ng-template #emptyListResult> - <alfa-empty-list *ngIf="isEmptySearchResult()" data-test-id="empty-list" - [searchString]="searchString"> - </alfa-empty-list> + <alfa-empty-list + *ngIf="isEmptySearchResult()" + data-test-id="empty-list" + [searchString]="searchString" + > + </alfa-empty-list> </ng-template> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.scss index 24c04204766ed998da0ad8c62e8fac8e7c07a817..a2b17555d0d94935344850325dc95be4f2acd9b6 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.scss @@ -22,24 +22,23 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ cdk-virtual-scroll-viewport { - ::ng-deep { - .cdk-virtual-scroll-content-wrapper { - min-height: 100%; - width: 100%; // important for text-overflow ellipsis in vorgang-list-item - } - } + ::ng-deep { + .cdk-virtual-scroll-content-wrapper { + min-height: 100%; + width: 100%; // important for text-overflow ellipsis in vorgang-list-item + } + } } .loading { - height: 88px; - display: flex; - justify-content: center; - align-items: center; - position: relative; - background-color: inherit; + height: 88px; + display: flex; + justify-content: center; + align-items: center; + position: relative; + background-color: inherit; } - mat-spinner { - margin: 16px auto; + margin: 16px auto; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.spec.ts index 99e1e9c4b7d9179a33d542bb254fda40b360bb11..e7bedf3b1bfc4c8354a3127a663578c8354a606d 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.spec.ts @@ -25,13 +25,26 @@ import { ScrollingModule } from '@angular/cdk/scrolling'; import { ComponentFixture, TestBed } from '@angular/core/testing'; import { ApiRootLinkRel } from '@alfa-client/api-root-shared'; import { HintContainerComponent } from '@alfa-client/hint'; -import { HasLinkPipe, StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; -import { existsAsHtmlElement, getElementsFromFixture, mock, notExistsAsHtmlElement } from '@alfa-client/test-utils'; +import { + HasLinkPipe, + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; +import { + existsAsHtmlElement, + getElementsFromFixture, + mock, + notExistsAsHtmlElement, +} from '@alfa-client/test-utils'; import { VorgangListLinkRel, VorgangListResource } from '@alfa-client/vorgang-shared'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { SpinnerComponent } from 'libs/ui/src/lib/ui/spinner/spinner.component'; -import { createVorgangListResource, createVorgangResources } from 'libs/vorgang-shared/test/vorgang'; +import { + createVorgangListResource, + createVorgangResources, +} from 'libs/vorgang-shared/test/vorgang'; import { MockComponent } from 'ng-mocks'; import { EventEmitter } from 'stream'; import { EmptyListComponent } from './empty-list/empty-list.component'; @@ -39,158 +52,157 @@ import { VorgangListItemComponent } from './vorgang-list-item/vorgang-list-item. import { VorgangListComponent } from './vorgang-list.component'; describe('VorgangListComponent', () => { - let component: VorgangListComponent; - let fixture: ComponentFixture<VorgangListComponent>; + let component: VorgangListComponent; + let fixture: ComponentFixture<VorgangListComponent>; - const vorgangListItem: string = 'alfa-vorgang-list-item';//TODO durch data-test-id ersetzen - const hintContainer: string = getDataTestIdOf('hint-container'); + const vorgangListItem: string = 'alfa-vorgang-list-item'; //TODO durch data-test-id ersetzen + const hintContainer: string = getDataTestIdOf('hint-container'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - ScrollingModule - ], - declarations: [ - VorgangListComponent, - HasLinkPipe, - MockComponent(SpinnerComponent), - MockComponent(VorgangListItemComponent), - MockComponent(HintContainerComponent), - MockComponent(EmptyListComponent) - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ScrollingModule], + declarations: [ + VorgangListComponent, + HasLinkPipe, + MockComponent(SpinnerComponent), + MockComponent(VorgangListItemComponent), + MockComponent(HintContainerComponent), + MockComponent(EmptyListComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangListComponent); - component = fixture.componentInstance; - component.vorgangListPageResource = createEmptyStateResource(); - component.vorgaenge = createVorgangResources(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangListComponent); + component = fixture.componentInstance; + component.vorgangListPageResource = createEmptyStateResource(); + component.vorgaenge = createVorgangResources(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - it('should have vorgang-list-item', () => { - fixture.detectChanges(); + it('should have vorgang-list-item', () => { + fixture.detectChanges(); - const elements = getElementsFromFixture(fixture, vorgangListItem); + const elements = getElementsFromFixture(fixture, vorgangListItem); - expect(elements).toHaveLength(10); - }); + expect(elements).toHaveLength(10); + }); - describe('onWindowsScroll', () => { + describe('onWindowsScroll', () => { + beforeEach(() => { + component.loadNextPage = jest.fn(); + }); - beforeEach(() => { - component.loadNextPage = jest.fn(); - }) + it('should call loadNextPage if scrolled to bottom', () => { + component.isScrolledToBottom = jest.fn().mockReturnValue(true); - it('should call loadNextPage if scrolled to bottom', () => { - component.isScrolledToBottom = jest.fn().mockReturnValue(true); + component.onWindowScroll({}); - component.onWindowScroll({}); + expect(component.loadNextPage).toHaveBeenCalled(); + }); - expect(component.loadNextPage).toHaveBeenCalled(); - }) + it('should do nothing if NOT scrolled to bottom', () => { + component.isScrolledToBottom = jest.fn().mockReturnValue(false); - it('should do nothing if NOT scrolled to bottom', () => { - component.isScrolledToBottom = jest.fn().mockReturnValue(false); + component.onWindowScroll({}); - component.onWindowScroll({}); + expect(component.loadNextPage).not.toHaveBeenCalled(); + }); + }); - expect(component.loadNextPage).not.toHaveBeenCalled(); - }) - }) + describe('load next page', () => { + beforeEach(() => { + component.nextPage = <any>mock(EventEmitter); + }); - describe('load next page', () => { + it('should emit "nextPage" if necessary', () => { + component.shouldLoadNextPage = jest.fn().mockReturnValue(true); - beforeEach(() => { - component.nextPage = <any>mock(EventEmitter); - }) + component.loadNextPage(); - it('should emit "nextPage" if necessary', () => { - component.shouldLoadNextPage = jest.fn().mockReturnValue(true); + expect(component.nextPage.emit).toHaveBeenCalled(); + }); - component.loadNextPage(); + it('should NOT emit "nextPage"', () => { + component.shouldLoadNextPage = jest.fn().mockReturnValue(false); - expect(component.nextPage.emit).toHaveBeenCalled(); - }) + component.loadNextPage(); - it('should NOT emit "nextPage"', () => { - component.shouldLoadNextPage = jest.fn().mockReturnValue(false); + expect(component.nextPage.emit).not.toHaveBeenCalled(); + }); + }); - component.loadNextPage(); + describe('shouldLoadNextPage', () => { + const vorgangListStateResource: StateResource<VorgangListResource> = createStateResource( + createVorgangListResource([VorgangListLinkRel.NEXT]), + ); - expect(component.nextPage.emit).not.toHaveBeenCalled(); - }) - }) + it('should return true if resource is loaded', () => { + component.vorgangListPageResource = vorgangListStateResource; - describe('shouldLoadNextPage', () => { + const shouldLoadNextPage: boolean = component.shouldLoadNextPage(); - const vorgangListStateResource: StateResource<VorgangListResource> = createStateResource(createVorgangListResource([VorgangListLinkRel.NEXT])); + expect(shouldLoadNextPage).toBeTruthy(); + }); - it('should return true if resource is loaded', () => { - component.vorgangListPageResource = vorgangListStateResource; + it('should return false if resource is loading', () => { + component.vorgangListPageResource = { ...vorgangListStateResource, loading: true }; - const shouldLoadNextPage: boolean = component.shouldLoadNextPage(); + const shouldLoadNextPage: boolean = component.shouldLoadNextPage(); - expect(shouldLoadNextPage).toBeTruthy(); - }) + expect(shouldLoadNextPage).toBeFalsy(); + }); - it('should return false if resource is loading', () => { - component.vorgangListPageResource = { ...vorgangListStateResource, loading: true }; + it('should return false if resource is reload required', () => { + component.vorgangListPageResource = { ...vorgangListStateResource, reload: true }; - const shouldLoadNextPage: boolean = component.shouldLoadNextPage(); + const shouldLoadNextPage: boolean = component.shouldLoadNextPage(); - expect(shouldLoadNextPage).toBeFalsy(); - }) + expect(shouldLoadNextPage).toBeFalsy(); + }); + }); - it('should return false if resource is reload required', () => { - component.vorgangListPageResource = { ...vorgangListStateResource, reload: true }; + describe('has next page', () => { + it('should return true is link exists', () => { + component.vorgangListPageResource = createStateResource( + createVorgangListResource([VorgangListLinkRel.NEXT]), + ); - const shouldLoadNextPage: boolean = component.shouldLoadNextPage(); + const hasNextPage: boolean = component.hasNextPage(); - expect(shouldLoadNextPage).toBeFalsy(); - }) - }) + expect(hasNextPage).toBeTruthy(); + }); - describe('has next page', () => { + it('should return false if link NOT exists', () => { + component.vorgangListPageResource = createStateResource(createVorgangListResource()); - it('should return true is link exists', () => { - component.vorgangListPageResource = createStateResource(createVorgangListResource([VorgangListLinkRel.NEXT])); + const hasNextPage: boolean = component.hasNextPage(); - const hasNextPage: boolean = component.hasNextPage(); + expect(hasNextPage).toBeFalsy(); + }); + }); - expect(hasNextPage).toBeTruthy(); - }) + describe('hint container', () => { + it('should show if link exists', () => { + component.apiRootStateResource = createStateResource( + createApiRootResource([ApiRootLinkRel.HINTS]), + ); - it('should return false if link NOT exists', () => { - component.vorgangListPageResource = createStateResource(createVorgangListResource()); + fixture.detectChanges(); - const hasNextPage: boolean = component.hasNextPage(); + existsAsHtmlElement(fixture, hintContainer); + }); - expect(hasNextPage).toBeFalsy(); - }) - }) + it('should hide if link NOT exists', () => { + component.apiRootStateResource = createStateResource(createApiRootResource()); - describe('hint container', () => { + fixture.detectChanges(); - it('should show if link exists', () => { - component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.HINTS])); - - fixture.detectChanges(); - - existsAsHtmlElement(fixture, hintContainer); - }) - - it('should hide if link NOT exists', () => { - component.apiRootStateResource = createStateResource(createApiRootResource()); - - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, hintContainer); - }) - }) -}); \ No newline at end of file + notExistsAsHtmlElement(fixture, hintContainer); + }); + }); +}); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.ts index b03fe629106d07a0f63687fc12ff8ce4e6a9f300..b78a5745d7d2e89d95e0a67c40b26bc1219a3d34 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-container/vorgang-list/vorgang-list.component.ts @@ -24,67 +24,80 @@ import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core'; import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; -import { VorgangListLinkRel, VorgangListResource, VorgangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangListLinkRel, + VorgangListResource, + VorgangResource, +} from '@alfa-client/vorgang-shared'; import { hasLink } from '@ngxp/rest'; @Component({ - selector: 'alfa-vorgang-list', - templateUrl: './vorgang-list.component.html', - styleUrls: ['./vorgang-list.component.scss'] + selector: 'alfa-vorgang-list', + templateUrl: './vorgang-list.component.html', + styleUrls: ['./vorgang-list.component.scss'], }) export class VorgangListComponent { + @Input() apiRootStateResource: StateResource<ApiRootResource> = createEmptyStateResource(); - @Input() apiRootStateResource: StateResource<ApiRootResource> = createEmptyStateResource(); + @Input() vorgangListPageResource: StateResource<VorgangListResource>; + @Input() vorgaenge: VorgangResource[]; + @Input() searchString: string; - @Input() vorgangListPageResource: StateResource<VorgangListResource>; - @Input() vorgaenge: VorgangResource[]; - @Input() searchString: string; + @Output() nextPage: EventEmitter<void> = new EventEmitter<void>(); - @Output() nextPage: EventEmitter<void> = new EventEmitter<void>(); + readonly apiRootLinkRel = ApiRootLinkRel; - readonly apiRootLinkRel = ApiRootLinkRel; + @HostListener('window:scroll', ['$event']) + onWindowScroll(event) { + //TODO event typisieren?! + if (this.isScrolledToBottom(event)) { + this.loadNextPage(); + } + } - @HostListener('window:scroll', ['$event']) - onWindowScroll(event) {//TODO event typisieren?! - if (this.isScrolledToBottom(event)) { - this.loadNextPage(); - } - } + isScrolledToBottom(event): boolean { + const top = event.currentTarget.scrollY; + const height = document.documentElement.scrollHeight; + const innerHeight = event.currentTarget.innerHeight + 1; + return top >= height - innerHeight; + } - isScrolledToBottom(event): boolean { - const top = event.currentTarget.scrollY; - const height = document.documentElement.scrollHeight; - const innerHeight = event.currentTarget.innerHeight + 1; - return top >= height - innerHeight; - } + loadNextPage(): void { + if (this.shouldLoadNextPage()) { + this.nextPage.emit(); + } + } - loadNextPage(): void { - if (this.shouldLoadNextPage()) { - this.nextPage.emit(); - } - } + shouldLoadNextPage(): boolean { + return this.isVorgangListNotLoading() && this.hasNextPage(); + } - shouldLoadNextPage(): boolean { - return this.isVorgangListNotLoading() && this.hasNextPage(); - } + private isVorgangListNotLoading(): boolean { + return ( + this.vorgangListPageResource.loaded && + !this.vorgangListPageResource.loading && + !this.vorgangListPageResource.reload + ); + } - private isVorgangListNotLoading(): boolean { - return this.vorgangListPageResource.loaded && !this.vorgangListPageResource.loading && !this.vorgangListPageResource.reload; - } + hasNextPage(): boolean { + return hasLink(this.vorgangListPageResource.resource, VorgangListLinkRel.NEXT); + } - hasNextPage(): boolean { - return hasLink(this.vorgangListPageResource.resource, VorgangListLinkRel.NEXT); - } + public isEmptySearchResult(): boolean { + return this.isValidList() && this.notExistsVorgaenge(); + } - public isEmptySearchResult(): boolean { - return this.isValidList() && this.notExistsVorgaenge(); - } + private isValidList(): boolean { + return ( + !this.vorgangListPageResource.loading && + this.vorgangListPageResource.loaded && + !this.vorgangListPageResource.reload && + !this.vorgangListPageResource.hasOwnProperty('error') + ); + } - private isValidList(): boolean { - return !this.vorgangListPageResource.loading && this.vorgangListPageResource.loaded && !this.vorgangListPageResource.reload && !this.vorgangListPageResource.hasOwnProperty('error'); - } - - private notExistsVorgaenge(): boolean { - return this.vorgaenge.length === 0; - } + private notExistsVorgaenge(): boolean { + return this.vorgaenge.length === 0; + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.html index b69cc5ae0cd758b23e3604208f59e67a7346cd8e..b3b077d4ba141c153a3993b66102fa15c97bfa58 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.html @@ -23,4 +23,6 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-vorgang-list-page [apiRootStateResource]="apiRootStateResource$ | async"></alfa-vorgang-list-page> \ No newline at end of file +<alfa-vorgang-list-page + [apiRootStateResource]="apiRootStateResource$ | async" +></alfa-vorgang-list-page> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.spec.ts index df5636e4ba0ff64c570c90c53135c6745f628d88..fe7b9b866526a83af76c22255c6115d36f7e8da1 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.spec.ts @@ -29,40 +29,38 @@ import { VorgangListPageContainerComponent } from './vorgang-list-page-container import { VorgangListPageComponent } from './vorgang-list-page/vorgang-list-page.component'; describe('VorgangListPageContainerComponent', () => { - let component: VorgangListPageContainerComponent; - let fixture: ComponentFixture<VorgangListPageContainerComponent>; + let component: VorgangListPageContainerComponent; + let fixture: ComponentFixture<VorgangListPageContainerComponent>; - const apiRootFacade = mock(ApiRootFacade); + const apiRootFacade = mock(ApiRootFacade); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangListPageContainerComponent, - MockComponent(VorgangListPageComponent) - ], - providers: [{ - provide: ApiRootFacade, - useValue: apiRootFacade - }] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VorgangListPageContainerComponent, MockComponent(VorgangListPageComponent)], + providers: [ + { + provide: ApiRootFacade, + useValue: apiRootFacade, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangListPageContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangListPageContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('onInit', () => { + describe('onInit', () => { + it('should call apiRootService', () => { + component.ngOnInit(); - it('should call apiRootService', () => { - component.ngOnInit(); - - expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); - }) - }) + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.ts index de5ac9fbb3b65b9ef7e1b724504eb9601ee95f43..0d016fe26634b7767305f0868dd070ff6d7b7ab9 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page-container.component.ts @@ -27,17 +27,16 @@ import { StateResource } from '@alfa-client/tech-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-list-page-container', - templateUrl: './vorgang-list-page-container.component.html', - styleUrls: ['./vorgang-list-page-container.component.scss'], + selector: 'alfa-vorgang-list-page-container', + templateUrl: './vorgang-list-page-container.component.html', + styleUrls: ['./vorgang-list-page-container.component.scss'], }) export class VorgangListPageContainerComponent implements OnInit { + apiRootStateResource$: Observable<StateResource<ApiRootResource>>; - apiRootStateResource$: Observable<StateResource<ApiRootResource>>; + constructor(private apiRootFacade: ApiRootFacade) {} - constructor(private apiRootFacade: ApiRootFacade) { } - - ngOnInit(): void { - this.apiRootStateResource$ = this.apiRootFacade.getApiRoot(); - } -} \ No newline at end of file + ngOnInit(): void { + this.apiRootStateResource$ = this.apiRootFacade.getApiRoot(); + } +} diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.html index 481790d08648127c7ae33c745e897beed0087877..58f56ae4024f342b5829e7d0745abcaa2ad51387 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.html @@ -23,4 +23,6 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-vorgang-filter-menu [apiRootStateResource]="apiRootStateResource$ | async"></alfa-vorgang-filter-menu> +<alfa-vorgang-filter-menu + [apiRootStateResource]="apiRootStateResource$ | async" +></alfa-vorgang-filter-menu> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.scss index d36af3c57117626594f026dfbc7a047d9eeecd33..0f988dfaacd575b371c4e302f847202aa0ea8fac 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.scss @@ -24,13 +24,13 @@ @import 'variables'; :host { - position: sticky; - top: $header-height; - height: 3rem; - width: 100%; - z-index: 2; - display: flex; - justify-content: flex-end; - align-items: center; - padding: 0.25rem 0 0.25rem 1rem; -} \ No newline at end of file + position: sticky; + top: $header-height; + height: 3rem; + width: 100%; + z-index: 2; + display: flex; + justify-content: flex-end; + align-items: center; + padding: 0.25rem 0 0.25rem 1rem; +} diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.spec.ts index 28e04dfdf0386959d3a3d57ab6bef18b53be86b6..9ae7310cfdd916c109645e7e413a6d2c48ccf3f6 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.spec.ts @@ -29,42 +29,41 @@ import { VorgangFilterMenuContainerComponent } from './vorgang-filter-menu-conta import { VorgangFilterMenuComponent } from './vorgang-filter-menu/vorgang-filter-menu.component'; describe('VorgangFilterMenuContainerComponent', () => { - let component: VorgangFilterMenuContainerComponent; - let fixture: ComponentFixture<VorgangFilterMenuContainerComponent>; + let component: VorgangFilterMenuContainerComponent; + let fixture: ComponentFixture<VorgangFilterMenuContainerComponent>; - const apiRootFacade = mock(ApiRootFacade); + const apiRootFacade = mock(ApiRootFacade); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangFilterMenuContainerComponent, - MockComponent(VorgangFilterMenuComponent), - ], - providers: [ - { - provide: ApiRootFacade, - useValue: apiRootFacade - } - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangFilterMenuContainerComponent, + MockComponent(VorgangFilterMenuComponent), + ], + providers: [ + { + provide: ApiRootFacade, + useValue: apiRootFacade, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangFilterMenuContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangFilterMenuContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should call api root service', () => { + component.ngOnInit(); - it('should call api root service', () => { - component.ngOnInit(); - - expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); - }); - }) + expect(apiRootFacade.getApiRoot).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.ts index a5134010d9a12fb7cbeead27fb6611df5ac156a2..db096d14c9b5734aa16cdfd31563ea1074cc62e0 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu-container.component.ts @@ -28,18 +28,17 @@ import { Observable } from 'rxjs'; import { VorgangFilterFormService } from './vorgang-filter-menu/vorgang-filter-menu.formservice'; @Component({ - selector: 'alfa-vorgang-filter-menu-container', - templateUrl: './vorgang-filter-menu-container.component.html', - styleUrls: ['./vorgang-filter-menu-container.component.scss'], - providers:[VorgangFilterFormService] + selector: 'alfa-vorgang-filter-menu-container', + templateUrl: './vorgang-filter-menu-container.component.html', + styleUrls: ['./vorgang-filter-menu-container.component.scss'], + providers: [VorgangFilterFormService], }) export class VorgangFilterMenuContainerComponent implements OnInit { + apiRootStateResource$: Observable<StateResource<ApiRootResource>>; - apiRootStateResource$: Observable<StateResource<ApiRootResource>>; + constructor(private apiRootFacade: ApiRootFacade) {} - constructor(private apiRootFacade: ApiRootFacade) { } - - ngOnInit(): void { - this.apiRootStateResource$ = this.apiRootFacade.getApiRoot(); - } -} \ No newline at end of file + ngOnInit(): void { + this.apiRootStateResource$ = this.apiRootFacade.getApiRoot(); + } +} diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/_vorgang-filter-item.theme.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/_vorgang-filter-item.theme.scss index c571efd928b79cb23a7cd7720932ec0bbb292291..48ef0d6830ef721386845fc09f7143e3648123f4 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/_vorgang-filter-item.theme.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/_vorgang-filter-item.theme.scss @@ -23,24 +23,24 @@ */ alfa-vorgang-filter-menu { - .filter-item-content { - display: grid; - grid-auto-flow: column; - align-content: center; - justify-content: space-between; - gap: 0.5rem; - height: 2rem; + .filter-item-content { + display: grid; + grid-auto-flow: column; + align-content: center; + justify-content: space-between; + gap: 0.5rem; + height: 2rem; - mat-icon { - display: none; - } - } + mat-icon { + display: none; + } + } - .mat-button-toggle-checked .filter-item-content { - font-weight: bold; + .mat-button-toggle-checked .filter-item-content { + font-weight: bold; - mat-icon { - display: block; - } - } + mat-icon { + display: block; + } + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.html index 2842293ac9aa8e2f75e7d4e10b10b2d96573575d..8fd35cdadf9dc2da14a7b26d83425ddc55755fee 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.html @@ -1,4 +1,4 @@ <div class="filter-item-content"> - <mat-icon [inline]="true">check</mat-icon> - <span>{{label}}</span> -</div> \ No newline at end of file + <mat-icon [inline]="true">check</mat-icon> + <span>{{ label }}</span> +</div> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.spec.ts index e74a78ef4fcd1386d96b8cbb361d6cf8df9ff6ff..c3cff3c5c7f4cc9d6d7a42c89d0060244a44a2aa 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.spec.ts @@ -3,23 +3,20 @@ import { MatIcon } from '@angular/material/icon'; import { VorgangFilterMenuItemComponent } from './vorgang-filter-menu-item.component'; describe('VorgangFilterMenuItemComponent', () => { - let component: VorgangFilterMenuItemComponent; - let fixture: ComponentFixture<VorgangFilterMenuItemComponent>; + let component: VorgangFilterMenuItemComponent; + let fixture: ComponentFixture<VorgangFilterMenuItemComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangFilterMenuItemComponent, - MatIcon - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VorgangFilterMenuItemComponent, MatIcon], + }).compileComponents(); - fixture = TestBed.createComponent(VorgangFilterMenuItemComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(VorgangFilterMenuItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.ts index 52109113a1db5ff8aeb41b38379a09f59accab8a..cd21bb2c5adec22a73f94dd9c552ca3ce9a8fff1 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu-item/vorgang-filter-menu-item.component.ts @@ -3,9 +3,8 @@ import { Component, Input } from '@angular/core'; @Component({ selector: 'alfa-vorgang-filter-menu-item', templateUrl: './vorgang-filter-menu-item.component.html', - styleUrls: ['./vorgang-filter-menu-item.component.scss'] + styleUrls: ['./vorgang-filter-menu-item.component.scss'], }) export class VorgangFilterMenuItemComponent { - - @Input() label: string; + @Input() label: string; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.html index 83b9abf81c136455cc4904284bc5a0b69f07afaa..07b48c607fdd9f85ea6b988f67a9e4f69863dd9f 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.html @@ -23,16 +23,41 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<form [formGroup]="formService.form" *ngIf="multipleFilterAvailable" data-test-id="vorgang-filter-form"> - <mat-button-toggle-group [formControlName]="filterName" multiple="false"> - <mat-button-toggle *ngIf="apiRootStateResource.resource | hasLink: apiRootLinkRel.MEINE_VORGAENGE" data-test-id="meine-vorgaenge-filter-toggle-button" [value]="formService.FILTER_MEINE_VALUE"> - <alfa-vorgang-filter-menu-item label="Meine Vorgänge" data-test-id="meine-vorgaenge-filter-item"></alfa-vorgang-filter-menu-item> - </mat-button-toggle> - <mat-button-toggle *ngIf="apiRootStateResource.resource | hasLink: apiRootLinkRel.ALLE_VORGAENGE" data-test-id="alle-filter-toggle-button" [value]="formService.FILTER_ALLE_VALUE"> - <alfa-vorgang-filter-menu-item label="Alle" data-test-id="alle-filter-item"></alfa-vorgang-filter-menu-item> - </mat-button-toggle> - <mat-button-toggle *ngIf="apiRootStateResource.resource | hasLink: apiRootLinkRel.UNASSIGNED" data-test-id="nicht-zugewiesen-filter-toggle-button" [value]="formService.FILTER_UNASSIGNED_VALUE"> - <alfa-vorgang-filter-menu-item label="Nicht zugewiesen" data-test-id="unassigned-filter-toggle-button"></alfa-vorgang-filter-menu-item> - </mat-button-toggle> - </mat-button-toggle-group> -</form> \ No newline at end of file +<form + [formGroup]="formService.form" + *ngIf="multipleFilterAvailable" + data-test-id="vorgang-filter-form" +> + <mat-button-toggle-group [formControlName]="filterName" multiple="false"> + <mat-button-toggle + *ngIf="apiRootStateResource.resource | hasLink: apiRootLinkRel.MEINE_VORGAENGE" + data-test-id="meine-vorgaenge-filter-toggle-button" + [value]="formService.FILTER_MEINE_VALUE" + > + <alfa-vorgang-filter-menu-item + label="Meine Vorgänge" + data-test-id="meine-vorgaenge-filter-item" + ></alfa-vorgang-filter-menu-item> + </mat-button-toggle> + <mat-button-toggle + *ngIf="apiRootStateResource.resource | hasLink: apiRootLinkRel.ALLE_VORGAENGE" + data-test-id="alle-filter-toggle-button" + [value]="formService.FILTER_ALLE_VALUE" + > + <alfa-vorgang-filter-menu-item + label="Alle" + data-test-id="alle-filter-item" + ></alfa-vorgang-filter-menu-item> + </mat-button-toggle> + <mat-button-toggle + *ngIf="apiRootStateResource.resource | hasLink: apiRootLinkRel.UNASSIGNED" + data-test-id="nicht-zugewiesen-filter-toggle-button" + [value]="formService.FILTER_UNASSIGNED_VALUE" + > + <alfa-vorgang-filter-menu-item + label="Nicht zugewiesen" + data-test-id="unassigned-filter-toggle-button" + ></alfa-vorgang-filter-menu-item> + </mat-button-toggle> + </mat-button-toggle-group> +</form> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.scss index 4df6c83f9a1ee678d1d5dd4c35e506ccb5e42615..5b627bc13f94ebb8634f1f6040ceac8f52e54cb3 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.scss @@ -24,9 +24,9 @@ @import 'variables'; mat-button-toggle-group { - border-radius: 1rem; + border-radius: 1rem; } .mat-button-toggle-checked { - background-color: $activeButton; -} \ No newline at end of file + background-color: $activeButton; +} diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.spec.ts index b12bb9c5b26fdcff48d56a30dd18aca9a9bf11e4..fe56f2abaa2fb063ba72fb9ea4053b1a3d15df56 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.spec.ts @@ -27,7 +27,11 @@ import { MatButtonToggle, MatButtonToggleGroup } from '@angular/material/button- import { MatRipple } from '@angular/material/core'; import { ApiRootLinkRel } from '@alfa-client/api-root-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { createEmptyStateResource, createStateResource, HasLinkPipe } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + HasLinkPipe, +} from '@alfa-client/tech-shared'; import { existsAsHtmlElement, mock, notExistsAsHtmlElement } from '@alfa-client/test-utils'; import { VorgangListService } from '@alfa-client/vorgang-shared'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; @@ -40,159 +44,165 @@ import { VorgangFilterMenuComponent } from './vorgang-filter-menu.component'; import { VorgangFilterFormService } from './vorgang-filter-menu.formservice'; describe('VorgangFilterMenuComponent', () => { - let component: VorgangFilterMenuComponent; - let fixture: ComponentFixture<VorgangFilterMenuComponent>; - - const alleFilterToggleButton: string = getDataTestIdOf('alle-filter-toggle-button'); - const meineVorgaengeFilterToggleButton: string = getDataTestIdOf('meine-vorgaenge-filter-toggle-button'); - const unassignFilterToggleButton: string = getDataTestIdOf('unassigned-filter-toggle-button'); - - const form: FormGroup = new FormBuilder().group({ - filter: new FormControl() - }); - - const vorgangFilterFormService = { ...mock(VorgangFilterFormService) , form }; - const navigationService = mock(NavigationService); - const vorgangListService = mock(VorgangListService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangFilterMenuComponent, - HasLinkPipe, - ButtonToggleGroupComponent, - MatButtonToggleGroup, - MatButtonToggle, - MatRipple, - MockComponent(ButtonToggleGroupComponent), - MockComponent(ButtonToggleComponent), - MockComponent(VorgangFilterMenuItemComponent), - ], - imports: [ - ReactiveFormsModule, - ], - providers: [ - FormBuilder, - { - provide: VorgangFilterFormService, - useValue: vorgangFilterFormService - }, - { - provide: NavigationService, - useValue: navigationService - }, - { - provide: VorgangListService, - useValue: vorgangListService - } - ] - }).compileComponents(); - }); + let component: VorgangFilterMenuComponent; + let fixture: ComponentFixture<VorgangFilterMenuComponent>; + + const alleFilterToggleButton: string = getDataTestIdOf('alle-filter-toggle-button'); + const meineVorgaengeFilterToggleButton: string = getDataTestIdOf( + 'meine-vorgaenge-filter-toggle-button', + ); + const unassignFilterToggleButton: string = getDataTestIdOf('unassigned-filter-toggle-button'); + + const form: FormGroup = new FormBuilder().group({ + filter: new FormControl(), + }); + + const vorgangFilterFormService = { ...mock(VorgangFilterFormService), form }; + const navigationService = mock(NavigationService); + const vorgangListService = mock(VorgangListService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangFilterMenuComponent, + HasLinkPipe, + ButtonToggleGroupComponent, + MatButtonToggleGroup, + MatButtonToggle, + MatRipple, + MockComponent(ButtonToggleGroupComponent), + MockComponent(ButtonToggleComponent), + MockComponent(VorgangFilterMenuItemComponent), + ], + imports: [ReactiveFormsModule], + providers: [ + FormBuilder, + { + provide: VorgangFilterFormService, + useValue: vorgangFilterFormService, + }, + { + provide: NavigationService, + useValue: navigationService, + }, + { + provide: VorgangListService, + useValue: vorgangListService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(VorgangFilterMenuComponent); + component = fixture.componentInstance; + component.apiRootStateResource = createStateResource(createApiRootResource()); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('alle filter item', () => { + beforeEach(() => { + jest.spyOn(component, 'areMultipleFilterAvailable').mockReturnValue(true); + }); + + it('should show on existing links', () => { + component.apiRootStateResource = createStateResource( + createApiRootResource([ApiRootLinkRel.ALLE_VORGAENGE]), + ); + + fixture.detectChanges(); + + existsAsHtmlElement(fixture, alleFilterToggleButton); + }); + + it('should hide on missing link', () => { + component.apiRootStateResource = createStateResource(createApiRootResource()); + + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, alleFilterToggleButton); + }); + }); + + describe('meine vorgaenge filter item', () => { + beforeEach(() => { + jest.spyOn(component, 'areMultipleFilterAvailable').mockReturnValue(true); + }); + + it('should show on existing link', () => { + component.apiRootStateResource = createStateResource( + createApiRootResource([ApiRootLinkRel.MEINE_VORGAENGE]), + ); + + fixture.detectChanges(); + + existsAsHtmlElement(fixture, meineVorgaengeFilterToggleButton); + }); + + it('should hide on missing link', () => { + component.apiRootStateResource = createStateResource(createApiRootResource()); + + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, meineVorgaengeFilterToggleButton); + }); + }); + + describe('unassigned filter item', () => { + beforeEach(() => { + jest.spyOn(component, 'areMultipleFilterAvailable').mockReturnValue(true); + }); + + it('should show on existing link', () => { + component.apiRootStateResource = createStateResource( + createApiRootResource([ApiRootLinkRel.UNASSIGNED]), + ); + + fixture.detectChanges(); + + existsAsHtmlElement(fixture, unassignFilterToggleButton); + }); + + it('should hide on missing link', () => { + component.apiRootStateResource = createStateResource(createApiRootResource()); + + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, unassignFilterToggleButton); + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangFilterMenuComponent); - component = fixture.componentInstance; - component.apiRootStateResource = createStateResource(createApiRootResource()); - fixture.detectChanges(); - }); + describe('areMultipleFilterAvailable', () => { + it('should return true if more than one link', () => { + component.apiRootStateResource = createStateResource( + createApiRootResource([ApiRootLinkRel.ALLE_VORGAENGE, ApiRootLinkRel.MEINE_VORGAENGE]), + ); - it('should create', () => { - expect(component).toBeTruthy(); - }); + const result: boolean = component.areMultipleFilterAvailable(); - describe('alle filter item', () => { + expect(result).toBeTruthy(); + }); - beforeEach(() => { - jest.spyOn(component, 'areMultipleFilterAvailable').mockReturnValue(true); - }) + it('should return false if only one link', () => { + component.apiRootStateResource = createStateResource( + createApiRootResource([ApiRootLinkRel.ALLE_VORGAENGE]), + ); - it('should show on existing links', () => { - component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.ALLE_VORGAENGE])); + const result: boolean = component.areMultipleFilterAvailable(); - fixture.detectChanges(); + expect(result).toBeFalsy(); + }); - existsAsHtmlElement(fixture, alleFilterToggleButton); - }) + it('should return false if no link', () => { + component.apiRootStateResource = createEmptyStateResource(); - it('should hide on missing link', () => { - component.apiRootStateResource = createStateResource(createApiRootResource()); + const result: boolean = component.areMultipleFilterAvailable(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, alleFilterToggleButton); - }) - }) - - describe('meine vorgaenge filter item', () => { - - beforeEach(() => { - jest.spyOn(component, 'areMultipleFilterAvailable').mockReturnValue(true); - }) - - it('should show on existing link', () => { - component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.MEINE_VORGAENGE])); - - fixture.detectChanges(); - - existsAsHtmlElement(fixture, meineVorgaengeFilterToggleButton); - }) - - it('should hide on missing link', () => { - component.apiRootStateResource = createStateResource(createApiRootResource()); - - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, meineVorgaengeFilterToggleButton); - }) - }) - - describe('unassigned filter item', () => { - - beforeEach(() => { - jest.spyOn(component, 'areMultipleFilterAvailable').mockReturnValue(true); - }) - - it('should show on existing link', () => { - component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.UNASSIGNED])); - - fixture.detectChanges(); - - existsAsHtmlElement(fixture, unassignFilterToggleButton); - }) - - it('should hide on missing link', () => { - component.apiRootStateResource = createStateResource(createApiRootResource()); - - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, unassignFilterToggleButton); - }) - }) - - describe('areMultipleFilterAvailable', () => { - - it('should return true if more than one link', () => { - component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.ALLE_VORGAENGE, ApiRootLinkRel.MEINE_VORGAENGE])); - - const result: boolean = component.areMultipleFilterAvailable(); - - expect(result).toBeTruthy(); - }) - - it('should return false if only one link', () => { - component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.ALLE_VORGAENGE])); - - const result: boolean = component.areMultipleFilterAvailable(); - - expect(result).toBeFalsy(); - }) - - it('should return false if no link', () => { - component.apiRootStateResource = createEmptyStateResource(); - - const result: boolean = component.areMultipleFilterAvailable(); - - expect(result).toBeFalsy(); - }) - }) + expect(result).toBeFalsy(); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.ts index ec9e4bbe96348a398bacb0afb08d54163e93f8b1..e76fea332e106b600d005059584e041ebc5e909e 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.component.ts @@ -28,30 +28,32 @@ import { hasLink } from '@ngxp/rest'; import { VorgangFilterFormService } from './vorgang-filter-menu.formservice'; @Component({ - selector: 'alfa-vorgang-filter-menu', - templateUrl: './vorgang-filter-menu.component.html', - styleUrls: ['./vorgang-filter-menu.component.scss'], + selector: 'alfa-vorgang-filter-menu', + templateUrl: './vorgang-filter-menu.component.html', + styleUrls: ['./vorgang-filter-menu.component.scss'], }) export class VorgangFilterMenuComponent { + @Input() public set apiRootStateResource(value: StateResource<ApiRootResource>) { + this._apiRootStateResource = value; + this.multipleFilterAvailable = this.areMultipleFilterAvailable(); + } + private _apiRootStateResource: StateResource<ApiRootResource>; + public get apiRootStateResource(): StateResource<ApiRootResource> { + return this._apiRootStateResource; + } - @Input() public set apiRootStateResource(value: StateResource<ApiRootResource>) { - this._apiRootStateResource = value; - this.multipleFilterAvailable = this.areMultipleFilterAvailable(); - } - private _apiRootStateResource: StateResource<ApiRootResource>; - public get apiRootStateResource(): StateResource<ApiRootResource> { - return this._apiRootStateResource; - } + multipleFilterAvailable: boolean; - multipleFilterAvailable: boolean; + readonly apiRootLinkRel = ApiRootLinkRel; - readonly apiRootLinkRel = ApiRootLinkRel; + filterName: string = VorgangFilterFormService.FILTER; - filterName: string = VorgangFilterFormService.FILTER; + constructor(public formService: VorgangFilterFormService) {} - constructor(public formService: VorgangFilterFormService) {} - - areMultipleFilterAvailable(): boolean { - return hasLink(this.apiRootStateResource.resource, ApiRootLinkRel.ALLE_VORGAENGE) && hasLink(this.apiRootStateResource.resource, ApiRootLinkRel.MEINE_VORGAENGE); - } + areMultipleFilterAvailable(): boolean { + return ( + hasLink(this.apiRootStateResource.resource, ApiRootLinkRel.ALLE_VORGAENGE) && + hasLink(this.apiRootStateResource.resource, ApiRootLinkRel.MEINE_VORGAENGE) + ); + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.formservice.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.formservice.spec.ts index 7a1eaba546a9b4361cf3f3af51739af6b397ac84..47db98135964609899f296dc7f737498f5f7bfd9 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.formservice.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.formservice.spec.ts @@ -6,72 +6,72 @@ import { of } from 'rxjs'; import { VorgangFilterFormService } from './vorgang-filter-menu.formservice'; describe('VorgangFilterFormservice', () => { + let formService: VorgangFilterFormService; + let navigationService: Mock<NavigationService>; + let vorgangListService; - let formService: VorgangFilterFormService;; - let navigationService: Mock<NavigationService>; - let vorgangListService; + beforeEach(() => { + vorgangListService = { ...mock(VorgangListService), getSearchString: () => of('searchString') }; + navigationService = mock(NavigationService); + vorgangListService.getSelectedFilterAsRouteParam.mockReturnValue(of('alle')); - beforeEach(() => { - vorgangListService = { ...mock(VorgangListService), getSearchString: () => of('searchString') }; - navigationService = mock(NavigationService); - vorgangListService.getSelectedFilterAsRouteParam.mockReturnValue(of('alle')); + formService = new VorgangFilterFormService( + new UntypedFormBuilder(), + useFromMock(navigationService), + useFromMock(vorgangListService), + ); + }); - formService = new VorgangFilterFormService(new UntypedFormBuilder(), useFromMock(navigationService), useFromMock(vorgangListService)); - }) + it('should create', () => { + expect(formService).toBeTruthy(); + }); - it('should create', () => { - expect(formService).toBeTruthy(); - }) + describe('init', () => { + beforeEach(() => { + formService.subscribeToFilterChanges = jest.fn(); + formService.subscribeToValueChanges = jest.fn(); + }); - describe('init', () => { + it('should create filter form controls', () => { + expect(formService.form).not.toBeUndefined(); + }); - beforeEach(() => { - formService.subscribeToFilterChanges = jest.fn(); - formService.subscribeToValueChanges = jest.fn(); - }) + it('should subscribe to filter changes', () => { + formService.init(); - it('should create filter form controls', () => { - expect(formService.form).not.toBeUndefined(); - }) + expect(formService.subscribeToFilterChanges).toHaveBeenCalled(); + }); - it('should subscribe to filter changes', () => { - formService.init(); + it('should subscribe to value changes', () => { + formService.init(); - expect(formService.subscribeToFilterChanges).toHaveBeenCalled(); - }) + expect(formService.subscribeToValueChanges).toHaveBeenCalled(); + }); + }); - it('should subscribe to value changes', () => { - formService.init(); + describe('subscribe to filter changes', () => { + it('should call vorgangListService getSelectedFilterAsRouteParam', () => { + formService.subscribeToFilterChanges(); - expect(formService.subscribeToValueChanges).toHaveBeenCalled(); - }) - }) + expect(vorgangListService.getSelectedFilterAsRouteParam).toHaveBeenCalled(); + }); - describe('subscribe to filter changes', () => { + it('should patch form control value', () => { + formService.subscribeToFilterChanges(); - it('should call vorgangListService getSelectedFilterAsRouteParam', () => { - formService.subscribeToFilterChanges(); + expect(formService.form.controls['filter'].value).toEqual('alle'); + }); + }); - expect(vorgangListService.getSelectedFilterAsRouteParam).toHaveBeenCalled(); - }) + describe('subscribe to value changes', () => { + const patchedFilter: string = 'meine'; - it('should patch form control value', () => { - formService.subscribeToFilterChanges(); + it('should call navigationService navigateByFilter', () => { + formService.subscribeToValueChanges(); - expect(formService.form.controls['filter'].value).toEqual('alle'); - }) - }) + formService.form.controls['filter'].patchValue(patchedFilter); - describe('subscribe to value changes', () => { - - const patchedFilter: string = 'meine'; - - it('should call navigationService navigateByFilter', () => { - formService.subscribeToValueChanges(); - - formService.form.controls['filter'].patchValue(patchedFilter); - - expect(navigationService.navigateByFilter).toHaveBeenCalledWith(patchedFilter); - }) - }) -}) \ No newline at end of file + expect(navigationService.navigateByFilter).toHaveBeenCalledWith(patchedFilter); + }); + }); +}); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.formservice.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.formservice.ts index 87f6aaa634e66ecec06f28dc7868640a5d711b14..947202ba9902c079248cd2c182c9f8f26f3cdb26 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.formservice.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-filter-menu-container/vorgang-filter-menu/vorgang-filter-menu.formservice.ts @@ -1,65 +1,68 @@ -import { Injectable, OnDestroy } from "@angular/core"; -import { FormControl, FormGroup, UntypedFormBuilder } from "@angular/forms"; -import { NavigationService } from "@alfa-client/navigation-shared"; -import { isNotNil } from "@alfa-client/tech-shared"; -import { VorgangListService } from "@alfa-client/vorgang-shared"; -import { Subscription } from "rxjs"; +import { Injectable, OnDestroy } from '@angular/core'; +import { FormControl, FormGroup, UntypedFormBuilder } from '@angular/forms'; +import { NavigationService } from '@alfa-client/navigation-shared'; +import { isNotNil } from '@alfa-client/tech-shared'; +import { VorgangListService } from '@alfa-client/vorgang-shared'; +import { Subscription } from 'rxjs'; @Injectable() export class VorgangFilterFormService implements OnDestroy { + public form: FormGroup; - public form: FormGroup; + static readonly FILTER: string = 'filter'; - static readonly FILTER: string = 'filter'; + public readonly FILTER_ALLE_VALUE: string = 'alle'; + public readonly FILTER_MEINE_VALUE: string = 'meine'; + public readonly FILTER_UNASSIGNED_VALUE: string = 'unassigned'; - public readonly FILTER_ALLE_VALUE: string = 'alle'; - public readonly FILTER_MEINE_VALUE: string = 'meine'; - public readonly FILTER_UNASSIGNED_VALUE: string = 'unassigned'; + private subscription: Subscription; - private subscription: Subscription; + constructor( + private formBuilder: UntypedFormBuilder, + private navigationService: NavigationService, + private vorgangListService: VorgangListService, + ) { + this.init(); + } - constructor( - private formBuilder: UntypedFormBuilder, - private navigationService: NavigationService, - private vorgangListService: VorgangListService - ) { - this.init(); - } + init(): void { + this.initForm(); - init(): void { - this.initForm(); + this.subscribeToFilterChanges(); + this.subscribeToValueChanges(); + } - this.subscribeToFilterChanges(); - this.subscribeToValueChanges(); - } + private initForm(): void { + this.form = this.formBuilder.group({ + [VorgangFilterFormService.FILTER]: new FormControl(), + }); + } - private initForm(): void { - this.form = this.formBuilder.group({ - [VorgangFilterFormService.FILTER]: new FormControl() - }) - } + subscribeToFilterChanges(): void { + this.subscription = this.vorgangListService + .getSelectedFilterAsRouteParam() + .subscribe((filter: string) => this.patch(filter)); + } - subscribeToFilterChanges(): void { - this.subscription = this.vorgangListService.getSelectedFilterAsRouteParam().subscribe((filter: string) => this.patch(filter)); - } + private patch(filter: string): void { + this.getFilterControl().patchValue(filter); + } - private patch(filter: string): void { - this.getFilterControl().patchValue(filter); - } + subscribeToValueChanges(): void { + this.subscription = this.getFilterControl().valueChanges.subscribe((value) => + this.handleFilterChange(value), + ); + } - subscribeToValueChanges(): void { - this.subscription = this.getFilterControl().valueChanges.subscribe(value => this.handleFilterChange(value)); - } + private getFilterControl(): FormControl { + return <FormControl>this.form.controls[VorgangFilterFormService.FILTER]; + } - private getFilterControl(): FormControl { - return <FormControl>this.form.controls[VorgangFilterFormService.FILTER]; - } + private handleFilterChange(value: string): void { + this.navigationService.navigateByFilter(value); + } - private handleFilterChange(value: string): void { - this.navigationService.navigateByFilter(value); - } - - ngOnDestroy(): void { - if (isNotNil(this.subscription)) this.subscription.unsubscribe(); - } + ngOnDestroy(): void { + if (isNotNil(this.subscription)) this.subscription.unsubscribe(); + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.html index a92d56f6d27c506b1a63c69a5e8fdc3248423d28..919d63c150d231e1d4c3786e49a6dde286e60df4 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.html @@ -26,19 +26,31 @@ <alfa-vorgang-filter-menu-container class="mat-app-background"></alfa-vorgang-filter-menu-container> <div class="content"> - <alfa-vorgang-views-menu-container *ngIf="apiRootStateResource.resource" [apiRootResource]="apiRootStateResource.resource" class="left"></alfa-vorgang-views-menu-container> - - <main *ngIf="apiRootStateResource?.resource | hasLink: apiRootLinkRel.ALLE_VORGAENGE; else showNoRoleMessage" data-test-id="vorgaenge-list"><router-outlet></router-outlet></main> - - <ng-template #showNoRoleMessage> - <div class="l-scroll-area--full no-role-message" data-test-id="user-no-role-message"> - <h2>Es sind keine Vorgänge in Alfa verfügbar.</h2> - <p>Prüfen Sie, ob folgendes zutrifft:</p> - <ul> - <li>Es wurden keine Rollen zugewiesen.</li> - </ul> - - <p>Bitte bei der verantwortlichen Person des User-Managements bzw. des Keycloaks melden.</p> - </div> - </ng-template> -</div> \ No newline at end of file + <alfa-vorgang-views-menu-container + *ngIf="apiRootStateResource.resource" + [apiRootResource]="apiRootStateResource.resource" + class="left" + ></alfa-vorgang-views-menu-container> + + <main + *ngIf=" + apiRootStateResource?.resource | hasLink: apiRootLinkRel.ALLE_VORGAENGE; + else showNoRoleMessage + " + data-test-id="vorgaenge-list" + > + <router-outlet></router-outlet> + </main> + + <ng-template #showNoRoleMessage> + <div class="l-scroll-area--full no-role-message" data-test-id="user-no-role-message"> + <h2>Es sind keine Vorgänge in Alfa verfügbar.</h2> + <p>Prüfen Sie, ob folgendes zutrifft:</p> + <ul> + <li>Es wurden keine Rollen zugewiesen.</li> + </ul> + + <p>Bitte bei der verantwortlichen Person des User-Managements bzw. des Keycloaks melden.</p> + </div> + </ng-template> +</div> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.scss index 2cabe1996910f4d5adaacea96119fb92421bf731..4cba32fefb63db0211a5fa83d1286d6b08eea8b5 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.scss @@ -24,42 +24,42 @@ @import 'variables'; h1 { - text-align: center; - margin: 0; - padding: 1rem; + text-align: center; + margin: 0; + padding: 1rem; } .content { - display:flex; - flex-direction: row; - background-color: $background; + display: flex; + flex-direction: row; + background-color: $background; - .left { - flex: 1 0 15.5rem; - } + .left { + flex: 1 0 15.5rem; + } - main, - .no-role-message { - flex: 1 1 100%; - border: 1px solid $greyLight; - } + main, + .no-role-message { + flex: 1 1 100%; + border: 1px solid $greyLight; + } - .no-role-message { - padding: 1.5rem 2rem; - } + .no-role-message { + padding: 1.5rem 2rem; + } } :host-context(.dark) { - h1 { - background-color: $dark-background; - } + h1 { + background-color: $dark-background; + } - .content { - background-color: $dark-background; + .content { + background-color: $dark-background; - main, - .no-role-message { - border: 1px solid $dark-background; - } - } -} \ No newline at end of file + main, + .no-role-message { + border: 1px solid $dark-background; + } + } +} diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.spec.ts index e20095e8908099432c7954ea71c24ec7378ef6a5..55bc23bc751f437f5df65b8f60d12aac5f6e4808 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.spec.ts @@ -24,7 +24,11 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { ApiRootLinkRel } from '@alfa-client/api-root-shared'; -import { HasLinkPipe, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + HasLinkPipe, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { getElementFromFixture } from '@alfa-client/test-utils'; import { createApiRootResource } from 'libs/api-root-shared/test/api-root'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; @@ -34,55 +38,54 @@ import { VorgangListPageComponent } from './vorgang-list-page.component'; import { VorgangViewsMenuContainerComponent } from './vorgang-views-menu-container/vorgang-views-menu-container.component'; describe('VorgangListPageComponent', () => { - let component: VorgangListPageComponent; - let fixture: ComponentFixture<VorgangListPageComponent>; + let component: VorgangListPageComponent; + let fixture: ComponentFixture<VorgangListPageComponent>; - const userMessage: string = getDataTestIdOf('user-no-role-message'); - const vorgaengeList: string = getDataTestIdOf('vorgaenge-list'); + const userMessage: string = getDataTestIdOf('user-no-role-message'); + const vorgaengeList: string = getDataTestIdOf('vorgaenge-list'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangListPageComponent, - HasLinkPipe, - MockComponent(VorgangFilterMenuContainerComponent), - MockComponent(VorgangViewsMenuContainerComponent) - ], - imports: [ - RouterTestingModule - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangListPageComponent, + HasLinkPipe, + MockComponent(VorgangFilterMenuContainerComponent), + MockComponent(VorgangViewsMenuContainerComponent), + ], + imports: [RouterTestingModule], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(VorgangListPageComponent); - component = fixture.componentInstance; - component.apiRootStateResource = createEmptyStateResource(); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(VorgangListPageComponent); + component = fixture.componentInstance; + component.apiRootStateResource = createEmptyStateResource(); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('page', () => { + describe('page', () => { + it('should show vorgaenge if link exists', () => { + component.apiRootStateResource = createStateResource( + createApiRootResource([ApiRootLinkRel.ALLE_VORGAENGE]), + ); + fixture.detectChanges(); - it('should show vorgaenge if link exists', () => { - component.apiRootStateResource = createStateResource(createApiRootResource([ApiRootLinkRel.ALLE_VORGAENGE])); - fixture.detectChanges(); + const element = getElementFromFixture(fixture, vorgaengeList); - const element = getElementFromFixture(fixture, vorgaengeList); + expect(element).toBeInstanceOf(HTMLElement); + }); - expect(element).toBeInstanceOf(HTMLElement); - }) + it('should show hint message if link not exists', () => { + component.apiRootStateResource = createStateResource(createApiRootResource()); + fixture.detectChanges(); - it('should show hint message if link not exists', () => { - component.apiRootStateResource = createStateResource(createApiRootResource()); - fixture.detectChanges(); + const element = getElementFromFixture(fixture, userMessage); - const element = getElementFromFixture(fixture, userMessage); - - expect(element).toBeInstanceOf(HTMLElement); - }) - }) + expect(element).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.ts index 3ef55f99a26d4a6055f1af307f77f4a80a30a11b..03d9616804bc109c90792dd7bb5cb5e10bca4346 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.ts @@ -26,13 +26,12 @@ import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; import { StateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-vorgang-list-page', - templateUrl: './vorgang-list-page.component.html', - styleUrls: ['./vorgang-list-page.component.scss'] + selector: 'alfa-vorgang-list-page', + templateUrl: './vorgang-list-page.component.html', + styleUrls: ['./vorgang-list-page.component.scss'], }) export class VorgangListPageComponent { + @Input() apiRootStateResource: StateResource<ApiRootResource>; - @Input() apiRootStateResource: StateResource<ApiRootResource>; - - readonly apiRootLinkRel = ApiRootLinkRel; -} \ No newline at end of file + readonly apiRootLinkRel = ApiRootLinkRel; +} diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.html index 13fc4116569b51f130bee80d5c9582ba453cb7ac..d67d78667b5a15d2cd2f1549fbd279dfbf317f89 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.html @@ -1 +1,4 @@ -<alfa-vorgang-views-menu [apiRootResource]="apiRootResource" [vorgangStatisticStateResource]="vorgangStatisticStateResource$ | async"></alfa-vorgang-views-menu> \ No newline at end of file +<alfa-vorgang-views-menu + [apiRootResource]="apiRootResource" + [vorgangStatisticStateResource]="vorgangStatisticStateResource$ | async" +></alfa-vorgang-views-menu> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.scss index 38e77a89ab3fb2bfdc4d9c33e3425f34f74a31c8..d952c68d1953ff972cb66210cc322820ef8104b9 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.scss @@ -1,13 +1,13 @@ @import 'variables'; :host { - background-color: $background; - padding: 0 1rem 0 0; - position: sticky; - align-self: flex-start; - top: $header-height + $navigation-height; + background-color: $background; + padding: 0 1rem 0 0; + position: sticky; + align-self: flex-start; + top: $header-height + $navigation-height; } :host-context(body.dark) { - background-color: $dark-background; + background-color: $dark-background; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.spec.ts index 40f218101fe12440915ff1d77ad269ca4c8e88e2..eeee44bf7b249e0643158ade0de778093aab9ca0 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.spec.ts @@ -6,40 +6,36 @@ import { VorgangViewsMenuComponent } from '../vorgang-views-menu/vorgang-views-m import { VorgangViewsMenuContainerComponent } from './vorgang-views-menu-container.component'; describe('VorgangViewsMenuContainerComponent', () => { - let component: VorgangViewsMenuContainerComponent; - let fixture: ComponentFixture<VorgangViewsMenuContainerComponent>; - - const vorgangListService: Mock<VorgangListService> = mock(VorgangListService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangViewsMenuContainerComponent, - MockComponent(VorgangViewsMenuComponent) - ], - providers: [ - { - provide: VorgangListService, - useValue: vorgangListService - } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(VorgangViewsMenuContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call vorganglistService to get vorgangStatistic', () => { - component.ngOnInit(); - - expect(vorgangListService.getVorgangStatistic).toHaveBeenCalled(); - }) - }) + let component: VorgangViewsMenuContainerComponent; + let fixture: ComponentFixture<VorgangViewsMenuContainerComponent>; + + const vorgangListService: Mock<VorgangListService> = mock(VorgangListService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VorgangViewsMenuContainerComponent, MockComponent(VorgangViewsMenuComponent)], + providers: [ + { + provide: VorgangListService, + useValue: vorgangListService, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(VorgangViewsMenuContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call vorganglistService to get vorgangStatistic', () => { + component.ngOnInit(); + + expect(vorgangListService.getVorgangStatistic).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.ts index 73f5df56de9315fe9702107dd13456553c7b1fe7..9eb19537dd39531bec67a1c601058eaf9e9ed95e 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu-container/vorgang-views-menu-container.component.ts @@ -5,19 +5,18 @@ import { VorgangListService, VorgangStatistic } from '@alfa-client/vorgang-share import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-views-menu-container', - templateUrl: './vorgang-views-menu-container.component.html', - styleUrls: ['./vorgang-views-menu-container.component.scss'], + selector: 'alfa-vorgang-views-menu-container', + templateUrl: './vorgang-views-menu-container.component.html', + styleUrls: ['./vorgang-views-menu-container.component.scss'], }) export class VorgangViewsMenuContainerComponent implements OnInit { + @Input() apiRootResource: ApiRootResource; - @Input() apiRootResource: ApiRootResource; + vorgangStatisticStateResource$: Observable<StateResource<VorgangStatistic>>; - vorgangStatisticStateResource$: Observable<StateResource<VorgangStatistic>>; + constructor(private vorgangList: VorgangListService) {} - constructor(private vorgangList: VorgangListService){} - - ngOnInit(): void { - this.vorgangStatisticStateResource$ = this.vorgangList.getVorgangStatistic(); - } + ngOnInit(): void { + this.vorgangStatisticStateResource$ = this.vorgangList.getVorgangStatistic(); + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/_vorgang-views-menu.theme.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/_vorgang-views-menu.theme.scss index 88a0683f6d2f0f32bea5ef85f22b62598596f7f6..29b647f3a046d8af5ca31e36412e6f161b5ded4d 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/_vorgang-views-menu.theme.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/_vorgang-views-menu.theme.scss @@ -7,127 +7,127 @@ $color-config: mat.get-color-config($alfaTheme); $primary: map.get($color-config, 'primary'); alfa-vorgang-search-view-item { - mat-icon { - color: mat.get-color-from-palette($primary); - } + mat-icon { + color: mat.get-color-from-palette($primary); + } } alfa-vorgang-view-item, alfa-vorgang-search-view-item { - ozgcloud-routing-button { - .mat-mdc-button { - text-align: left; - width: 100%; - border-radius: 1rem; - font-weight: normal; - padding: 0 0.875rem; - } - - &.selected:not(:hover) .mat-mdc-button { - background-color: $activeButton; - font-weight: 500; - } - .mdc-button__label { - display: flex; - align-items: center; - width: 100%; - - .label { - flex-grow: 1; - } - } - } + ozgcloud-routing-button { + .mat-mdc-button { + text-align: left; + width: 100%; + border-radius: 1rem; + font-weight: normal; + padding: 0 0.875rem; + } + + &.selected:not(:hover) .mat-mdc-button { + background-color: $activeButton; + font-weight: 500; + } + .mdc-button__label { + display: flex; + align-items: center; + width: 100%; + + .label { + flex-grow: 1; + } + } + } } body.dark { - alfa-vorgang-view-item, - alfa-vorgang-search-view-item-container { - ozgcloud-routing-button { - &.selected:not(:hover) .mat-mdc-button { - background-color: $activeButtonDark; - } - } - } + alfa-vorgang-view-item, + alfa-vorgang-search-view-item-container { + ozgcloud-routing-button { + &.selected:not(:hover) .mat-mdc-button { + background-color: $activeButtonDark; + } + } + } } alfa-vorgang-view-item { - ozgcloud-routing-button { - .dot { - border-radius: 50%; - border: 1px solid darken(#E4E4E4, 30%); - background-color: #E4E4E4; - margin: 5px; - margin-right: 11px; - display: inline-block; - height: 0.875rem; - width: 0.875rem; - - &.neu { - background-color: #c0d1e8; - border-color: #155ab4; - } - - &.angenommen { - background-color: #f6ebce; - border-color: #f1c14e; - } - - &.in_bearbeitung { - background-color: #f6ebce; - border-color: #f1c14e; - } - - &.beschieden { - background-color: #d9eec5; - border-color: #7ccb2b; - } - - &.abgeschlossen { - background-color: #d9eec5; - border-color: #7ccb2b; - } - - &.verworfen { - background-color: #dedede; - border-color: #8e8e8f; - } - - &.zu-loeschen { - background-color: #fff; - border-color: #bbb; - } - } - - &.selected { - .dot { - &.neu { - background-color: #155ab4; - } - - &.angenommen { - background-color: #f1c14e; - } - - &.in_bearbeitung { - background-color: #f1c14e; - } - - &.beschieden { - background-color: #7ccb2b; - } - - &.abgeschlossen { - background-color: #7ccb2b; - } - - &.verworfen { - background-color: #8e8e8f; - } - - &.zu-loeschen { - background-color: #bbb; - } - } - } - } + ozgcloud-routing-button { + .dot { + border-radius: 50%; + border: 1px solid darken(#e4e4e4, 30%); + background-color: #e4e4e4; + margin: 5px; + margin-right: 11px; + display: inline-block; + height: 0.875rem; + width: 0.875rem; + + &.neu { + background-color: #c0d1e8; + border-color: #155ab4; + } + + &.angenommen { + background-color: #f6ebce; + border-color: #f1c14e; + } + + &.in_bearbeitung { + background-color: #f6ebce; + border-color: #f1c14e; + } + + &.beschieden { + background-color: #d9eec5; + border-color: #7ccb2b; + } + + &.abgeschlossen { + background-color: #d9eec5; + border-color: #7ccb2b; + } + + &.verworfen { + background-color: #dedede; + border-color: #8e8e8f; + } + + &.zu-loeschen { + background-color: #fff; + border-color: #bbb; + } + } + + &.selected { + .dot { + &.neu { + background-color: #155ab4; + } + + &.angenommen { + background-color: #f1c14e; + } + + &.in_bearbeitung { + background-color: #f1c14e; + } + + &.beschieden { + background-color: #7ccb2b; + } + + &.abgeschlossen { + background-color: #7ccb2b; + } + + &.verworfen { + background-color: #8e8e8f; + } + + &.zu-loeschen { + background-color: #bbb; + } + } + } + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.html index c9142868824af6b90df416d47f25b7e1c29365ce..ebffc3b757f885bde0e6146286f3a3c9f4244dc0 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.html @@ -1 +1,4 @@ -<alfa-vorgang-search-view-item [routePath]="routePath$ | async" [isSelected]="isSelected$ | async"></alfa-vorgang-search-view-item> \ No newline at end of file +<alfa-vorgang-search-view-item + [routePath]="routePath$ | async" + [isSelected]="isSelected$ | async" +></alfa-vorgang-search-view-item> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.spec.ts index 2ac67b2ff3c00cb6b6b42a29a0c437cef87d4fe1..f1b39df129914dd62bdbe6283c31aa801b40f7d5 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.spec.ts @@ -6,46 +6,45 @@ import { VorgangSearchViewItemContainerComponent } from './vorgang-search-view-i import { VorgangSearchViewItemComponent } from './vorgang-search-view-item/vorgang-search-view-item.component'; describe('VorgangSearchViewItemContainerComponent', () => { - let component: VorgangSearchViewItemContainerComponent; - let fixture: ComponentFixture<VorgangSearchViewItemContainerComponent>; - - const vorgangListService = mock(VorgangListService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangSearchViewItemContainerComponent, - MockComponent(VorgangSearchViewItemComponent) - ], - providers: [ - { - provide: VorgangListService, - useValue: vorgangListService - } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(VorgangSearchViewItemContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('OnInit', () => { - - it('should call vorgangListService isVorgangViewSelected', () => { - component.ngOnInit(); - - expect(vorgangListService.isVorgangViewSelected).toHaveBeenCalledWith(VorgangView.SEARCH); - }) - - it('should call vorgangListService getVorgangViewRoutePath', () => { - component.ngOnInit(); - - expect(vorgangListService.getVorgangViewRoutePath).toHaveBeenCalledWith(VorgangView.SEARCH); - }) - }) + let component: VorgangSearchViewItemContainerComponent; + let fixture: ComponentFixture<VorgangSearchViewItemContainerComponent>; + + const vorgangListService = mock(VorgangListService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangSearchViewItemContainerComponent, + MockComponent(VorgangSearchViewItemComponent), + ], + providers: [ + { + provide: VorgangListService, + useValue: vorgangListService, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(VorgangSearchViewItemContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('OnInit', () => { + it('should call vorgangListService isVorgangViewSelected', () => { + component.ngOnInit(); + + expect(vorgangListService.isVorgangViewSelected).toHaveBeenCalledWith(VorgangView.SEARCH); + }); + + it('should call vorgangListService getVorgangViewRoutePath', () => { + component.ngOnInit(); + + expect(vorgangListService.getVorgangViewRoutePath).toHaveBeenCalledWith(VorgangView.SEARCH); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.ts index 6c7012eb5603175d08f35a41bc9aad9c18d4a5eb..61718f8b79a3bca91a233ba679077924e8ce28c2 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item-container.component.ts @@ -3,19 +3,18 @@ import { VorgangListService, VorgangView } from '@alfa-client/vorgang-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-search-view-item-container', - templateUrl: './vorgang-search-view-item-container.component.html', - styleUrls: ['./vorgang-search-view-item-container.component.scss'], + selector: 'alfa-vorgang-search-view-item-container', + templateUrl: './vorgang-search-view-item-container.component.html', + styleUrls: ['./vorgang-search-view-item-container.component.scss'], }) export class VorgangSearchViewItemContainerComponent implements OnInit { + isSelected$: Observable<boolean>; + routePath$: Observable<string>; - isSelected$: Observable<boolean>; - routePath$: Observable<string>; + constructor(private vorgangListService: VorgangListService) {} - constructor(private vorgangListService: VorgangListService){ } - - ngOnInit(): void { - this.isSelected$ = this.vorgangListService.isVorgangViewSelected(VorgangView.SEARCH); - this.routePath$ = this.vorgangListService.getVorgangViewRoutePath(VorgangView.SEARCH); - } + ngOnInit(): void { + this.isSelected$ = this.vorgangListService.isVorgangViewSelected(VorgangView.SEARCH); + this.routePath$ = this.vorgangListService.getVorgangViewRoutePath(VorgangView.SEARCH); + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.html index 62d3a47a3d80749fd4e126842a1934eda5d06723..9f578e5efcee92394cc676b46eb6cd5e0ee27cca 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.html @@ -1,4 +1,8 @@ -<ozgcloud-routing-button [routerLinkPath]="routePath" [class.selected]="isSelected" data-test-id="views-menu-item-Suche"> - <ozgcloud-icon icon="search"></ozgcloud-icon> - Suche -</ozgcloud-routing-button> \ No newline at end of file +<ozgcloud-routing-button + [routerLinkPath]="routePath" + [class.selected]="isSelected" + data-test-id="views-menu-item-Suche" +> + <ozgcloud-icon icon="search"></ozgcloud-icon> + Suche +</ozgcloud-routing-button> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.scss index fdf84892eecf5e44341bee847c0e3bec2066bc0a..9a13513543de0d2bb3fdb63914d8695286a18cf5 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.scss @@ -1,3 +1,3 @@ ozgcloud-icon { - margin-right: 6px; -} \ No newline at end of file + margin-right: 6px; +} diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.spec.ts index 826551c2744d2536b032d8482be739be79b0e2a7..303c02fbab9ea9b39ea34efe0628b72711b44f12 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.spec.ts @@ -4,24 +4,24 @@ import { MockComponent } from 'ng-mocks'; import { VorgangSearchViewItemComponent } from './vorgang-search-view-item.component'; describe('VorgangSearchViewItemComponent', () => { - let component: VorgangSearchViewItemComponent; - let fixture: ComponentFixture<VorgangSearchViewItemComponent>; + let component: VorgangSearchViewItemComponent; + let fixture: ComponentFixture<VorgangSearchViewItemComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangSearchViewItemComponent, - MockComponent(OzgcloudRoutingButtonComponent), - MockComponent(OzgcloudIconComponent), - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangSearchViewItemComponent, + MockComponent(OzgcloudRoutingButtonComponent), + MockComponent(OzgcloudIconComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(VorgangSearchViewItemComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(VorgangSearchViewItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.ts index 2d27b3a7fcc8ba86eb85a3629efd513365901e9a..902f8b76556104e2653f70987b3f2080f3b5dcc0 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-search-view-item-container/vorgang-search-view-item/vorgang-search-view-item.component.ts @@ -1,13 +1,11 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'alfa-vorgang-search-view-item', - templateUrl: './vorgang-search-view-item.component.html', - styleUrls: ['./vorgang-search-view-item.component.scss'], + selector: 'alfa-vorgang-search-view-item', + templateUrl: './vorgang-search-view-item.component.html', + styleUrls: ['./vorgang-search-view-item.component.scss'], }) export class VorgangSearchViewItemComponent { - - @Input() readonly isSelected: boolean; - @Input() readonly routePath: string; - + @Input() readonly isSelected: boolean; + @Input() readonly routePath: string; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.html index 9d1362205ca06128993cf658c82a92c1cf186751..9be88dd2c5967f551d1682ee807b4bc052a97954 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.html @@ -1,3 +1,8 @@ -<alfa-vorgang-view-item [label]="label" [count]="count" [isSelected]="isSelected$ | async" [routePath]="routePath$ | async"> - <ng-content></ng-content> -</alfa-vorgang-view-item> \ No newline at end of file +<alfa-vorgang-view-item + [label]="label" + [count]="count" + [isSelected]="isSelected$ | async" + [routePath]="routePath$ | async" +> + <ng-content></ng-content> +</alfa-vorgang-view-item> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.spec.ts index 657e90f012e2ecd5ac1e58ee68be0ed2cab053f0..21d26dd8f92c99f04eadb111b0d9227ff7e5b691 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.spec.ts @@ -6,53 +6,49 @@ import { VorgangViewItemContainerComponent } from './vorgang-view-item-container import { VorgangViewItemComponent } from './vorgang-view-item/vorgang-view-item.component'; describe('VorgangViewItemContainerComponent', () => { - let component: VorgangViewItemContainerComponent; - let fixture: ComponentFixture<VorgangViewItemContainerComponent>; - - const label: string = 'TestLabel'; - const view: VorgangView = VorgangView.NEU; - const count: number = 1; - - const vorgangListService: Mock<VorgangListService> = mock(VorgangListService); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangViewItemContainerComponent, - MockComponent(VorgangViewItemComponent) - ], - providers:[ - { - provide: VorgangListService, - useValue: vorgangListService - } - ] - }).compileComponents(); - - fixture = TestBed.createComponent(VorgangViewItemContainerComponent); - component = fixture.componentInstance; - component.label = label; - component.view = view; - component.count = count; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnInit', () => { - - it('should call service to check if view is selected', () => { - component.ngOnInit(); - - expect(vorgangListService.isVorgangViewSelected).toHaveBeenCalledWith(view); - }) - - it('should call service to get view route path', () => { - component.ngOnInit(); - - expect(vorgangListService.getVorgangViewRoutePath).toHaveBeenCalledWith(view); - }) - }) + let component: VorgangViewItemContainerComponent; + let fixture: ComponentFixture<VorgangViewItemContainerComponent>; + + const label: string = 'TestLabel'; + const view: VorgangView = VorgangView.NEU; + const count: number = 1; + + const vorgangListService: Mock<VorgangListService> = mock(VorgangListService); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [VorgangViewItemContainerComponent, MockComponent(VorgangViewItemComponent)], + providers: [ + { + provide: VorgangListService, + useValue: vorgangListService, + }, + ], + }).compileComponents(); + + fixture = TestBed.createComponent(VorgangViewItemContainerComponent); + component = fixture.componentInstance; + component.label = label; + component.view = view; + component.count = count; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnInit', () => { + it('should call service to check if view is selected', () => { + component.ngOnInit(); + + expect(vorgangListService.isVorgangViewSelected).toHaveBeenCalledWith(view); + }); + + it('should call service to get view route path', () => { + component.ngOnInit(); + + expect(vorgangListService.getVorgangViewRoutePath).toHaveBeenCalledWith(view); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.ts index aaf81ee9e46b966dac9e5599493c20c63b71ef7e..e50dcaf20c8185f1dafc7f06a45de650851ef0e1 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item-container.component.ts @@ -3,23 +3,22 @@ import { VorgangListService, VorgangView } from '@alfa-client/vorgang-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-view-item-container', - templateUrl: './vorgang-view-item-container.component.html', - styleUrls: ['./vorgang-view-item-container.component.scss'], + selector: 'alfa-vorgang-view-item-container', + templateUrl: './vorgang-view-item-container.component.html', + styleUrls: ['./vorgang-view-item-container.component.scss'], }) export class VorgangViewItemContainerComponent implements OnInit { + @Input() label: string; + @Input() view: VorgangView; + @Input() count: number; - @Input() label: string; - @Input() view: VorgangView; - @Input() count: number; + isSelected$: Observable<boolean>; + routePath$: Observable<string>; - isSelected$: Observable<boolean>; - routePath$: Observable<string>; + constructor(private vorgangListService: VorgangListService) {} - constructor(private vorgangListService: VorgangListService){ } - - ngOnInit(): void { - this.isSelected$ = this.vorgangListService.isVorgangViewSelected(this.view); - this.routePath$ = this.vorgangListService.getVorgangViewRoutePath(this.view); - } -} \ No newline at end of file + ngOnInit(): void { + this.isSelected$ = this.vorgangListService.isVorgangViewSelected(this.view); + this.routePath$ = this.vorgangListService.getVorgangViewRoutePath(this.view); + } +} diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.html index b2689921c1abc6927c2a634d0a62b1180df7334b..85a09071dd9f3890a988ce787c06accb65d54a16 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.html @@ -1,5 +1,14 @@ -<ozgcloud-routing-button [routerLinkPath]="routePath" [class.selected]="isSelected" [attr.data-test-id]="'views-menu-item-' + (label | convertForDataTest)"> - <ng-content></ng-content> - <div class="label">{{ label }}</div> - <div *ngIf="count != null" [attr.data-test-id]="'views-menu-item-count-' + (label | convertForDataTest)">{{count}}</div> +<ozgcloud-routing-button + [routerLinkPath]="routePath" + [class.selected]="isSelected" + [attr.data-test-id]="'views-menu-item-' + (label | convertForDataTest)" +> + <ng-content></ng-content> + <div class="label">{{ label }}</div> + <div + *ngIf="count != null" + [attr.data-test-id]="'views-menu-item-count-' + (label | convertForDataTest)" + > + {{ count }} + </div> </ozgcloud-routing-button> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.spec.ts index 93f9a296606355feed583acf4e9544e47b50c24d..09916d5c2076e04c964e259842c6fed177b1e3e6 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.spec.ts @@ -7,58 +7,57 @@ import { MockComponent } from 'ng-mocks'; import { VorgangViewItemComponent } from './vorgang-view-item.component'; describe('VorgangViewItemComponent', () => { - let component: VorgangViewItemComponent; - let fixture: ComponentFixture<VorgangViewItemComponent>; + let component: VorgangViewItemComponent; + let fixture: ComponentFixture<VorgangViewItemComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangViewItemComponent, - ConvertForDataTestPipe, - MockComponent(OzgcloudRoutingButtonComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangViewItemComponent, + ConvertForDataTestPipe, + MockComponent(OzgcloudRoutingButtonComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(VorgangViewItemComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(VorgangViewItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('count', () => { + describe('count', () => { + const count: string = getDataTestIdOf('views-menu-item-count-Dummy'); - const count: string = getDataTestIdOf('views-menu-item-count-Dummy'); + beforeEach(() => { + component.label = 'Dummy'; + }); - beforeEach(() => { - component.label = 'Dummy'; - }) + it('should show on number', () => { + component.count = 5; - it('should show on number', () => { - component.count = 5; + fixture.detectChanges(); - fixture.detectChanges(); + existsAsHtmlElement(fixture, count); + }); - existsAsHtmlElement(fixture, count); - }) + it('should hide on null', () => { + component.count = null; + component.label = 'Dummy'; - it('should hide on null', () => { - component.count = null; - component.label = 'Dummy'; + fixture.detectChanges(); - fixture.detectChanges(); + notExistsAsHtmlElement(fixture, count); + }); - notExistsAsHtmlElement(fixture, count); - }) + it('should show on 0', () => { + component.count = 0; - it('should show on 0', () => { - component.count = 0; + fixture.detectChanges(); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, count); - }) - }) + existsAsHtmlElement(fixture, count); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.ts index ea6ff3a2d9dffdf100a88869f471dad7c00d8160..746c194b2dfe60337b4b7e3b8df640097faff622 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-view-item-container/vorgang-view-item/vorgang-view-item.component.ts @@ -1,14 +1,13 @@ import { Component, Input } from '@angular/core'; @Component({ - selector: 'alfa-vorgang-view-item', - templateUrl: './vorgang-view-item.component.html', - styleUrls: ['./vorgang-view-item.component.scss'], + selector: 'alfa-vorgang-view-item', + templateUrl: './vorgang-view-item.component.html', + styleUrls: ['./vorgang-view-item.component.scss'], }) export class VorgangViewItemComponent { - - @Input() label: string; - @Input() isSelected: string; - @Input() routePath: string; - @Input() count: number; + @Input() label: string; + @Input() isSelected: string; + @Input() routePath: string; + @Input() count: number; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html index 772f2ae2c24d8c75850fd036e4e2e089fb29e8c9..c7d9d6fc8850a44c562412d25b77ea4a0c2cda83 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.html @@ -24,44 +24,156 @@ --> <ng-container *ngIf="vorgangStatisticStateResource?.resource as statistic"> - <div class="views"> - <alfa-vorgang-view-item-container *ngIf="apiRootResource | hasAnyLink: apiRootLinkRel.ALLE_VORGAENGE_NEU: apiRootLinkRel.MEINE_VORGAENGE_NEU: apiRootLinkRel.UNASSIGNED_NEU" data-test-id="vorgang-neu-view" - label="Neu" [view]="vorgangView.NEU" [count]="statistic.byStatus.neu"> - <div class="dot neu"></div> - </alfa-vorgang-view-item-container> - <alfa-vorgang-view-item-container *ngIf="apiRootResource | hasAnyLink: apiRootLinkRel.ALLE_VORGAENGE_ANGENOMMEN: apiRootLinkRel.MEINE_VORGAENGE_ANGENOMMEN: apiRootLinkRel.UNASSIGNED_ANGENOMMEN" data-test-id="vorgang-angenommen-view" - label="Angenommen" [view]="vorgangView.ANGENOMMEN" [count]="statistic.byStatus.angenommen"> - <div class="dot angenommen"></div> - </alfa-vorgang-view-item-container> - <alfa-vorgang-view-item-container *ngIf="apiRootResource | hasAnyLink: apiRootLinkRel.ALLE_VORGAENGE_IN_BEARBEITUNG: apiRootLinkRel.MEINE_VORGAENGE_IN_BEARBEITUNG: apiRootLinkRel.UNASSIGNED_IN_BEARBEITUNG" data-test-id="vorgang-in-bearbeitung-view" - label="In Bearbeitung" [view]="vorgangView.IN_BEARBEITUNG" [count]="statistic.byStatus.inBearbeitung"> - <div class="dot in_bearbeitung"></div> - </alfa-vorgang-view-item-container> - <alfa-vorgang-view-item-container *ngIf="apiRootResource | hasAnyLink: apiRootLinkRel.ALLE_VORGAENGE_BESCHIEDEN: apiRootLinkRel.MEINE_VORGAENGE_BESCHIEDEN: apiRootLinkRel.UNASSIGNED_BESCHIEDEN" data-test-id="vorgang-beschieden-view" - label="Beschieden" [view]="vorgangView.BESCHIEDEN" [count]="statistic.byStatus.beschieden"> - <div class="dot beschieden"></div> - </alfa-vorgang-view-item-container> - <alfa-vorgang-view-item-container *ngIf="apiRootResource | hasAnyLink: apiRootLinkRel.ALLE_VORGAENGE_ABGESCHLOSSEN: apiRootLinkRel.MEINE_VORGAENGE_ABGESCHLOSSEN: apiRootLinkRel.UNASSIGNED_ABGESCHLOSSEN" data-test-id="vorgang-abgeschlossen-view" - label="Abgeschlossen" [view]="vorgangView.ABGESCHLOSSEN" [count]="statistic.byStatus.abgeschlossen"> - <div class="dot abgeschlossen"></div> - </alfa-vorgang-view-item-container> - <alfa-vorgang-view-item-container *ngIf="apiRootResource | hasAnyLink: apiRootLinkRel.ALLE_VORGAENGE_VERWORFEN: apiRootLinkRel.MEINE_VORGAENGE_VERWORFEN: apiRootLinkRel.UNASSIGNED_VERWORFEN" data-test-id="vorgang-verworfen-view" - label="Verworfen" [view]="vorgangView.VERWORFEN" [count]="statistic.byStatus.verworfen"> - <div class="dot verworfen"></div> - </alfa-vorgang-view-item-container> - <alfa-vorgang-view-item-container *ngIf="apiRootResource | hasAnyLink: apiRootLinkRel.ALLE_VORGAENGE_ZU_LOESCHEN: apiRootLinkRel.MEINE_VORGAENGE_ZU_LOESCHEN: apiRootLinkRel.UNASSIGNED_ZU_LOESCHEN" data-test-id="vorgang-zu-loeschen-view" - label="Zu Löschen" [view]="vorgangView.ZU_LOESCHEN" [count]="statistic.byStatus.zuLoeschen"> - <div class="dot zu-loeschen"></div> - </alfa-vorgang-view-item-container> - <alfa-vorgang-view-item-container *ngIf="apiRootResource | hasAnyLink: apiRootLinkRel.ALL_WIEDERVORLAGEN: apiRootLinkRel.MY_WIEDERVORLAGEN: apiRootLinkRel.UNASSIGNED_WIEDERVORLAGEN" data-test-id="vorgang-wiedervorlagen-view" - label="Wiedervorlagen" [view]="vorgangView.WIEDERVORLAGEN" [count]="statistic.wiedervorlagen" class="top-border"> - <alfa-wiedervorlage-icon [isOverdue]="statistic.existsWiedervorlageOverdue"></alfa-wiedervorlage-icon> - </alfa-vorgang-view-item-container> - <alfa-vorgang-view-item-container *ngIf="apiRootResource | hasAnyLink: apiRootLinkRel.ALLE_VORGAENGE: apiRootLinkRel.MEINE_VORGAENGE: apiRootLinkRel.UNASSIGNED" data-test-id="vorgang-vorgang-list-view" - label="Vorgangsliste" [view]="vorgangView.VORGANG_LIST" class="top-border"> - <ozgcloud-icon icon="format_list_bulleted"></ozgcloud-icon> - </alfa-vorgang-view-item-container> - <alfa-vorgang-search-view-item-container *ngIf="apiRootResource | hasAnyLink: apiRootLinkRel.SEARCH_ALLE: apiRootLinkRel.SEARCH_MEINE: apiRootLinkRel.SEARCH_UNASSIGNED" data-test-id="vorgang-search-view" class="top-border"> - </alfa-vorgang-search-view-item-container> - </div> -</ng-container> \ No newline at end of file + <div class="views"> + <alfa-vorgang-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.ALLE_VORGAENGE_NEU + : apiRootLinkRel.MEINE_VORGAENGE_NEU + : apiRootLinkRel.UNASSIGNED_NEU + " + data-test-id="vorgang-neu-view" + label="Neu" + [view]="vorgangView.NEU" + [count]="statistic.byStatus.neu" + > + <div class="dot neu"></div> + </alfa-vorgang-view-item-container> + <alfa-vorgang-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.ALLE_VORGAENGE_ANGENOMMEN + : apiRootLinkRel.MEINE_VORGAENGE_ANGENOMMEN + : apiRootLinkRel.UNASSIGNED_ANGENOMMEN + " + data-test-id="vorgang-angenommen-view" + label="Angenommen" + [view]="vorgangView.ANGENOMMEN" + [count]="statistic.byStatus.angenommen" + > + <div class="dot angenommen"></div> + </alfa-vorgang-view-item-container> + <alfa-vorgang-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.ALLE_VORGAENGE_IN_BEARBEITUNG + : apiRootLinkRel.MEINE_VORGAENGE_IN_BEARBEITUNG + : apiRootLinkRel.UNASSIGNED_IN_BEARBEITUNG + " + data-test-id="vorgang-in-bearbeitung-view" + label="In Bearbeitung" + [view]="vorgangView.IN_BEARBEITUNG" + [count]="statistic.byStatus.inBearbeitung" + > + <div class="dot in_bearbeitung"></div> + </alfa-vorgang-view-item-container> + <alfa-vorgang-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.ALLE_VORGAENGE_BESCHIEDEN + : apiRootLinkRel.MEINE_VORGAENGE_BESCHIEDEN + : apiRootLinkRel.UNASSIGNED_BESCHIEDEN + " + data-test-id="vorgang-beschieden-view" + label="Beschieden" + [view]="vorgangView.BESCHIEDEN" + [count]="statistic.byStatus.beschieden" + > + <div class="dot beschieden"></div> + </alfa-vorgang-view-item-container> + <alfa-vorgang-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.ALLE_VORGAENGE_ABGESCHLOSSEN + : apiRootLinkRel.MEINE_VORGAENGE_ABGESCHLOSSEN + : apiRootLinkRel.UNASSIGNED_ABGESCHLOSSEN + " + data-test-id="vorgang-abgeschlossen-view" + label="Abgeschlossen" + [view]="vorgangView.ABGESCHLOSSEN" + [count]="statistic.byStatus.abgeschlossen" + > + <div class="dot abgeschlossen"></div> + </alfa-vorgang-view-item-container> + <alfa-vorgang-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.ALLE_VORGAENGE_VERWORFEN + : apiRootLinkRel.MEINE_VORGAENGE_VERWORFEN + : apiRootLinkRel.UNASSIGNED_VERWORFEN + " + data-test-id="vorgang-verworfen-view" + label="Verworfen" + [view]="vorgangView.VERWORFEN" + [count]="statistic.byStatus.verworfen" + > + <div class="dot verworfen"></div> + </alfa-vorgang-view-item-container> + <alfa-vorgang-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.ALLE_VORGAENGE_ZU_LOESCHEN + : apiRootLinkRel.MEINE_VORGAENGE_ZU_LOESCHEN + : apiRootLinkRel.UNASSIGNED_ZU_LOESCHEN + " + data-test-id="vorgang-zu-loeschen-view" + label="Zu Löschen" + [view]="vorgangView.ZU_LOESCHEN" + [count]="statistic.byStatus.zuLoeschen" + > + <div class="dot zu-loeschen"></div> + </alfa-vorgang-view-item-container> + <alfa-vorgang-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.ALL_WIEDERVORLAGEN + : apiRootLinkRel.MY_WIEDERVORLAGEN + : apiRootLinkRel.UNASSIGNED_WIEDERVORLAGEN + " + data-test-id="vorgang-wiedervorlagen-view" + label="Wiedervorlagen" + [view]="vorgangView.WIEDERVORLAGEN" + [count]="statistic.wiedervorlagen" + class="top-border" + > + <alfa-wiedervorlage-icon + [isOverdue]="statistic.existsWiedervorlageOverdue" + ></alfa-wiedervorlage-icon> + </alfa-vorgang-view-item-container> + <alfa-vorgang-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.ALLE_VORGAENGE + : apiRootLinkRel.MEINE_VORGAENGE + : apiRootLinkRel.UNASSIGNED + " + data-test-id="vorgang-vorgang-list-view" + label="Vorgangsliste" + [view]="vorgangView.VORGANG_LIST" + class="top-border" + > + <ozgcloud-icon icon="format_list_bulleted"></ozgcloud-icon> + </alfa-vorgang-view-item-container> + <alfa-vorgang-search-view-item-container + *ngIf=" + apiRootResource + | hasAnyLink + : apiRootLinkRel.SEARCH_ALLE + : apiRootLinkRel.SEARCH_MEINE + : apiRootLinkRel.SEARCH_UNASSIGNED + " + data-test-id="vorgang-search-view" + class="top-border" + > + </alfa-vorgang-search-view-item-container> + </div> +</ng-container> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss index 71938d0cdcffcbfe84bac7dca8894571aecd8685..4b089df917f623d3d02d1f44fcca2dc9e7ba79c1 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.scss @@ -24,52 +24,52 @@ @import 'variables'; :host { - background-color: $background; - padding: 0 1rem 0 0; - position: sticky; - align-self: flex-start; - top: $header-height + $navigation-height; + background-color: $background; + padding: 0 1rem 0 0; + position: sticky; + align-self: flex-start; + top: $header-height + $navigation-height; } :host-context(body.dark) { - background-color: $dark-background; + background-color: $dark-background; } .views { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } hr { - display: block; - height: 1px; - border: 0; - border-top: 1px solid $greyLight; - margin: 1em 0; - padding: 0; + display: block; + height: 1px; + border: 0; + border-top: 1px solid $greyLight; + margin: 1em 0; + padding: 0; } .top-border { - margin-top: 0.5rem; - padding-top: 0.5rem; - border-top: 1px solid $greyLight; + margin-top: 0.5rem; + padding-top: 0.5rem; + border-top: 1px solid $greyLight; } body.dark :host { - .top-border { - border-top: 1px solid $grey; - } + .top-border { + border-top: 1px solid $grey; + } } .views > * { - margin: 0.25rem 0; + margin: 0.25rem 0; - &:first-child { - margin-top: 0.125rem; - border-top: none; - } + &:first-child { + margin-top: 0.125rem; + border-top: none; + } } ozgcloud-icon { - margin-right: 6px; -} \ No newline at end of file + margin-right: 6px; +} diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts index 868c70e49e0d2243b06fe2746bad3e5eea73bcd9..cf4f8bd301a92a054afbf9e6c3d22c7c1af0b5fe 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.spec.ts @@ -38,194 +38,220 @@ import { VorgangViewsMenuComponent } from './vorgang-views-menu.component'; import { WiedervorlageIconComponent } from '../../../../../../vorgang-shared-ui/src/lib/wiedervorlage-icon/wiedervorlage-icon.component'; describe('VorgangViewsMenuComponent', () => { - let component: VorgangViewsMenuComponent; - let fixture: ComponentFixture<VorgangViewsMenuComponent>; - - const neuView: string = getDataTestIdOf('vorgang-neu-view'); - const angenommenView: string = getDataTestIdOf('vorgang-angenommen-view'); - const inBearbeitungView: string = getDataTestIdOf('vorgang-in-bearbeitung-view'); - const beschiedenView: string = getDataTestIdOf('vorgang-beschieden-view'); - const abgeschlossenView: string = getDataTestIdOf('vorgang-abgeschlossen-view'); - const verworfenView: string = getDataTestIdOf('vorgang-verworfen-view'); - const wiedervorlagenView: string = getDataTestIdOf('vorgang-wiedervorlagen-view'); - const vorgangListView: string = getDataTestIdOf('vorgang-vorgang-list-view'); - const searchView: string = getDataTestIdOf('vorgang-search-view'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageIconComponent, - VorgangViewsMenuComponent, - HasLinkPipe, - HasAnyLinkPipe, - MockComponent(VorgangViewItemContainerComponent), - MockComponent(VorgangViewItemComponent), - MockComponent(VorgangSearchViewItemContainerComponent), - MockComponent(OzgcloudIconComponent) - ], - }).compileComponents(); - - fixture = TestBed.createComponent(VorgangViewsMenuComponent); - component = fixture.componentInstance; - component.vorgangStatisticStateResource = createStateResource(createVorgangStatistic()); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('neu view', () => { - - it.each([ApiRootLinkRel.ALLE_VORGAENGE_NEU, ApiRootLinkRel.MEINE_VORGAENGE_NEU, ApiRootLinkRel.UNASSIGNED_NEU])('should show if %s link exists', (linkRel: string) => { - component.apiRootResource = createApiRootResource([linkRel]); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, neuView); - }) - - it('should hide if both links not exists', () => { - component.apiRootResource = createApiRootResource(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, neuView); - }) - }) - - describe('angenommen view', () => { - - it.each([ApiRootLinkRel.ALLE_VORGAENGE_ANGENOMMEN, ApiRootLinkRel.MEINE_VORGAENGE_ANGENOMMEN, ApiRootLinkRel.UNASSIGNED_ANGENOMMEN])('should show if %s link exists', (linkRel: string) => { - component.apiRootResource = createApiRootResource([linkRel]); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, angenommenView); - }) - - it('should hide if both links not exists', () => { - component.apiRootResource = createApiRootResource(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, angenommenView); - }) - }) - - describe('in bearbeitung view', () => { - - it.each([ApiRootLinkRel.ALLE_VORGAENGE_IN_BEARBEITUNG, ApiRootLinkRel.MEINE_VORGAENGE_IN_BEARBEITUNG, ApiRootLinkRel.UNASSIGNED_IN_BEARBEITUNG])('should show if %s link exists', (linkRel: string) => { - component.apiRootResource = createApiRootResource([linkRel]); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, inBearbeitungView); - }) - - it('should hide if both links not exists', () => { - component.apiRootResource = createApiRootResource(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, inBearbeitungView); - }) - }) - - describe('beschieden view', () => { - - it.each([ApiRootLinkRel.ALLE_VORGAENGE_BESCHIEDEN, ApiRootLinkRel.MEINE_VORGAENGE_BESCHIEDEN, ApiRootLinkRel.UNASSIGNED_BESCHIEDEN])('should show if %s link exists', (linkRel: string) => { - component.apiRootResource = createApiRootResource([linkRel]); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, beschiedenView); - }) - - it('should hide if both links not exists', () => { - component.apiRootResource = createApiRootResource(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, beschiedenView); - }) - }) - - describe('abgeschlossen view', () => { - - it.each([ApiRootLinkRel.ALLE_VORGAENGE_ABGESCHLOSSEN, ApiRootLinkRel.MEINE_VORGAENGE_ABGESCHLOSSEN, ApiRootLinkRel.UNASSIGNED_ABGESCHLOSSEN])('should show if %s link exists', (linkRel: string) => { - component.apiRootResource = createApiRootResource([linkRel]); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, abgeschlossenView); - }) - - it('should hide if both links not exists', () => { - component.apiRootResource = createApiRootResource(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, beschiedenView); - }) - }) - - describe('verworfen view', () => { - - it.each([ApiRootLinkRel.ALLE_VORGAENGE_VERWORFEN, ApiRootLinkRel.MEINE_VORGAENGE_VERWORFEN, ApiRootLinkRel.UNASSIGNED_VERWORFEN])('should show if %s link exists', (linkRel: string) => { - component.apiRootResource = createApiRootResource([linkRel]); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, verworfenView); - }) - - it('should hide if both links not exists', () => { - component.apiRootResource = createApiRootResource(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, verworfenView); - }) - }) - - describe('wiedervorlagen view', () => { - - it.each([ApiRootLinkRel.ALL_WIEDERVORLAGEN, ApiRootLinkRel.MY_WIEDERVORLAGEN, ApiRootLinkRel.UNASSIGNED_WIEDERVORLAGEN])('should show if %s link exists', (linkRel: string) => { - component.apiRootResource = createApiRootResource([linkRel]); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, wiedervorlagenView); - }) - - it('should hide if link not exists', () => { - component.apiRootResource = createApiRootResource(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, wiedervorlagenView); - }) - }) - - - describe('vorgangList view', () => { - - it.each([ApiRootLinkRel.ALLE_VORGAENGE, ApiRootLinkRel.MEINE_VORGAENGE, ApiRootLinkRel.UNASSIGNED])('should show if %s link exists', (linkRel: string) => { - component.apiRootResource = createApiRootResource([linkRel]); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, vorgangListView); - }) - - it('should hide if link not exists', () => { - component.apiRootResource = createApiRootResource(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, vorgangListView); - }) - }) - - describe('search view', () => { - - it.each([ApiRootLinkRel.SEARCH_ALLE, ApiRootLinkRel.SEARCH_MEINE, ApiRootLinkRel.SEARCH_UNASSIGNED])('should show if %s link exists', (linkRel: string) => { - component.apiRootResource = createApiRootResource([linkRel]); - fixture.detectChanges(); - - existsAsHtmlElement(fixture, searchView); - }) - - it('should hide if no link not exists', () => { - component.apiRootResource = createApiRootResource(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, searchView); - }) - }) + let component: VorgangViewsMenuComponent; + let fixture: ComponentFixture<VorgangViewsMenuComponent>; + + const neuView: string = getDataTestIdOf('vorgang-neu-view'); + const angenommenView: string = getDataTestIdOf('vorgang-angenommen-view'); + const inBearbeitungView: string = getDataTestIdOf('vorgang-in-bearbeitung-view'); + const beschiedenView: string = getDataTestIdOf('vorgang-beschieden-view'); + const abgeschlossenView: string = getDataTestIdOf('vorgang-abgeschlossen-view'); + const verworfenView: string = getDataTestIdOf('vorgang-verworfen-view'); + const wiedervorlagenView: string = getDataTestIdOf('vorgang-wiedervorlagen-view'); + const vorgangListView: string = getDataTestIdOf('vorgang-vorgang-list-view'); + const searchView: string = getDataTestIdOf('vorgang-search-view'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageIconComponent, + VorgangViewsMenuComponent, + HasLinkPipe, + HasAnyLinkPipe, + MockComponent(VorgangViewItemContainerComponent), + MockComponent(VorgangViewItemComponent), + MockComponent(VorgangSearchViewItemContainerComponent), + MockComponent(OzgcloudIconComponent), + ], + }).compileComponents(); + + fixture = TestBed.createComponent(VorgangViewsMenuComponent); + component = fixture.componentInstance; + component.vorgangStatisticStateResource = createStateResource(createVorgangStatistic()); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('neu view', () => { + it.each([ + ApiRootLinkRel.ALLE_VORGAENGE_NEU, + ApiRootLinkRel.MEINE_VORGAENGE_NEU, + ApiRootLinkRel.UNASSIGNED_NEU, + ])('should show if %s link exists', (linkRel: string) => { + component.apiRootResource = createApiRootResource([linkRel]); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, neuView); + }); + + it('should hide if both links not exists', () => { + component.apiRootResource = createApiRootResource(); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, neuView); + }); + }); + + describe('angenommen view', () => { + it.each([ + ApiRootLinkRel.ALLE_VORGAENGE_ANGENOMMEN, + ApiRootLinkRel.MEINE_VORGAENGE_ANGENOMMEN, + ApiRootLinkRel.UNASSIGNED_ANGENOMMEN, + ])('should show if %s link exists', (linkRel: string) => { + component.apiRootResource = createApiRootResource([linkRel]); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, angenommenView); + }); + + it('should hide if both links not exists', () => { + component.apiRootResource = createApiRootResource(); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, angenommenView); + }); + }); + + describe('in bearbeitung view', () => { + it.each([ + ApiRootLinkRel.ALLE_VORGAENGE_IN_BEARBEITUNG, + ApiRootLinkRel.MEINE_VORGAENGE_IN_BEARBEITUNG, + ApiRootLinkRel.UNASSIGNED_IN_BEARBEITUNG, + ])('should show if %s link exists', (linkRel: string) => { + component.apiRootResource = createApiRootResource([linkRel]); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, inBearbeitungView); + }); + + it('should hide if both links not exists', () => { + component.apiRootResource = createApiRootResource(); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, inBearbeitungView); + }); + }); + + describe('beschieden view', () => { + it.each([ + ApiRootLinkRel.ALLE_VORGAENGE_BESCHIEDEN, + ApiRootLinkRel.MEINE_VORGAENGE_BESCHIEDEN, + ApiRootLinkRel.UNASSIGNED_BESCHIEDEN, + ])('should show if %s link exists', (linkRel: string) => { + component.apiRootResource = createApiRootResource([linkRel]); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, beschiedenView); + }); + + it('should hide if both links not exists', () => { + component.apiRootResource = createApiRootResource(); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, beschiedenView); + }); + }); + + describe('abgeschlossen view', () => { + it.each([ + ApiRootLinkRel.ALLE_VORGAENGE_ABGESCHLOSSEN, + ApiRootLinkRel.MEINE_VORGAENGE_ABGESCHLOSSEN, + ApiRootLinkRel.UNASSIGNED_ABGESCHLOSSEN, + ])('should show if %s link exists', (linkRel: string) => { + component.apiRootResource = createApiRootResource([linkRel]); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, abgeschlossenView); + }); + + it('should hide if both links not exists', () => { + component.apiRootResource = createApiRootResource(); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, beschiedenView); + }); + }); + + describe('verworfen view', () => { + it.each([ + ApiRootLinkRel.ALLE_VORGAENGE_VERWORFEN, + ApiRootLinkRel.MEINE_VORGAENGE_VERWORFEN, + ApiRootLinkRel.UNASSIGNED_VERWORFEN, + ])('should show if %s link exists', (linkRel: string) => { + component.apiRootResource = createApiRootResource([linkRel]); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, verworfenView); + }); + + it('should hide if both links not exists', () => { + component.apiRootResource = createApiRootResource(); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, verworfenView); + }); + }); + + describe('wiedervorlagen view', () => { + it.each([ + ApiRootLinkRel.ALL_WIEDERVORLAGEN, + ApiRootLinkRel.MY_WIEDERVORLAGEN, + ApiRootLinkRel.UNASSIGNED_WIEDERVORLAGEN, + ])('should show if %s link exists', (linkRel: string) => { + component.apiRootResource = createApiRootResource([linkRel]); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, wiedervorlagenView); + }); + + it('should hide if link not exists', () => { + component.apiRootResource = createApiRootResource(); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, wiedervorlagenView); + }); + }); + + describe('vorgangList view', () => { + it.each([ + ApiRootLinkRel.ALLE_VORGAENGE, + ApiRootLinkRel.MEINE_VORGAENGE, + ApiRootLinkRel.UNASSIGNED, + ])('should show if %s link exists', (linkRel: string) => { + component.apiRootResource = createApiRootResource([linkRel]); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, vorgangListView); + }); + + it('should hide if link not exists', () => { + component.apiRootResource = createApiRootResource(); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, vorgangListView); + }); + }); + + describe('search view', () => { + it.each([ + ApiRootLinkRel.SEARCH_ALLE, + ApiRootLinkRel.SEARCH_MEINE, + ApiRootLinkRel.SEARCH_UNASSIGNED, + ])('should show if %s link exists', (linkRel: string) => { + component.apiRootResource = createApiRootResource([linkRel]); + fixture.detectChanges(); + + existsAsHtmlElement(fixture, searchView); + }); + + it('should hide if no link not exists', () => { + component.apiRootResource = createApiRootResource(); + fixture.detectChanges(); + + notExistsAsHtmlElement(fixture, searchView); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.ts index 982a5d97a07847161476b0a2a5d2b22f066cd78c..ae37aca29cb55ba0cde8bb13c375225ce328a0d8 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-views-menu/vorgang-views-menu.component.ts @@ -28,15 +28,14 @@ import { VorgangStatistic, VorgangView } from '@alfa-client/vorgang-shared'; //MOVEME Unter vorgang-views-menu-container schieben @Component({ - selector: 'alfa-vorgang-views-menu', - templateUrl: './vorgang-views-menu.component.html', - styleUrls: ['./vorgang-views-menu.component.scss'], + selector: 'alfa-vorgang-views-menu', + templateUrl: './vorgang-views-menu.component.html', + styleUrls: ['./vorgang-views-menu.component.scss'], }) export class VorgangViewsMenuComponent { + @Input() apiRootResource: ApiRootResource; + @Input() vorgangStatisticStateResource: StateResource<VorgangStatistic>; - @Input() apiRootResource: ApiRootResource; - @Input() vorgangStatisticStateResource: StateResource<VorgangStatistic>; - - readonly apiRootLinkRel = ApiRootLinkRel; - readonly vorgangView = VorgangView; + readonly apiRootLinkRel = ApiRootLinkRel; + readonly vorgangView = VorgangView; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page.guard.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page.guard.spec.ts index 8252c00ccd725bcf076e7c3f24c255a8c67b4f10..754c452946a194d3cd9634c13744f0329746bcc9 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page.guard.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page.guard.spec.ts @@ -22,7 +22,14 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { TestBed } from '@angular/core/testing'; -import { ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot, UrlSegment, UrlTree } from '@angular/router'; +import { + ActivatedRouteSnapshot, + CanActivateFn, + Router, + RouterStateSnapshot, + UrlSegment, + UrlTree, +} from '@angular/router'; import { AuthService } from '@alfa-client/app-shared'; import { mock, useFromMock } from '@alfa-client/test-utils'; @@ -30,101 +37,118 @@ import * as VorgangNavigationUtil from 'libs/vorgang-shared/src/lib/vorgang-navi import * as Guard from './vorgang-list-page.guard'; const next: ActivatedRouteSnapshot = {} as unknown as ActivatedRouteSnapshot; -const state: RouterStateSnapshot = { root: { url: [<UrlSegment>{}] } } as unknown as RouterStateSnapshot; +const state: RouterStateSnapshot = { + root: { url: [<UrlSegment>{}] }, +} as unknown as RouterStateSnapshot; describe('VorgangListPageGuard', () => { - const router = mock(Router); - const authService = mock(AuthService); - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - { - provide: Router, - useValue: router - }, - { - provide: AuthService, - useValue: authService - } - ] - }); - - }); - - - it('should be created', () => { - const guard = TestBed.runInInjectionContext(() => Guard.vorgangListPageGuard(next, state)) as unknown as CanActivateFn; - - expect(guard).toBeTruthy(); - }); - - describe('vorgangListPageGuard', () => { - - it('should not call buildDefaultUrlTreeFromLocalStorage', () => { - const spy = jest.spyOn(Guard, 'buildDefaultUrlTreeFromLocalStorage'); - state.root.url = [<UrlSegment>{ path: 'test' }]; - - TestBed.runInInjectionContext(() => Guard.vorgangListPageGuard(next, state)) as unknown as CanActivateFn; - - expect(spy).not.toHaveBeenCalled(); - }) - - it('should call buildDefaultUrlTreeFromLocalStorage', () => { - const spy = jest.spyOn(Guard, 'buildDefaultUrlTreeFromLocalStorage'); - state.root.url = null; - - TestBed.runInInjectionContext(() => Guard.vorgangListPageGuard(next, state)) as unknown as CanActivateFn; - - expect(spy).toHaveBeenCalled(); - }) - - }) - - describe('buildDefaultUrlTreeFromLocalStorage', () => { - const buildPathSegmentsFromLocalStorage = jest.spyOn(VorgangNavigationUtil, 'buildPathSegmentsFromLocalStorage'); - - it('should call hasNoValidToken', () => { - const spy = jest.spyOn(authService, 'hasNoValidToken'); - - TestBed.runInInjectionContext(() => Guard.buildDefaultUrlTreeFromLocalStorage(useFromMock(router), useFromMock(authService))); - - expect(spy).toHaveBeenCalled(); - }) - - it('should call router.createUrlTree', () => { - jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(false); - - TestBed.runInInjectionContext(() => Guard.buildDefaultUrlTreeFromLocalStorage(useFromMock(router), useFromMock(authService))); - - expect(router.createUrlTree).toHaveBeenCalled(); - }) - - it('should call VorgangNavigationUtil.buildPathSegmentsFromLocalStorage', () => { - jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(false); - - TestBed.runInInjectionContext(() => Guard.buildDefaultUrlTreeFromLocalStorage(useFromMock(router), useFromMock(authService))); - - expect(buildPathSegmentsFromLocalStorage).toHaveBeenCalled(); - }) - - it('should return URLTree if access token is valid', () => { - jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(false); - const pathSegments: string[] = ['meine', 'neu']; - buildPathSegmentsFromLocalStorage.mockReturnValue(pathSegments); - - TestBed.runInInjectionContext(() => Guard.buildDefaultUrlTreeFromLocalStorage(useFromMock(router), useFromMock(authService))); - - expect(router.createUrlTree).toHaveBeenCalledWith(pathSegments); - }) - - it('should return true if it has no valid access token', () => { - jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(true); - - const result: boolean | UrlTree = Guard.buildDefaultUrlTreeFromLocalStorage(useFromMock(router), useFromMock(authService)); - - expect(result).toBeTruthy(); - }) - }) - + const router = mock(Router); + const authService = mock(AuthService); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + { + provide: Router, + useValue: router, + }, + { + provide: AuthService, + useValue: authService, + }, + ], + }); + }); + + it('should be created', () => { + const guard = TestBed.runInInjectionContext(() => + Guard.vorgangListPageGuard(next, state), + ) as unknown as CanActivateFn; + + expect(guard).toBeTruthy(); + }); + + describe('vorgangListPageGuard', () => { + it('should not call buildDefaultUrlTreeFromLocalStorage', () => { + const spy = jest.spyOn(Guard, 'buildDefaultUrlTreeFromLocalStorage'); + state.root.url = [<UrlSegment>{ path: 'test' }]; + + TestBed.runInInjectionContext(() => + Guard.vorgangListPageGuard(next, state), + ) as unknown as CanActivateFn; + + expect(spy).not.toHaveBeenCalled(); + }); + + it('should call buildDefaultUrlTreeFromLocalStorage', () => { + const spy = jest.spyOn(Guard, 'buildDefaultUrlTreeFromLocalStorage'); + state.root.url = null; + + TestBed.runInInjectionContext(() => + Guard.vorgangListPageGuard(next, state), + ) as unknown as CanActivateFn; + + expect(spy).toHaveBeenCalled(); + }); + }); + + describe('buildDefaultUrlTreeFromLocalStorage', () => { + const buildPathSegmentsFromLocalStorage = jest.spyOn( + VorgangNavigationUtil, + 'buildPathSegmentsFromLocalStorage', + ); + + it('should call hasNoValidToken', () => { + const spy = jest.spyOn(authService, 'hasNoValidToken'); + + TestBed.runInInjectionContext(() => + Guard.buildDefaultUrlTreeFromLocalStorage(useFromMock(router), useFromMock(authService)), + ); + + expect(spy).toHaveBeenCalled(); + }); + + it('should call router.createUrlTree', () => { + jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(false); + + TestBed.runInInjectionContext(() => + Guard.buildDefaultUrlTreeFromLocalStorage(useFromMock(router), useFromMock(authService)), + ); + + expect(router.createUrlTree).toHaveBeenCalled(); + }); + + it('should call VorgangNavigationUtil.buildPathSegmentsFromLocalStorage', () => { + jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(false); + + TestBed.runInInjectionContext(() => + Guard.buildDefaultUrlTreeFromLocalStorage(useFromMock(router), useFromMock(authService)), + ); + + expect(buildPathSegmentsFromLocalStorage).toHaveBeenCalled(); + }); + + it('should return URLTree if access token is valid', () => { + jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(false); + const pathSegments: string[] = ['meine', 'neu']; + buildPathSegmentsFromLocalStorage.mockReturnValue(pathSegments); + + TestBed.runInInjectionContext(() => + Guard.buildDefaultUrlTreeFromLocalStorage(useFromMock(router), useFromMock(authService)), + ); + + expect(router.createUrlTree).toHaveBeenCalledWith(pathSegments); + }); + + it('should return true if it has no valid access token', () => { + jest.spyOn(authService, 'hasNoValidToken').mockReturnValue(true); + + const result: boolean | UrlTree = Guard.buildDefaultUrlTreeFromLocalStorage( + useFromMock(router), + useFromMock(authService), + ); + + expect(result).toBeTruthy(); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-page.guard.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-page.guard.ts index 05f06451ad4b9ce56b084aee1dd9df3af2caa6ef..4e081ff917b8e088606ba3ce7002b53dcd71dae3 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-page.guard.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-page.guard.ts @@ -22,29 +22,41 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { inject } from '@angular/core'; -import { ActivatedRouteSnapshot, CanActivateFn, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; +import { + ActivatedRouteSnapshot, + CanActivateFn, + Router, + RouterStateSnapshot, + UrlTree, +} from '@angular/router'; import { AuthService } from '@alfa-client/app-shared'; import { buildPathSegmentsFromLocalStorage } from 'libs/vorgang-shared/src/lib/vorgang-navigation.util'; import { isEmpty } from 'lodash-es'; import * as Guard from './vorgang-list-page.guard'; -export const vorgangListPageGuard: CanActivateFn = (next: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { - const router = inject(Router); - const authService = inject(AuthService); +export const vorgangListPageGuard: CanActivateFn = ( + next: ActivatedRouteSnapshot, + state: RouterStateSnapshot, +) => { + const router = inject(Router); + const authService = inject(AuthService); - if (isEmpty(state.root.url) ) { - return Guard.buildDefaultUrlTreeFromLocalStorage(router, authService); - } + if (isEmpty(state.root.url)) { + return Guard.buildDefaultUrlTreeFromLocalStorage(router, authService); + } - return true; + return true; }; -export function buildDefaultUrlTreeFromLocalStorage(router: Router, authService: AuthService): boolean | UrlTree { - if (authService.hasNoValidToken()) { - return true; - } +export function buildDefaultUrlTreeFromLocalStorage( + router: Router, + authService: AuthService, +): boolean | UrlTree { + if (authService.hasNoValidToken()) { + return true; + } - const pathSegments: string[] = buildPathSegmentsFromLocalStorage(); - return router.createUrlTree(pathSegments); + const pathSegments: string[] = buildPathSegmentsFromLocalStorage(); + return router.createUrlTree(pathSegments); } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.html index 4d1ec4f59f401c99c672756890354d5e4ad0c01a..cf3811854188199b7f3ec88e736679490e5fe631 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.html @@ -23,4 +23,6 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-vorgang-list-search [apiRootStateResource]="apiRootStateResource$ | async"></alfa-vorgang-list-search> +<alfa-vorgang-list-search + [apiRootStateResource]="apiRootStateResource$ | async" +></alfa-vorgang-list-search> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.spec.ts index b8a11f9c0f9be4cb92ce84d8de787bee4373935e..0b1942a0dd0177427d68b3bfce1bbb4dd0a19fd3 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.spec.ts @@ -29,40 +29,39 @@ import { VorgangListSearchContainerComponent } from './vorgang-list-search-conta import { VorgangListSearchComponent } from './vorgang-list-search/vorgang-list-search.component'; describe('VorgangListSearchContainerComponent', () => { - let component: VorgangListSearchContainerComponent; - let fixture: ComponentFixture<VorgangListSearchContainerComponent>; + let component: VorgangListSearchContainerComponent; + let fixture: ComponentFixture<VorgangListSearchContainerComponent>; - const apiRootService: Mock<ApiRootService> = mock(ApiRootService); + const apiRootService: Mock<ApiRootService> = mock(ApiRootService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangListSearchContainerComponent, - MockComponent(VorgangListSearchComponent) - ], - providers:[ - { - provide: ApiRootService, - useValue: apiRootService - } - ] - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangListSearchContainerComponent, + MockComponent(VorgangListSearchComponent), + ], + providers: [ + { + provide: ApiRootService, + useValue: apiRootService, + }, + ], + }).compileComponents(); - fixture = TestBed.createComponent(VorgangListSearchContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(VorgangListSearchContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('ngOnInit', () => { + describe('ngOnInit', () => { + it('should get apiRootResource', () => { + component.ngOnInit(); - it('should get apiRootResource', () => { - component.ngOnInit(); - - expect(apiRootService.getApiRoot).toHaveBeenCalled(); - }) - }) + expect(apiRootService.getApiRoot).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.ts index 1452c008509fa5dfdd286d8f76e688c521fb427a..b5e4bae05741ae9be8f617693bcba81fbefb2c9a 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search-container.component.ts @@ -27,17 +27,16 @@ import { StateResource } from '@alfa-client/tech-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-vorgang-list-search-container', - templateUrl: './vorgang-list-search-container.component.html', - styleUrls: ['./vorgang-list-search-container.component.scss'], + selector: 'alfa-vorgang-list-search-container', + templateUrl: './vorgang-list-search-container.component.html', + styleUrls: ['./vorgang-list-search-container.component.scss'], }) export class VorgangListSearchContainerComponent implements OnInit { + public apiRootStateResource$: Observable<StateResource<ApiRootResource>>; - public apiRootStateResource$: Observable<StateResource<ApiRootResource>>; + constructor(private apiRootService: ApiRootService) {} - constructor(private apiRootService: ApiRootService) { } - - ngOnInit(): void { - this.apiRootStateResource$ = this.apiRootService.getApiRoot(); - } + ngOnInit(): void { + this.apiRootStateResource$ = this.apiRootService.getApiRoot(); + } } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.html b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.html index f178e73b2103b357cf4701069d141eb70079c5e9..b2ceec7b0ef589fd9305a5de50eee7595365fcb0 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.html +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.html @@ -1,9 +1,16 @@ -<ng-container *ngIf="apiRootStateResource.resource | hasLink: apiRootLinkRel.HINTS; else searchResult"> - <alfa-hint-container data-test-id="hint-container"></alfa-hint-container> +<ng-container + *ngIf="apiRootStateResource.resource | hasLink: apiRootLinkRel.HINTS; else searchResult" +> + <alfa-hint-container data-test-id="hint-container"></alfa-hint-container> </ng-container> <ng-template #searchResult> - <div data-test-id="vorgang-list-empty-search-result" role="status" aria-live="assertive" class="l-scroll-area--full"> - <h3 data-test-id="empty-list-text">Bitte geben Sie einen Suchbegriff ein.</h3> - </div> -</ng-template> \ No newline at end of file + <div + data-test-id="vorgang-list-empty-search-result" + role="status" + aria-live="assertive" + class="l-scroll-area--full" + > + <h3 data-test-id="empty-list-text">Bitte geben Sie einen Suchbegriff ein.</h3> + </div> +</ng-template> diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.scss b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.scss index d14f7a0d7021b3ddf1d0ba7fa10b16cccf9d020b..df5f0bc9484e063d9de082c2293e383a0827f3e2 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.scss +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.scss @@ -1,12 +1,12 @@ div { - padding: 1.5rem; + padding: 1.5rem; } :host { - display: block; + display: block; } h3 { - font-size: 18px; - margin-bottom: 4px; + font-size: 18px; + margin-bottom: 4px; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.spec.ts index 6fe698694ef2f990da188cf183d9ebf5f52831a4..94c1d40f8b9e6b7bd6b5e5423bf3b1b057a9c144 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.spec.ts @@ -8,46 +8,45 @@ import { MockComponent } from 'ng-mocks'; import { VorgangListSearchComponent } from './vorgang-list-search.component'; describe('VorgangListSearchComponent', () => { - let component: VorgangListSearchComponent; - let fixture: ComponentFixture<VorgangListSearchComponent>; + let component: VorgangListSearchComponent; + let fixture: ComponentFixture<VorgangListSearchComponent>; - const hintContainer: string = getDataTestIdOf('hint-container'); - const emptySearchResult: string = getDataTestIdOf('vorgang-list-empty-search-result'); + const hintContainer: string = getDataTestIdOf('hint-container'); + const emptySearchResult: string = getDataTestIdOf('vorgang-list-empty-search-result'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - VorgangListSearchComponent, - HasLinkPipe, - MockComponent(HintContainerComponent) - ], - }).compileComponents(); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + VorgangListSearchComponent, + HasLinkPipe, + MockComponent(HintContainerComponent), + ], + }).compileComponents(); - fixture = TestBed.createComponent(VorgangListSearchComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + fixture = TestBed.createComponent(VorgangListSearchComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('if hints link is not present', () => { + describe('if hints link is not present', () => { + it('should show search result', () => { + component.apiRootStateResource = createStateResource(createApiRootResource()); - it('should show search result', () => { - component.apiRootStateResource = createStateResource(createApiRootResource()); + fixture.detectChanges(); - fixture.detectChanges(); + existsAsHtmlElement(fixture, emptySearchResult); + }); - existsAsHtmlElement(fixture, emptySearchResult); - }) + it('should hide hint container', () => { + component.apiRootStateResource = createStateResource(createApiRootResource()); - it('should hide hint container', () => { - component.apiRootStateResource = createStateResource(createApiRootResource()); + fixture.detectChanges(); - fixture.detectChanges(); - - notExistsAsHtmlElement(fixture, hintContainer); - }) - }) + notExistsAsHtmlElement(fixture, hintContainer); + }); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.ts b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.ts index eab6c29ef9a29dea6ba84d0230d760e4fba4bff6..83edc10fff7112f06b6ebb44f3a114332bfc26aa 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component.ts @@ -3,13 +3,12 @@ import { ApiRootLinkRel, ApiRootResource } from '@alfa-client/api-root-shared'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; @Component({ - selector: 'alfa-vorgang-list-search', - templateUrl: './vorgang-list-search.component.html', - styleUrls: ['./vorgang-list-search.component.scss'], + selector: 'alfa-vorgang-list-search', + templateUrl: './vorgang-list-search.component.html', + styleUrls: ['./vorgang-list-search.component.scss'], }) export class VorgangListSearchComponent { + @Input() apiRootStateResource: StateResource<ApiRootResource> = createEmptyStateResource(); - @Input() apiRootStateResource: StateResource<ApiRootResource> = createEmptyStateResource(); - - readonly apiRootLinkRel = ApiRootLinkRel; + readonly apiRootLinkRel = ApiRootLinkRel; } diff --git a/alfa-client/libs/vorgang/src/lib/vorgang.module.spec.ts b/alfa-client/libs/vorgang/src/lib/vorgang.module.spec.ts index 1d9264768b5867058908b78e95a876edd3735f1c..087d3ddacbd6f33799433111fea9908ae16092b8 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang.module.spec.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { VorgangModule } from './vorgang.module'; describe('VorgangModule', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [VorgangModule] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [VorgangModule], + }).compileComponents(); + }); - it('should create', () => { - expect(VorgangModule).toBeDefined(); - }); + it('should create', () => { + expect(VorgangModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/vorgang/src/lib/vorgang.module.ts b/alfa-client/libs/vorgang/src/lib/vorgang.module.ts index 798ab362e1f349d78af8a9ab600f4f93a4bfb124..1a8ab06a87e0c08fbff779b374f4bd469ea4ef1e 100644 --- a/alfa-client/libs/vorgang/src/lib/vorgang.module.ts +++ b/alfa-client/libs/vorgang/src/lib/vorgang.module.ts @@ -56,150 +56,147 @@ import { VorgangListSearchContainerComponent } from './vorgang-list-search-conta import { VorgangListSearchComponent } from './vorgang-list-search-container/vorgang-list-search/vorgang-list-search.component'; const routes: Routes = [ - { - path: '', - component: VorgangListPageContainerComponent, - title: 'Vorgänge | Alfa', - children: [ - { - path: '', - title: 'Alle Vorgänge | Alfa', - pathMatch: 'full', - canActivate: [vorgangListPageGuard], - children: [], - }, - { - path: 'alle', - title: 'Alle Vorgänge | Alfa', - component: VorgangListContainerComponent, - }, - { - path: 'alle/search/:search', - title: 'Suchergebnisseite | Alfa', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - { - path: 'alle/search', - canActivate: [vorgangFilterViewGuard], - component: VorgangListSearchContainerComponent, - }, - { - path: 'alle/:status', - title: 'Alle Vorgänge | Alfa', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - { - path: 'alle/wiedervorlagen', - title: 'Alle Vorgänge mit offenen Wiedervorlagen', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - { - path: 'meine', - title: 'Meine Vorgänge | Alfa', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - { - path: 'meine/search/:search', - title: 'Suchergebnis in meine Vorgänge | Alfa', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - { - path: 'meine/search', - canActivate: [vorgangFilterViewGuard], - component: VorgangListSearchContainerComponent, - }, - { - path: 'meine/:status', - title: 'Meine Vorgänge | Alfa', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - { - path: 'meine/wiedervorlagen', - title: 'Alle mir zugewiesenen Vorgänge mit offenen Wiedervorlagen', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - { - path: 'unassigned', - title: 'Nicht zugewiesen | Alfa', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - { - path: 'unassigned/search/:search', - title: 'Suchergebnis in nicht zugewiesen | Alfa', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - { - path: 'unassigned/search', - canActivate: [vorgangFilterViewGuard], - component: VorgangListSearchContainerComponent, - }, - { - path: 'unassigned/:status', - title: 'Nicht zugewiesen | Alfa', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - { - path: 'unassigned/wiedervorlagen', - title: 'Alle nicht zugewiesenen Vorgänge mit offenen Wiedervorlagen', - canActivate: [vorgangFilterViewGuard], - component: VorgangListContainerComponent, - }, - ], - }, - { - path: 'vorgang/:vorgangWithEingangUrl', - loadChildren: () => - import('@alfa-client/vorgang-detail').then( - (m) => m.VorgangDetailModule - ), - title: 'Details zum Vorgang | Alfa', - }, + { + path: '', + component: VorgangListPageContainerComponent, + title: 'Vorgänge | Alfa', + children: [ + { + path: '', + title: 'Alle Vorgänge | Alfa', + pathMatch: 'full', + canActivate: [vorgangListPageGuard], + children: [], + }, + { + path: 'alle', + title: 'Alle Vorgänge | Alfa', + component: VorgangListContainerComponent, + }, + { + path: 'alle/search/:search', + title: 'Suchergebnisseite | Alfa', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + { + path: 'alle/search', + canActivate: [vorgangFilterViewGuard], + component: VorgangListSearchContainerComponent, + }, + { + path: 'alle/:status', + title: 'Alle Vorgänge | Alfa', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + { + path: 'alle/wiedervorlagen', + title: 'Alle Vorgänge mit offenen Wiedervorlagen', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + { + path: 'meine', + title: 'Meine Vorgänge | Alfa', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + { + path: 'meine/search/:search', + title: 'Suchergebnis in meine Vorgänge | Alfa', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + { + path: 'meine/search', + canActivate: [vorgangFilterViewGuard], + component: VorgangListSearchContainerComponent, + }, + { + path: 'meine/:status', + title: 'Meine Vorgänge | Alfa', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + { + path: 'meine/wiedervorlagen', + title: 'Alle mir zugewiesenen Vorgänge mit offenen Wiedervorlagen', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + { + path: 'unassigned', + title: 'Nicht zugewiesen | Alfa', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + { + path: 'unassigned/search/:search', + title: 'Suchergebnis in nicht zugewiesen | Alfa', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + { + path: 'unassigned/search', + canActivate: [vorgangFilterViewGuard], + component: VorgangListSearchContainerComponent, + }, + { + path: 'unassigned/:status', + title: 'Nicht zugewiesen | Alfa', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + { + path: 'unassigned/wiedervorlagen', + title: 'Alle nicht zugewiesenen Vorgänge mit offenen Wiedervorlagen', + canActivate: [vorgangFilterViewGuard], + component: VorgangListContainerComponent, + }, + ], + }, + { + path: 'vorgang/:vorgangWithEingangUrl', + loadChildren: () => import('@alfa-client/vorgang-detail').then((m) => m.VorgangDetailModule), + title: 'Details zum Vorgang | Alfa', + }, ]; @NgModule({ - imports: [ - CommonModule, - TechSharedModule, - ScrollingModule, - UiModule, - RouterModule.forChild(routes), - VorgangSharedModule, - WiedervorlageModule, - VorgangSharedUiModule, - UserProfileModule, - MatButtonToggleModule, - HintModule, - ], - declarations: [ - VorgangListComponent, - VorgangListItemComponent, - VorgangListContainerComponent, - VorgangListPageComponent, - EmptyListComponent, - VorgangNextFristButton, - VorgangListPageContainerComponent, - VorgangFilterMenuContainerComponent, - VorgangFilterMenuComponent, - VorgangViewsMenuComponent, - VorgangSearchViewItemComponent, - VorgangSearchViewItemContainerComponent, - VorgangListSearchContainerComponent, - VorgangFilterMenuItemComponent, - VorgangCreatedAtComponent, - VorgangViewItemContainerComponent, - VorgangViewItemComponent, - VorgangViewsMenuContainerComponent, - VorgangListSearchComponent, - ], + imports: [ + CommonModule, + TechSharedModule, + ScrollingModule, + UiModule, + RouterModule.forChild(routes), + VorgangSharedModule, + WiedervorlageModule, + VorgangSharedUiModule, + UserProfileModule, + MatButtonToggleModule, + HintModule, + ], + declarations: [ + VorgangListComponent, + VorgangListItemComponent, + VorgangListContainerComponent, + VorgangListPageComponent, + EmptyListComponent, + VorgangNextFristButton, + VorgangListPageContainerComponent, + VorgangFilterMenuContainerComponent, + VorgangFilterMenuComponent, + VorgangViewsMenuComponent, + VorgangSearchViewItemComponent, + VorgangSearchViewItemContainerComponent, + VorgangListSearchContainerComponent, + VorgangFilterMenuItemComponent, + VorgangCreatedAtComponent, + VorgangViewItemContainerComponent, + VorgangViewItemComponent, + VorgangViewsMenuContainerComponent, + VorgangListSearchComponent, + ], }) export class VorgangModule {} diff --git a/alfa-client/libs/vorgang/src/test-setup.ts b/alfa-client/libs/vorgang/src/test-setup.ts index 5870fdabb6470fd0f6f3f63be3d4f6b8041b4dd2..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/vorgang/src/test-setup.ts +++ b/alfa-client/libs/vorgang/src/test-setup.ts @@ -26,17 +26,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/vorgang/tsconfig.json b/alfa-client/libs/vorgang/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/vorgang/tsconfig.json +++ b/alfa-client/libs/vorgang/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/vorgang/tsconfig.lib.json b/alfa-client/libs/vorgang/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/vorgang/tsconfig.lib.json +++ b/alfa-client/libs/vorgang/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/vorgang/tsconfig.spec.json b/alfa-client/libs/vorgang/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/vorgang/tsconfig.spec.json +++ b/alfa-client/libs/vorgang/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/wiedervorlage-shared/.eslintrc.json b/alfa-client/libs/wiedervorlage-shared/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/wiedervorlage-shared/.eslintrc.json +++ b/alfa-client/libs/wiedervorlage-shared/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/wiedervorlage-shared/jest.config.ts b/alfa-client/libs/wiedervorlage-shared/jest.config.ts index 738371753cbae1c3f458a9f076a8acf36cd560e8..f6c891974b9ccf85889fb0b5c43dc13c9e63c84b 100644 --- a/alfa-client/libs/wiedervorlage-shared/jest.config.ts +++ b/alfa-client/libs/wiedervorlage-shared/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'wiedervorlage-shared', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/wiedervorlage-shared', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'wiedervorlage-shared', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/wiedervorlage-shared', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/wiedervorlage-shared/project.json b/alfa-client/libs/wiedervorlage-shared/project.json index d62e6e3ece2379919298ad942f5abd8d8dd6bd0e..417bb7950d0c807445760282a9617fa516ea4f28 100644 --- a/alfa-client/libs/wiedervorlage-shared/project.json +++ b/alfa-client/libs/wiedervorlage-shared/project.json @@ -1,29 +1,29 @@ { - "name": "wiedervorlage-shared", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/wiedervorlage-shared/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/wiedervorlage-shared/src/**/*.ts", - "libs/wiedervorlage-shared/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/wiedervorlage-shared"], - "options": { - "tsConfig": "libs/wiedervorlage-shared/tsconfig.spec.json", - "jestConfig": "libs/wiedervorlage-shared/jest.config.ts", - "passWithNoTests": true - } - } - }, - "tags": [] + "name": "wiedervorlage-shared", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/wiedervorlage-shared/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": [ + "libs/wiedervorlage-shared/src/**/*.ts", + "libs/wiedervorlage-shared/src/**/*.html" + ] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/wiedervorlage-shared"], + "options": { + "tsConfig": "libs/wiedervorlage-shared/tsconfig.spec.json", + "jestConfig": "libs/wiedervorlage-shared/jest.config.ts", + "passWithNoTests": true + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage-shared.module.spec.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage-shared.module.spec.ts index 44ba75ba30538e91cc0f62815b859056a2115caf..7585c7e30e88192bff0a83aa22c32f65cd24d782 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage-shared.module.spec.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage-shared.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { WiedervorlageSharedModule } from './wiedervorlage-shared.module'; describe('WiedervorlageSharedModule', () => { - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [WiedervorlageSharedModule], - }).compileComponents(); - }); + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [WiedervorlageSharedModule], + }).compileComponents(); + }); - it('should create', () => { - expect(WiedervorlageSharedModule).toBeDefined(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(WiedervorlageSharedModule).toBeDefined(); + }); +}); diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage-shared.module.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage-shared.module.ts index 59f2bfa45d667d57db71e674efa0a843ea13b519..ef0580cbd675dc17aea810fba6988b6c48b57354 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage-shared.module.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage-shared.module.ts @@ -25,6 +25,6 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; @NgModule({ - imports: [CommonModule], + imports: [CommonModule], }) -export class WiedervorlageSharedModule { } +export class WiedervorlageSharedModule {} diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.linkrel.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.linkrel.ts index b9a81c1d0333d2de7bf57c67063e46f38a795fc6..819b6fc49c03f18b340a9fea1fc579d4b2211956 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.linkrel.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.linkrel.ts @@ -22,15 +22,15 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum WiedervorlageListLinkRel { - WIEDERVORLAGE_LIST = 'wiedervorlageList', - CREATE_WIEDERVORLAGE = 'create-wiedervorlage', - UPLOAD_FILE = 'uploadFile' + WIEDERVORLAGE_LIST = 'wiedervorlageList', + CREATE_WIEDERVORLAGE = 'create-wiedervorlage', + UPLOAD_FILE = 'uploadFile', } export enum WiedervorlageLinkRel { - EDIT = 'edit', - ERLEDIGEN = 'erledigen', - WIEDEREROEFFNEN = 'wiedereroeffnen', - ATTACHMENTS = 'attachments', - CREATED_BY = 'createdBy' + EDIT = 'edit', + ERLEDIGEN = 'erledigen', + WIEDEREROEFFNEN = 'wiedereroeffnen', + ATTACHMENTS = 'attachments', + CREATED_BY = 'createdBy', } diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.message.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.message.ts index 77d42050f83d62bfbc0a24a973a7b5038ff573ed..c561d96766936a941959d60001e737bba5173586 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.message.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.message.ts @@ -22,10 +22,10 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum WiedervorlageMessages { - NEW = 'Neue Wiedervorlage', - CREATED = 'Die Wiedervorlage "{betreff}" wurde angelegt', - SAVED = 'Die Wiedervorlage "{betreff}" wurde gespeichert', - TOOLTIP = '{betreff}, erstellt am {createdAt} von {firstName} {lastName}', - ERLEDIGT = 'Die Wiedervorlage {betreff} wurde erledigt', - WIEDEREROEFFNET = 'Die Wiedervorlage {betreff} wurde wiedereröffnet' -} \ No newline at end of file + NEW = 'Neue Wiedervorlage', + CREATED = 'Die Wiedervorlage "{betreff}" wurde angelegt', + SAVED = 'Die Wiedervorlage "{betreff}" wurde gespeichert', + TOOLTIP = '{betreff}, erstellt am {createdAt} von {firstName} {lastName}', + ERLEDIGT = 'Die Wiedervorlage {betreff} wurde erledigt', + WIEDEREROEFFNET = 'Die Wiedervorlage {betreff} wurde wiedereröffnet', +} diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.model.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.model.ts index 7a58cad195036695e3739427d77708503712a38a..b24c2d66850741f13a5f0b63a6f7b9284704a756 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.model.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.model.ts @@ -28,22 +28,22 @@ import { Resource, ResourceUri } from '@ngxp/rest'; import { BehaviorSubject } from 'rxjs'; export interface Wiedervorlage { - done: boolean; - betreff: string; - beschreibung: string; - frist: Date; - createdAt: Date; - attachments: ResourceUri[] | string + done: boolean; + betreff: string; + beschreibung: string; + frist: Date; + createdAt: Date; + attachments: ResourceUri[] | string; } -export interface WiedervorlageResource extends Wiedervorlage, Resource { } -export interface WiedervorlageListResource extends ListResource { } +export interface WiedervorlageResource extends Wiedervorlage, Resource {} +export interface WiedervorlageListResource extends ListResource {} export interface CreateWiedervorlageCommand extends CreateCommand { - order: CommandOrder, - wiedervorlage: Wiedervorlage + order: CommandOrder; + wiedervorlage: Wiedervorlage; } export interface BinaryFileListByWiedervorlageUri { - [uri: ResourceUri]: BehaviorSubject<StateResource<BinaryFileListResource>> -} \ No newline at end of file + [uri: ResourceUri]: BehaviorSubject<StateResource<BinaryFileListResource>>; +} diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.repository.spec.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.repository.spec.ts index a634b425c7daaa12b55b9f4f0e55069721583a87..73225f9d73eadef124962389b753568c6cd4211a 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.repository.spec.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.repository.spec.ts @@ -27,74 +27,77 @@ import { VorgangHeaderLinkRel, VorgangWithEingangResource } from '@alfa-client/v import { ResourceFactory, ResourceUri } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; -import { createWiedervorlageListResource, createWiedervorlageResource } from '../../test/wiedervorlage'; +import { + createWiedervorlageListResource, + createWiedervorlageResource, +} from '../../test/wiedervorlage'; import { WiedervorlageListResource, WiedervorlageResource } from './wiedervorlage.model'; import { WiedervorlageRepository } from './wiedervorlage.repository'; describe('WiedervorlageRepository', () => { - let repository: WiedervorlageRepository; - let resourceFactory = mock(ResourceFactory); - let resourceWrapper = { get: jest.fn() }; + let repository: WiedervorlageRepository; + let resourceFactory = mock(ResourceFactory); + let resourceWrapper = { get: jest.fn() }; - beforeEach(() => { - repository = new WiedervorlageRepository(useFromMock(resourceFactory)); - }) + beforeEach(() => { + repository = new WiedervorlageRepository(useFromMock(resourceFactory)); + }); - describe('loadWiedervorlagenList', () => { - const wiedervorlageListResource: WiedervorlageListResource = createWiedervorlageListResource(); - const vorgangResource: VorgangWithEingangResource = createVorgangWithEingangResource(); + describe('loadWiedervorlagenList', () => { + const wiedervorlageListResource: WiedervorlageListResource = createWiedervorlageListResource(); + const vorgangResource: VorgangWithEingangResource = createVorgangWithEingangResource(); - beforeEach(() => { - resourceFactory.from.mockReturnValue(resourceWrapper); - resourceWrapper.get.mockReturnValue(cold('a', { a: wiedervorlageListResource })); - }) + beforeEach(() => { + resourceFactory.from.mockReturnValue(resourceWrapper); + resourceWrapper.get.mockReturnValue(cold('a', { a: wiedervorlageListResource })); + }); - it('should call resourceFactory with resource', () => { - repository.getWiedervorlageList(vorgangResource); + it('should call resourceFactory with resource', () => { + repository.getWiedervorlageList(vorgangResource); - expect(resourceFactory.from).toHaveBeenCalledWith(vorgangResource); - }) + expect(resourceFactory.from).toHaveBeenCalledWith(vorgangResource); + }); - it('should call resourceWrapper with link', () => { - repository.getWiedervorlageList(vorgangResource); + it('should call resourceWrapper with link', () => { + repository.getWiedervorlageList(vorgangResource); - expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangHeaderLinkRel.WIEDERVORLAGEN); - }) + expect(resourceWrapper.get).toHaveBeenCalledWith(VorgangHeaderLinkRel.WIEDERVORLAGEN); + }); - it('should return result', () => { - let result = repository.getWiedervorlageList(vorgangResource); + it('should return result', () => { + let result = repository.getWiedervorlageList(vorgangResource); - expect(result).not.toBeNull(); - expect(result).toBeObservable(hot('a', { a: wiedervorlageListResource })); - }) - }) + expect(result).not.toBeNull(); + expect(result).toBeObservable(hot('a', { a: wiedervorlageListResource })); + }); + }); - describe('getWiedervorlage', () => { - const wiedervorlageUri: ResourceUri = faker.internet.url(); - const wiedervorlageResource: WiedervorlageResource = createWiedervorlageResource(); + describe('getWiedervorlage', () => { + const wiedervorlageUri: ResourceUri = faker.internet.url(); + const wiedervorlageResource: WiedervorlageResource = createWiedervorlageResource(); - beforeEach(() => { - resourceFactory.fromId.mockReturnValue(resourceWrapper); - resourceWrapper.get.mockReturnValue(cold('a', { a: wiedervorlageResource })); - }) + beforeEach(() => { + resourceFactory.fromId.mockReturnValue(resourceWrapper); + resourceWrapper.get.mockReturnValue(cold('a', { a: wiedervorlageResource })); + }); - it('should call resourceFactory with resource', () => { - repository.getWiedervorlage(wiedervorlageUri); + it('should call resourceFactory with resource', () => { + repository.getWiedervorlage(wiedervorlageUri); - expect(resourceFactory.fromId).toHaveBeenCalledWith(wiedervorlageUri); - }) + expect(resourceFactory.fromId).toHaveBeenCalledWith(wiedervorlageUri); + }); - it('should call resourceWrapper with link', () => { - repository.getWiedervorlage(wiedervorlageUri); + it('should call resourceWrapper with link', () => { + repository.getWiedervorlage(wiedervorlageUri); - expect(resourceWrapper.get).toHaveBeenCalled(); - }) + expect(resourceWrapper.get).toHaveBeenCalled(); + }); - it('should return result', () => { - let result = repository.getWiedervorlage(wiedervorlageUri); + it('should return result', () => { + let result = repository.getWiedervorlage(wiedervorlageUri); - expect(result).not.toBeNull(); - expect(result).toBeObservable(hot('a', { a: wiedervorlageResource })); - }) - }) -}) \ No newline at end of file + expect(result).not.toBeNull(); + expect(result).toBeObservable(hot('a', { a: wiedervorlageResource })); + }); + }); +}); diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.repository.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.repository.ts index bdfa0df1efee1a8a52bda91e5f5a797d2d54cc79..0dbcc864992aa530396cb7813d92898041ea5b55 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.repository.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.repository.ts @@ -29,14 +29,15 @@ import { WiedervorlageListResource, WiedervorlageResource } from './wiedervorlag @Injectable({ providedIn: 'root' }) export class WiedervorlageRepository { + constructor(private resourceFactory: ResourceFactory) {} - constructor(private resourceFactory: ResourceFactory) { } + public getWiedervorlageList( + vorgangResource: VorgangResource, + ): Observable<WiedervorlageListResource> { + return this.resourceFactory.from(vorgangResource).get(VorgangHeaderLinkRel.WIEDERVORLAGEN); + } - public getWiedervorlageList(vorgangResource: VorgangResource): Observable<WiedervorlageListResource> { - return this.resourceFactory.from(vorgangResource).get(VorgangHeaderLinkRel.WIEDERVORLAGEN); - } - - public getWiedervorlage(wiedervorlageUri: ResourceUri): Observable<WiedervorlageResource> { - return this.resourceFactory.fromId(wiedervorlageUri).get(); - } -} \ No newline at end of file + public getWiedervorlage(wiedervorlageUri: ResourceUri): Observable<WiedervorlageResource> { + return this.resourceFactory.fromId(wiedervorlageUri).get(); + } +} diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.route.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.route.ts index 301316f1762ab33c08567b9b7f2eb10fdd61a20b..a80623baebd2597cf5dd8ecb3475dcbcf0767ccc 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.route.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.route.ts @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ export enum WiedervorlageRoutes { - NEW = 'neu' + NEW = 'neu', } diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts index 737a87bdb0a26e836ec3b24145173747495e17b3..a6fda05d4aae0d6cbc82268e5e0ac05f1655af0b 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.spec.ts @@ -24,21 +24,41 @@ import { BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared'; import { CommandOrder, CommandResource, CommandService } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { StateResource, createEmptyStateResource, createStateResource, decodeUrlFromEmbedding } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createStateResource, + decodeUrlFromEmbedding, +} from '@alfa-client/tech-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { SnackBarService } from '@alfa-client/ui'; -import { VorgangResource, VorgangService, VorgangWithEingangResource } from '@alfa-client/vorgang-shared'; +import { + VorgangResource, + VorgangService, + VorgangWithEingangResource, +} from '@alfa-client/vorgang-shared'; import { getUrl } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; import { createBinaryFileListResource } from 'libs/binary-file-shared/test/binary-file'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; import { createCommandResource } from 'libs/command-shared/test/command'; -import { createVorgangResource, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; -import { createWiedervorlage, createWiedervorlageListResource, createWiedervorlageResource } from 'libs/wiedervorlage-shared/test/wiedervorlage'; +import { + createVorgangResource, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; +import { + createWiedervorlage, + createWiedervorlageListResource, + createWiedervorlageResource, +} from 'libs/wiedervorlage-shared/test/wiedervorlage'; import { of } from 'rxjs'; import { WiedervorlageLinkRel, WiedervorlageListLinkRel } from './wiedervorlage.linkrel'; import { WiedervorlageMessages } from './wiedervorlage.message'; -import { Wiedervorlage, WiedervorlageListResource, WiedervorlageResource } from './wiedervorlage.model'; +import { + Wiedervorlage, + WiedervorlageListResource, + WiedervorlageResource, +} from './wiedervorlage.model'; import { WiedervorlageRepository } from './wiedervorlage.repository'; import { WiedervorlageService } from './wiedervorlage.service'; @@ -47,479 +67,555 @@ import * as TechShared from '@alfa-client/tech-shared'; jest.mock('@alfa-client/tech-shared', () => mockAsEsModule('@alfa-client/tech-shared')); function mockAsEsModule(module: string) { - return { - __esModule: true, - ...jest.requireActual(module) - }; + return { + __esModule: true, + ...jest.requireActual(module), + }; } describe('WiedervorlageService', () => { - let service: WiedervorlageService; - let repository: Mock<WiedervorlageRepository>; - let navigationService: Mock<NavigationService>; - let commandService: Mock<CommandService>; - let snackbarService: Mock<SnackBarService>; - let binaryFileService: Mock<BinaryFileService>; - let vorgangService: Mock<VorgangService> = mock(VorgangService); + let service: WiedervorlageService; + let repository: Mock<WiedervorlageRepository>; + let navigationService: Mock<NavigationService>; + let commandService: Mock<CommandService>; + let snackbarService: Mock<SnackBarService>; + let binaryFileService: Mock<BinaryFileService>; + let vorgangService: Mock<VorgangService> = mock(VorgangService); + + const vorgangResource: VorgangWithEingangResource = createVorgangWithEingangResource(); + const wiedervorlageResource: WiedervorlageResource = createWiedervorlageResource(); + const wiedervorlage: Wiedervorlage = createWiedervorlage(); + const commandResource: CommandResource = createCommandResource(); + const commandResourceWithEffectedResourceLink: CommandResource = createCommandResource([ + CommandLinkRel.EFFECTED_RESOURCE, + ]); + + beforeEach(() => { + repository = mock(WiedervorlageRepository); + navigationService = mock(NavigationService); + commandService = mock(CommandService); + snackbarService = mock(SnackBarService); + binaryFileService = mock(BinaryFileService); + vorgangService = mock(VorgangService); + + navigationService.urlChanged.mockReturnValue(of({})); + + service = new WiedervorlageService( + useFromMock(repository), + useFromMock(navigationService), + useFromMock(commandService), + useFromMock(snackbarService), + useFromMock(binaryFileService), + useFromMock(vorgangService), + ); + }); + + describe('getWiedervorlageList', () => { + const wiedervorlageList: WiedervorlageListResource = createWiedervorlageListResource(); + const wiedervorlageListStateResource: StateResource<WiedervorlageListResource> = + createStateResource(wiedervorlageList); + + const vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource> = + createStateResource(vorgangResource); + + beforeEach(() => { + vorgangService.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); + }); + + it('should call vorgangFacade getVorgangWithEingang', () => { + service.getWiedervorlageList(); + + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); + + it('should return values', () => { + vorgangService.getVorgangWithEingang.mockReturnValue( + hot('-a', { a: vorgangWithEingangStateResource }), + ); + service.wiedervorlageList$.asObservable = jest + .fn() + .mockReturnValue(hot('-a', { a: wiedervorlageListStateResource })); + + const result = service.getWiedervorlageList(); + + expect(result).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: wiedervorlageListStateResource }), + ); + }); + + it.skip('should call loadWiedervorlagenByVorgang if required', (done) => { + service.loadWiedervorlagenByVorgang = jest.fn(); + // service.wiedervorlageList$.next({ ...wiedervorlageListStateResource, reload: true }); + + service.getWiedervorlageList().subscribe((list) => { + expect(service.loadWiedervorlagenByVorgang).toHaveBeenCalled(); + done(); + }); + // expect(service.loadWiedervorlagenByVorgang).toHaveBeenCalled(); + service.wiedervorlageList$.next({ ...wiedervorlageListStateResource, reload: true }); + // service.wiedervorlageList$.next({ ...wiedervorlageListStateResource, reload: true }); + service.getWiedervorlageList(); + }); + + it('should NOT call loadWiedervorlagenByVorgang if already loaded', () => { + service.loadWiedervorlagenByVorgang = jest.fn(); + service.wiedervorlageList$.asObservable = jest + .fn() + .mockReturnValue(of(wiedervorlageListStateResource)); + + service.getWiedervorlageList(); + + expect(service.loadWiedervorlagenByVorgang).not.toHaveBeenCalled(); + }); + }); + + describe('getWiedervorlageListByGivenVorgang', () => { + const vorgang: VorgangResource = createVorgangResource(); + const wiedervorlageListResource: WiedervorlageListResource = createWiedervorlageListResource(); + const wiedervorlageListStateResource: StateResource<WiedervorlageListResource> = + createStateResource(wiedervorlageListResource); + + it('should return initial value', () => { + service.wiedervorlageList$.asObservable = jest + .fn() + .mockReturnValue(hot('-a', { a: wiedervorlageListResource })); + + const result = service.getWiedervorlageListByGivenVorgang(vorgang); + + expect(result).toBeObservable(cold('-a', { a: wiedervorlageListResource })); + }); + + it('should load wiedervorlagen by vorgang if required', () => { + service.loadWiedervorlagenByVorgang = jest.fn(); + service.wiedervorlageList$.next(createEmptyStateResource()); + + service.getWiedervorlageListByGivenVorgang(vorgang).subscribe(); + + expect(service.loadWiedervorlagenByVorgang).toHaveBeenCalledWith(vorgang); + }); + + it('should NOT load wiedervorlagen by vorgang if already loaded', () => { + service.loadWiedervorlagenByVorgang = jest.fn(); + service.wiedervorlageList$.next(wiedervorlageListStateResource); - const vorgangResource: VorgangWithEingangResource = createVorgangWithEingangResource(); - const wiedervorlageResource: WiedervorlageResource = createWiedervorlageResource(); - const wiedervorlage: Wiedervorlage = createWiedervorlage(); - const commandResource: CommandResource = createCommandResource(); - const commandResourceWithEffectedResourceLink: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); + service.getWiedervorlageListByGivenVorgang(vorgang).subscribe(); - beforeEach(() => { - repository = mock(WiedervorlageRepository); - navigationService = mock(NavigationService); - commandService = mock(CommandService); - snackbarService = mock(SnackBarService); - binaryFileService = mock(BinaryFileService); - vorgangService = mock(VorgangService); + expect(service.loadWiedervorlagenByVorgang).not.toHaveBeenCalled(); + }); + }); + + describe('getWiedervorlage', () => { + const wiedervorlage: WiedervorlageResource = createWiedervorlageResource(); + const wiedervorlageStateResource: StateResource<WiedervorlageResource> = + createStateResource(wiedervorlage); + + beforeEach(() => { + navigationService.getDecodedParam.mockReturnValue(getUrl(wiedervorlageResource)); + repository.getWiedervorlage.mockReturnValue(of(wiedervorlageResource)); + }); + + it('should return initial values', () => { + service.wiedervorlage$.asObservable = jest + .fn() + .mockReturnValue(hot('-a', { a: wiedervorlageStateResource })); + + const result = service.getWiedervorlage(); + + expect(result).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: wiedervorlageStateResource }), + ); + }); + + it('should set loading to true', () => { + service.setWiedervorlageLoading = jest.fn(); + + service.getWiedervorlage().subscribe(); + + expect(service.setWiedervorlageLoading).toHaveBeenCalled(); + }); - navigationService.urlChanged.mockReturnValue(of({})); + it('should call navigationService', () => { + service.getWiedervorlage().subscribe(); - service = new WiedervorlageService( - useFromMock(repository), - useFromMock(navigationService), - useFromMock(commandService), - useFromMock(snackbarService), - useFromMock(binaryFileService), - useFromMock(vorgangService) - ); - }) + expect(navigationService.getDecodedParam).toHaveBeenCalledWith( + WiedervorlageService.encodedWiedervorlageUriParam, + ); + }); - describe('getWiedervorlageList', () => { + it('should call repository', () => { + service.getWiedervorlage().subscribe(); + + expect(repository.getWiedervorlage).toHaveBeenCalledWith(getUrl(wiedervorlageResource)); + }); + + it('should set returnvalue', () => { + service.getWiedervorlage().subscribe(); - const wiedervorlageList: WiedervorlageListResource = createWiedervorlageListResource(); - const wiedervorlageListStateResource: StateResource<WiedervorlageListResource> = createStateResource(wiedervorlageList); + expect(service.wiedervorlage$.value).toEqual(createStateResource(wiedervorlageResource)); + }); + }); - const vorgangWithEingangStateResource: StateResource<VorgangWithEingangResource> = createStateResource(vorgangResource); + describe('saveWiedervorlage', () => { + beforeEach(() => { + commandService.createCommand.mockReturnValue( + of(createStateResource(commandResourceWithEffectedResourceLink)), + ); + }); - beforeEach(() => { - vorgangService.getVorgangWithEingang.mockReturnValue(of(vorgangWithEingangStateResource)); - }) + it('should return initial value and mapped value', () => { + commandService.createCommand.mockReturnValue( + hot('-a', { a: createStateResource(commandResourceWithEffectedResourceLink) }), + ); + + const result = service.saveWiedervorlage(wiedervorlageResource, wiedervorlage); + + expect(result).toBeObservable( + cold('ab', { + a: createEmptyStateResource(true), + b: createStateResource(commandResourceWithEffectedResourceLink), + }), + ); + }); - it('should call vorgangFacade getVorgangWithEingang', () => { - service.getWiedervorlageList(); + it('should call command service', () => { + service.saveWiedervorlage(wiedervorlageResource, wiedervorlage).subscribe(); - expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); - }) + expect(commandService.createCommand).toHaveBeenCalledWith( + wiedervorlageResource, + WiedervorlageLinkRel.EDIT, + { order: CommandOrder.EDIT_WIEDERVORLAGE, wiedervorlage, body: null }, + ); + }); + + it('should set submit-in-progress on loading', () => { + (<any>service).setSubmitInProgressLoading = jest.fn(); + + service.saveWiedervorlage(wiedervorlageResource, wiedervorlage); + + expect((<any>service).setSubmitInProgressLoading).toHaveBeenCalled(); + }); + + it('should call proceedAfterRecieveCommand', () => { + service.proceedAfterReceiveCommand = jest.fn(); + + service.saveWiedervorlage(wiedervorlageResource, wiedervorlage).subscribe(); + + const expectedMessage = WiedervorlageMessages.SAVED.replace( + '{betreff}', + wiedervorlage.betreff, + ); + expect(service.proceedAfterReceiveCommand).toHaveBeenCalledWith( + createStateResource(commandResourceWithEffectedResourceLink), + expectedMessage, + ); + }); + }); + + describe('createWiedervorlage', () => { + beforeEach(() => { + commandService.createCommand.mockReturnValue(of(createStateResource(commandResource))); + }); + + it('should return intitial value and mapped value', () => { + commandService.createCommand.mockReturnValue( + hot('-a', { a: createStateResource(commandResource) }), + ); + + const result = service.createWiedervorlage(wiedervorlage); + + expect(result).toBeObservable( + cold('ab', { a: createEmptyStateResource(true), b: createStateResource(commandResource) }), + ); + }); + + it('should set submit-in-progress on loading', () => { + (<any>service).setSubmitInProgressLoading = jest.fn(); + + service.createWiedervorlage(wiedervorlage); + + expect((<any>service).setSubmitInProgressLoading).toHaveBeenCalled(); + }); + + it('should call command service', () => { + service.createWiedervorlage(wiedervorlage).subscribe(); + + const command = { order: CommandOrder.CREATE_WIEDERVORLAGE, wiedervorlage, body: null }; + expect(commandService.createCommand).toHaveBeenCalledWith( + service.wiedervorlageList$.value.resource, + WiedervorlageListLinkRel.CREATE_WIEDERVORLAGE, + command, + ); + }); + + it('should call proceedAfterReceiveCommand', () => { + service.proceedAfterReceiveCommand = jest.fn(); + + service.createWiedervorlage(wiedervorlage).subscribe(); + + const expectedMessage = WiedervorlageMessages.CREATED.replace( + '{betreff}', + wiedervorlage.betreff, + ); + expect(service.proceedAfterReceiveCommand).toHaveBeenCalledWith( + createStateResource(commandResource), + expectedMessage, + ); + }); + }); + + describe('proceedAfterRecieveCommand', () => { + it('should set reload on wiedervorlageList', () => { + service.proceedAfterReceiveCommand( + createStateResource(commandResourceWithEffectedResourceLink), + null, + ); + + expect(service.wiedervorlageList$.value.reload).toBe(true); + }); + + it('should do nothing on apiError', () => { + service.proceedAfterReceiveCommand(createEmptyStateResource(), null); + + expect(service.wiedervorlageList$.value.reload).toBe(false); + }); + + it('should call show snackbar', () => { + snackbarService.show = jest.fn(); + const snackbarMessage: string = 'XX wurde XX'; + + service.proceedAfterReceiveCommand( + createStateResource(commandResourceWithEffectedResourceLink), + snackbarMessage, + ); + + expect(snackbarService.show).toHaveBeenCalledWith( + commandResourceWithEffectedResourceLink, + snackbarMessage, + ); + }); + }); + + describe('order actions', () => { + const wiedervorlageResource: WiedervorlageResource = createWiedervorlageResource(); + + beforeEach(() => { + commandService.createCommand.mockReturnValue( + of(createStateResource(commandResourceWithEffectedResourceLink)), + ); + (<any>service).reloadWiedervorlageList = jest.fn(); + (<any>service).loadAndSetWiedervorlageByUrl = jest.fn(); + + service.wiedervorlage$.next(createStateResource(wiedervorlageResource)); + }); + + describe('wiedervorlage erledigen', () => { + it('should call commandService', () => { + service.erledigen(); + + expect(commandService.createCommand).toHaveBeenCalledWith( + wiedervorlageResource, + WiedervorlageLinkRel.ERLEDIGEN, + { order: CommandOrder.WIEDERVORLAGE_ERLEDIGEN, body: null }, + ); + }); + + it('should reload wiedervorlage', () => { + service.erledigen(); + + expect((<any>service).loadAndSetWiedervorlageByUrl).toHaveBeenCalled(); + }); + + it('should show snackbar', () => { + service.erledigen(); + + expect(snackbarService.show).toHaveBeenCalledWith( + commandResourceWithEffectedResourceLink, + `Die Wiedervorlage ${wiedervorlageResource.betreff} wurde erledigt`, + ); + }); + }); + + describe('wiedervorlage wiedereroeffnen', () => { + it('should call commandService', () => { + service.wiedereroeffnen(); + + expect(commandService.createCommand).toHaveBeenCalledWith( + wiedervorlageResource, + WiedervorlageLinkRel.WIEDEREROEFFNEN, + { order: CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN, body: null }, + ); + }); + + it('should reload wiedervorlage', () => { + service.wiedereroeffnen(); + + expect((<any>service).loadAndSetWiedervorlageByUrl).toHaveBeenCalled(); + }); + + it('should show snackbar', () => { + service.wiedereroeffnen(); + + expect(snackbarService.show).toHaveBeenCalledWith( + commandResourceWithEffectedResourceLink, + `Die Wiedervorlage ${wiedervorlageResource.betreff} wurde wiedereröffnet`, + ); + }); + }); + }); - it('should return values', () => { - vorgangService.getVorgangWithEingang.mockReturnValue(hot('-a', { a: vorgangWithEingangStateResource })); - service.wiedervorlageList$.asObservable = jest.fn().mockReturnValue(hot('-a', { a: wiedervorlageListStateResource })); + describe('showSnackbar', () => { + const message: string = 'SnackbarMessage'; - const result = service.getWiedervorlageList(); + it('should call service if command is done', () => { + const commandResource: CommandResource = createCommandResource([ + CommandLinkRel.EFFECTED_RESOURCE, + ]); - expect(result).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: wiedervorlageListStateResource })); - }) + service.showSnackBar(commandResource, message); - it.skip('should call loadWiedervorlagenByVorgang if required', (done) => { - service.loadWiedervorlagenByVorgang = jest.fn(); - // service.wiedervorlageList$.next({ ...wiedervorlageListStateResource, reload: true }); + expect(snackbarService.show).toHaveBeenCalledWith(commandResource, message); + }); - service.getWiedervorlageList().subscribe(list => { - expect(service.loadWiedervorlagenByVorgang).toHaveBeenCalled(); - done(); - }); - // expect(service.loadWiedervorlagenByVorgang).toHaveBeenCalled(); - service.wiedervorlageList$.next({ ...wiedervorlageListStateResource, reload: true }); - // service.wiedervorlageList$.next({ ...wiedervorlageListStateResource, reload: true }); - service.getWiedervorlageList() - }) + it('should NOT call service if command is pending', () => { + const commandResource: CommandResource = createCommandResource(); - it('should NOT call loadWiedervorlagenByVorgang if already loaded', () => { - service.loadWiedervorlagenByVorgang = jest.fn(); - service.wiedervorlageList$.asObservable = jest.fn().mockReturnValue(of(wiedervorlageListStateResource)); + service.showSnackBar(commandResource, message); - service.getWiedervorlageList(); + expect(snackbarService.show).not.toHaveBeenCalled(); + }); + }); + + describe('on navigation', () => { + beforeEach(() => { + (<any>service).navigateToVorgangDetailPage = jest.fn(); + + service.setWiedervorlageListReload = jest.fn(); + (<any>service).forceWiedervorlageReload = jest.fn(); + service.clearAttachmentList = jest.fn(); + service.clearWiedervorlagenList = jest.fn(); + }); - expect(service.loadWiedervorlagenByVorgang).not.toHaveBeenCalled(); - }) - }) + describe('to vorgang detail', () => { + beforeEach(() => { + (<any>service).navigateToVorgangDetailPage.mockReturnValue(true); + }); + + it('should set wiedervorlage list on reload', () => { + service.onNavigation({}); - describe('getWiedervorlageListByGivenVorgang', () => { + expect(service.setWiedervorlageListReload).toHaveBeenCalled(); + }); - const vorgang: VorgangResource = createVorgangResource(); - const wiedervorlageListResource: WiedervorlageListResource = createWiedervorlageListResource(); - const wiedervorlageListStateResource: StateResource<WiedervorlageListResource> = createStateResource(wiedervorlageListResource); + it('should set wiedervorlage on reload', () => { + service.onNavigation({}); - it('should return initial value', () => { - service.wiedervorlageList$.asObservable = jest.fn().mockReturnValue(hot('-a', { a: wiedervorlageListResource })); + expect((<any>service).forceWiedervorlageReload).toHaveBeenCalled(); + }); - const result = service.getWiedervorlageListByGivenVorgang(vorgang); + it('should clear attachments', () => { + service.onNavigation({}); - expect(result).toBeObservable(cold('-a', { a: wiedervorlageListResource })); - }) + expect(service.clearAttachmentList).toHaveBeenCalled(); + }); + }); - it('should load wiedervorlagen by vorgang if required', () => { - service.loadWiedervorlagenByVorgang = jest.fn(); - service.wiedervorlageList$.next(createEmptyStateResource()); + describe('to vorgang list', () => { + it('should clear list', () => { + service.onNavigation({}); - service.getWiedervorlageListByGivenVorgang(vorgang).subscribe(); + expect(service.clearWiedervorlagenList).toHaveBeenCalled(); + }); - expect(service.loadWiedervorlagenByVorgang).toHaveBeenCalledWith(vorgang); - }) + it('should clear attachments', () => { + service.onNavigation({}); - it('should NOT load wiedervorlagen by vorgang if already loaded', () => { - service.loadWiedervorlagenByVorgang = jest.fn(); - service.wiedervorlageList$.next(wiedervorlageListStateResource); + expect(service.clearAttachmentList).toHaveBeenCalled(); + }); + }); + }); - service.getWiedervorlageListByGivenVorgang(vorgang).subscribe(); + describe('load attachments', () => { + const binaryFileListResource: BinaryFileListResource = createBinaryFileListResource(); + const binaryFileStateResource: StateResource<BinaryFileListResource> = + createStateResource(binaryFileListResource); - expect(service.loadWiedervorlagenByVorgang).not.toHaveBeenCalled(); - }) - }) + beforeEach(() => { + binaryFileService.getFiles.mockReturnValue(of(binaryFileStateResource)); + service.setAttachmentLoading = jest.fn(); + }); - describe('getWiedervorlage', () => { + it('should set attachment state resource on loading', () => { + service.loadAttachments(wiedervorlageResource); - const wiedervorlage: WiedervorlageResource = createWiedervorlageResource(); - const wiedervorlageStateResource: StateResource<WiedervorlageResource> = createStateResource(wiedervorlage); + expect(service.setAttachmentLoading).toHaveBeenCalledWith(wiedervorlageResource); + }); - beforeEach(() => { - navigationService.getDecodedParam.mockReturnValue(getUrl(wiedervorlageResource)); - repository.getWiedervorlage.mockReturnValue(of(wiedervorlageResource)); - }) + it('should call file service', () => { + service.loadAttachments(wiedervorlageResource); - it('should return initial values', () => { - service.wiedervorlage$.asObservable = jest.fn().mockReturnValue(hot('-a', { a: wiedervorlageStateResource })); + expect(binaryFileService.getFiles).toHaveBeenCalledWith( + wiedervorlageResource, + WiedervorlageLinkRel.ATTACHMENTS, + ); + }); - const result = service.getWiedervorlage(); + it('should set loaded resource into state resource', () => { + service.loadAttachments(wiedervorlageResource); - expect(result).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: wiedervorlageStateResource })); - }) + service.getAttachmentList(wiedervorlageResource); + const result: StateResource<BinaryFileListResource> = + service.attachmentListByWiedervorlage[getUrl(wiedervorlageResource)].value; - it('should set loading to true', () => { - service.setWiedervorlageLoading = jest.fn(); + expect(result).toEqual(binaryFileStateResource); + }); + }); - service.getWiedervorlage().subscribe(); + describe('loadWiedervorlagenByVorgangStrict', () => { + const wiedervorlageListResource: WiedervorlageListResource = createWiedervorlageListResource(); - expect(service.setWiedervorlageLoading).toHaveBeenCalled(); - }) + beforeEach(() => { + repository.getWiedervorlageList.mockReturnValue(hot('-a', { a: wiedervorlageListResource })); + }); - it('should call navigationService', () => { - service.getWiedervorlage().subscribe(); + it('should return value', () => { + const result = service.loadWiedervorlagenByVorgangStrict(vorgangResource); - expect(navigationService.getDecodedParam).toHaveBeenCalledWith(WiedervorlageService.encodedWiedervorlageUriParam); - }) + expect(result).toBeObservable( + cold('ab', { + a: createEmptyStateResource(true), + b: createStateResource(wiedervorlageListResource), + }), + ); + }); - it('should call repository', () => { - service.getWiedervorlage().subscribe(); + it('should call repository', () => { + service.loadWiedervorlagenByVorgangStrict(vorgangResource); - expect(repository.getWiedervorlage).toHaveBeenCalledWith(getUrl(wiedervorlageResource)); - }) + expect(repository.getWiedervorlageList).toHaveBeenCalledWith(vorgangResource); + }); + }); - it('should set returnvalue', () => { - service.getWiedervorlage().subscribe(); + describe('hasEditLink', () => { + beforeEach(() => { + navigationService.getDecodedParam.mockReturnValue(getUrl(wiedervorlageResource)); + repository.getWiedervorlage.mockReturnValue(of(wiedervorlageResource)); + }); - expect(service.wiedervorlage$.value).toEqual(createStateResource(wiedervorlageResource)); - }) - }) + it('should call decodeUrlFromEmbedding', () => { + const spy = jest.spyOn(TechShared, 'decodeUrlFromEmbedding'); - describe('saveWiedervorlage', () => { + service.hasEditLink(getUrl(wiedervorlageResource)); - beforeEach(() => { - commandService.createCommand.mockReturnValue(of(createStateResource(commandResourceWithEffectedResourceLink))); - }) + expect(spy).toHaveBeenCalled(); + }); - it('should return initial value and mapped value', () => { - commandService.createCommand.mockReturnValue(hot('-a', { a: createStateResource(commandResourceWithEffectedResourceLink) })); + it('should call repository.getWiedervorlage', () => { + const url: string = getUrl(wiedervorlageResource); + const decodedUrl: string = decodeUrlFromEmbedding(url); - const result = service.saveWiedervorlage(wiedervorlageResource, wiedervorlage); + service.hasEditLink(url); - expect(result).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: createStateResource(commandResourceWithEffectedResourceLink) })); - }) - - it('should call command service', () => { - service.saveWiedervorlage(wiedervorlageResource, wiedervorlage).subscribe(); - - expect(commandService.createCommand).toHaveBeenCalledWith(wiedervorlageResource, WiedervorlageLinkRel.EDIT, { order: CommandOrder.EDIT_WIEDERVORLAGE, wiedervorlage, body: null }); - }) - - it('should set submit-in-progress on loading', () => { - (<any>service).setSubmitInProgressLoading = jest.fn(); - - service.saveWiedervorlage(wiedervorlageResource, wiedervorlage); - - expect((<any>service).setSubmitInProgressLoading).toHaveBeenCalled(); - }) - - it('should call proceedAfterRecieveCommand', () => { - service.proceedAfterReceiveCommand = jest.fn(); - - service.saveWiedervorlage(wiedervorlageResource, wiedervorlage).subscribe(); - - const expectedMessage = WiedervorlageMessages.SAVED.replace('{betreff}', wiedervorlage.betreff); - expect(service.proceedAfterReceiveCommand).toHaveBeenCalledWith(createStateResource(commandResourceWithEffectedResourceLink), expectedMessage); - }) - }) - - describe('createWiedervorlage', () => { - - beforeEach(() => { - commandService.createCommand.mockReturnValue(of(createStateResource(commandResource))); - }) - - it('should return intitial value and mapped value', () => { - commandService.createCommand.mockReturnValue(hot('-a', { a: createStateResource(commandResource) })); - - const result = service.createWiedervorlage(wiedervorlage); - - expect(result).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: createStateResource(commandResource) })); - }) - - it('should set submit-in-progress on loading', () => { - (<any>service).setSubmitInProgressLoading = jest.fn(); - - service.createWiedervorlage(wiedervorlage); - - expect((<any>service).setSubmitInProgressLoading).toHaveBeenCalled(); - }) - - it('should call command service', () => { - service.createWiedervorlage(wiedervorlage).subscribe(); - - const command = { order: CommandOrder.CREATE_WIEDERVORLAGE, wiedervorlage, body: null }; - expect(commandService.createCommand).toHaveBeenCalledWith(service.wiedervorlageList$.value.resource, WiedervorlageListLinkRel.CREATE_WIEDERVORLAGE, command); - }) - - it('should call proceedAfterReceiveCommand', () => { - service.proceedAfterReceiveCommand = jest.fn(); - - service.createWiedervorlage(wiedervorlage).subscribe(); - - const expectedMessage = WiedervorlageMessages.CREATED.replace('{betreff}', wiedervorlage.betreff); - expect(service.proceedAfterReceiveCommand).toHaveBeenCalledWith(createStateResource(commandResource), expectedMessage); - }) - }) - - describe('proceedAfterRecieveCommand', () => { - - it('should set reload on wiedervorlageList', () => { - service.proceedAfterReceiveCommand(createStateResource(commandResourceWithEffectedResourceLink), null); - - expect(service.wiedervorlageList$.value.reload).toBe(true); - }) - - it('should do nothing on apiError', () => { - service.proceedAfterReceiveCommand(createEmptyStateResource(), null); - - expect(service.wiedervorlageList$.value.reload).toBe(false); - }) - - it('should call show snackbar', () => { - snackbarService.show = jest.fn(); - const snackbarMessage: string = 'XX wurde XX'; - - service.proceedAfterReceiveCommand(createStateResource(commandResourceWithEffectedResourceLink), snackbarMessage); - - expect(snackbarService.show).toHaveBeenCalledWith(commandResourceWithEffectedResourceLink, snackbarMessage); - }); - }) - - describe('order actions', () => { - const wiedervorlageResource: WiedervorlageResource = createWiedervorlageResource(); - - beforeEach(() => { - commandService.createCommand.mockReturnValue(of(createStateResource(commandResourceWithEffectedResourceLink))); - (<any>service).reloadWiedervorlageList = jest.fn(); - (<any>service).loadAndSetWiedervorlageByUrl = jest.fn(); - - service.wiedervorlage$.next(createStateResource(wiedervorlageResource)); - }) - - describe('wiedervorlage erledigen', () => { - - it('should call commandService', () => { - service.erledigen(); - - expect(commandService.createCommand).toHaveBeenCalledWith(wiedervorlageResource, WiedervorlageLinkRel.ERLEDIGEN, { order: CommandOrder.WIEDERVORLAGE_ERLEDIGEN, body: null }); - }) - - it('should reload wiedervorlage', () => { - service.erledigen(); - - expect((<any>service).loadAndSetWiedervorlageByUrl).toHaveBeenCalled(); - }) - - it('should show snackbar', () => { - service.erledigen(); - - expect(snackbarService.show).toHaveBeenCalledWith(commandResourceWithEffectedResourceLink, `Die Wiedervorlage ${wiedervorlageResource.betreff} wurde erledigt`); - }) - }) - - describe('wiedervorlage wiedereroeffnen', () => { - - it('should call commandService', () => { - service.wiedereroeffnen(); - - expect(commandService.createCommand).toHaveBeenCalledWith(wiedervorlageResource, WiedervorlageLinkRel.WIEDEREROEFFNEN, { order: CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN, body: null }); - }); - - it('should reload wiedervorlage', () => { - service.wiedereroeffnen(); - - expect((<any>service).loadAndSetWiedervorlageByUrl).toHaveBeenCalled(); - }); - - it('should show snackbar', () => { - service.wiedereroeffnen(); - - expect(snackbarService.show).toHaveBeenCalledWith(commandResourceWithEffectedResourceLink, `Die Wiedervorlage ${wiedervorlageResource.betreff} wurde wiedereröffnet`); - }) - }) - }) - - describe('showSnackbar', () => { - - const message: string = 'SnackbarMessage'; - - it('should call service if command is done', () => { - const commandResource: CommandResource = createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]); - - service.showSnackBar(commandResource, message); - - expect(snackbarService.show).toHaveBeenCalledWith(commandResource, message); - }) - - it('should NOT call service if command is pending', () => { - const commandResource: CommandResource = createCommandResource(); - - service.showSnackBar(commandResource, message); - - expect(snackbarService.show).not.toHaveBeenCalled(); - }) - }) - - describe('on navigation', () => { - - beforeEach(() => { - (<any>service).navigateToVorgangDetailPage = jest.fn(); - - service.setWiedervorlageListReload = jest.fn(); - (<any>service).forceWiedervorlageReload = jest.fn(); - service.clearAttachmentList = jest.fn(); - service.clearWiedervorlagenList = jest.fn(); - }) - - describe('to vorgang detail', () => { - - beforeEach(() => { - (<any>service).navigateToVorgangDetailPage.mockReturnValue(true); - }) - - it('should set wiedervorlage list on reload', () => { - service.onNavigation({}); - - expect(service.setWiedervorlageListReload).toHaveBeenCalled(); - }) - - it('should set wiedervorlage on reload', () => { - service.onNavigation({}); - - expect((<any>service).forceWiedervorlageReload).toHaveBeenCalled(); - }) - - it('should clear attachments', () => { - service.onNavigation({}); - - expect(service.clearAttachmentList).toHaveBeenCalled(); - }) - }) - - describe('to vorgang list', () => { - - it('should clear list', () => { - service.onNavigation({}); - - expect(service.clearWiedervorlagenList).toHaveBeenCalled(); - }) - - it('should clear attachments', () => { - service.onNavigation({}); - - expect(service.clearAttachmentList).toHaveBeenCalled(); - }) - }) - }) - - describe('load attachments', () => { - - const binaryFileListResource: BinaryFileListResource = createBinaryFileListResource(); - const binaryFileStateResource: StateResource<BinaryFileListResource> = createStateResource(binaryFileListResource); - - beforeEach(() => { - binaryFileService.getFiles.mockReturnValue(of(binaryFileStateResource)); - service.setAttachmentLoading = jest.fn(); - }) - - it('should set attachment state resource on loading', () => { - service.loadAttachments(wiedervorlageResource); - - expect(service.setAttachmentLoading).toHaveBeenCalledWith(wiedervorlageResource); - }) - - it('should call file service', () => { - service.loadAttachments(wiedervorlageResource); - - expect(binaryFileService.getFiles).toHaveBeenCalledWith(wiedervorlageResource, WiedervorlageLinkRel.ATTACHMENTS); - }) - - it('should set loaded resource into state resource', () => { - service.loadAttachments(wiedervorlageResource); - - service.getAttachmentList(wiedervorlageResource); - const result: StateResource<BinaryFileListResource> = service.attachmentListByWiedervorlage[getUrl(wiedervorlageResource)].value; - - expect(result).toEqual(binaryFileStateResource); - }) - }) - - describe('loadWiedervorlagenByVorgangStrict', () => { - - const wiedervorlageListResource: WiedervorlageListResource = createWiedervorlageListResource(); - - beforeEach(() => { - repository.getWiedervorlageList.mockReturnValue(hot('-a', { a: wiedervorlageListResource })); - }) - - it('should return value', () => { - const result = service.loadWiedervorlagenByVorgangStrict(vorgangResource); - - expect(result).toBeObservable(cold('ab', { a: createEmptyStateResource(true), b: createStateResource(wiedervorlageListResource) })); - }) - - it('should call repository', () => { - service.loadWiedervorlagenByVorgangStrict(vorgangResource); - - expect(repository.getWiedervorlageList).toHaveBeenCalledWith(vorgangResource); - }) - }) - - describe('hasEditLink', () => { - - beforeEach(() => { - navigationService.getDecodedParam.mockReturnValue(getUrl(wiedervorlageResource)); - repository.getWiedervorlage.mockReturnValue(of(wiedervorlageResource)); - }) - - it('should call decodeUrlFromEmbedding', () => { - const spy = jest.spyOn(TechShared, 'decodeUrlFromEmbedding'); - - service.hasEditLink(getUrl(wiedervorlageResource)); - - expect(spy).toHaveBeenCalled(); - }) - - it('should call repository.getWiedervorlage', () => { - const url: string = getUrl(wiedervorlageResource); - const decodedUrl: string = decodeUrlFromEmbedding(url); - - service.hasEditLink(url); - - expect(repository.getWiedervorlage).toHaveBeenCalledWith(decodedUrl); - }) - - }) -}) \ No newline at end of file + expect(repository.getWiedervorlage).toHaveBeenCalledWith(decodedUrl); + }); + }); +}); diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts index ecb26ca5932e88f29d05b33b826df8dbeb0fdabf..a96d7ca4e7cd27b2936a41b5b91e9fcbfc1f853d 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.service.ts @@ -22,9 +22,26 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { BinaryFileListResource, BinaryFileService } from '@alfa-client/binary-file-shared'; -import { Command, CommandOrder, CommandResource, CommandService, CreateCommand, isDone } from '@alfa-client/command-shared'; +import { + Command, + CommandOrder, + CommandResource, + CommandService, + CreateCommand, + isDone, +} from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; -import { StateResource, createEmptyStateResource, createStateResource, decodeUrlFromEmbedding, doIfLoadingRequired, hasError, isNotNull, isNotUndefined, replacePlaceholder } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createStateResource, + decodeUrlFromEmbedding, + doIfLoadingRequired, + hasError, + isNotNull, + isNotUndefined, + replacePlaceholder, +} from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; import { VorgangHeaderLinkRel, VorgangResource, VorgangService } from '@alfa-client/vorgang-shared'; import { Injectable, OnDestroy } from '@angular/core'; @@ -35,295 +52,405 @@ import { BehaviorSubject, Observable, Subscription, combineLatest } from 'rxjs'; import { filter, map, startWith, tap } from 'rxjs/operators'; import { WiedervorlageLinkRel, WiedervorlageListLinkRel } from './wiedervorlage.linkrel'; import { WiedervorlageMessages } from './wiedervorlage.message'; -import { BinaryFileListByWiedervorlageUri, CreateWiedervorlageCommand, Wiedervorlage, WiedervorlageListResource, WiedervorlageResource } from './wiedervorlage.model'; +import { + BinaryFileListByWiedervorlageUri, + CreateWiedervorlageCommand, + Wiedervorlage, + WiedervorlageListResource, + WiedervorlageResource, +} from './wiedervorlage.model'; import { WiedervorlageRepository } from './wiedervorlage.repository'; import { WiedervorlageRoutes } from './wiedervorlage.route'; import { createErledigenCommand, createWiedereroeffnenCommand } from './wiedervorlage.util'; - @Injectable({ providedIn: 'root' }) export class WiedervorlageService implements OnDestroy { - - static encodedWiedervorlageUriParam: string = 'wiedervorlageUrl'; - - readonly wiedervorlageList$: BehaviorSubject<StateResource<WiedervorlageListResource>> = new BehaviorSubject<StateResource<WiedervorlageListResource>>(createEmptyStateResource<WiedervorlageListResource>()); - readonly wiedervorlage$: BehaviorSubject<StateResource<WiedervorlageResource>> = new BehaviorSubject<StateResource<WiedervorlageResource>>(createEmptyStateResource<WiedervorlageResource>()); - - readonly submitInProgress$: BehaviorSubject<StateResource<CommandResource>> = new BehaviorSubject<StateResource<CommandResource>>(createEmptyStateResource<CommandResource>()); - - readonly erledigenCommand$: BehaviorSubject<StateResource<CommandResource>> = new BehaviorSubject<StateResource<CommandResource>>(createEmptyStateResource<CommandResource>()); - readonly wiedereroeffnenCommand$: BehaviorSubject<StateResource<CommandResource>> = new BehaviorSubject<StateResource<CommandResource>>(createEmptyStateResource<CommandResource>()); - - attachmentListByWiedervorlage = <BinaryFileListByWiedervorlageUri>{}; - - private subscription: Subscription; - private attachmentSubscription: Subscription; - - constructor( - private repository: WiedervorlageRepository, - private navigationService: NavigationService, - private commandService: CommandService, - private snackbarService: SnackBarService, - private binaryFileService: BinaryFileService, - private vorgangService: VorgangService - ) { - this.listenToNavigation(); - } - - public getWiedervorlageList(): Observable<StateResource<WiedervorlageListResource>> { - return combineLatest([this.wiedervorlageList$.asObservable(), this.vorgangService.getVorgangWithEingang()]).pipe( - tap(([wiedervorlageList, vorgangResource]) => { - if(isNotNull(vorgangResource.resource)){ - doIfLoadingRequired(wiedervorlageList, () => this.loadWiedervorlagenByVorgang(vorgangResource.resource)); - } - }), - map(([wiedervorlageList,]) => wiedervorlageList), - startWith(createEmptyStateResource<WiedervorlageListResource>(true)) - ) - } - - public getWiedervorlageListByGivenVorgang(vorgangResource: VorgangResource): Observable<StateResource<WiedervorlageListResource>> { - doIfLoadingRequired(this.wiedervorlageList$.value, () => this.loadWiedervorlagenByVorgang(vorgangResource)); - return this.wiedervorlageList$.asObservable(); - } - - loadWiedervorlagenByVorgang(vorgangResource: VorgangResource): void { - if (hasLink(vorgangResource, VorgangHeaderLinkRel.WIEDERVORLAGEN)) { - const subscription: Subscription = this.repository.getWiedervorlageList(vorgangResource).subscribe(wiedervorlagenList => { - if (!isNull(wiedervorlagenList)) { - this.setWiedervorlagenList(wiedervorlagenList); - subscription.unsubscribe(); - } - }); - } else { - this.clearWiedervorlagenList(); - } - } - - public loadWiedervorlagenByVorgangStrict(vorgangResource: VorgangResource): Observable<StateResource<WiedervorlageListResource>> { - return this.repository.getWiedervorlageList(vorgangResource).pipe( - map(wiedervorlagenList => createStateResource(wiedervorlagenList)), - startWith(createEmptyStateResource<WiedervorlageListResource>(true))); - } - - setWiedervorlageListLoading(): void { - this.wiedervorlageList$.next({ ...this.wiedervorlageList$.value, loading: true }); - } - - setWiedervorlagenList(wiedervorlagenList: WiedervorlageListResource): void { - this.wiedervorlageList$.next(createStateResource(wiedervorlagenList)); - } - - public getWiedervorlage(): Observable<StateResource<WiedervorlageResource>> { - return this.wiedervorlage$.asObservable().pipe( - tap(wiedervorlage => doIfLoadingRequired(wiedervorlage, () => this.updateWiedervorlage())), - startWith(createEmptyStateResource<WiedervorlageResource>(true)) - ); - } - - private updateWiedervorlage(): void { - this.setWiedervorlageLoading(); - - this.loadAndSetWiedervorlageByUrl(this.getWiedervorlageUri()); - } - - private loadAndSetWiedervorlageByUrl(url: ResourceUri): void { - this.setWiedervorlageLoading(); - - const subscription: Subscription = this.repository.getWiedervorlage(url).subscribe(wiedervorlage => { - this.wiedervorlage$.next(createStateResource(wiedervorlage)); - subscription.unsubscribe(); - }); - } - - public isNewWiedervorlage(): boolean { - return isEqual(this.navigationService.getParam(WiedervorlageService.encodedWiedervorlageUriParam), WiedervorlageRoutes.NEW); - } - - private listenToNavigation(): void { - this.unsubscribe(); - this.subscription = this.navigationService.urlChanged().subscribe(params => this.onNavigation(params)); - } - - onNavigation(params: Params): void { - if (this.navigateToVorgangDetailPage(params)) { - this.setWiedervorlageListReload(); - this.forceWiedervorlageReload(); - this.submitInProgress$.next(createEmptyStateResource<CommandResource>()); - this.clearAttachmentList(); - } - if (NavigationService.isVorgangListPage(params)) { - this.clearWiedervorlagenList(); - this.submitInProgress$.next(createEmptyStateResource<CommandResource>()); - this.clearAttachmentList(); - } - } - - clearAttachmentList(): void { - this.attachmentListByWiedervorlage = <BinaryFileListByWiedervorlageUri>{}; - } - - clearWiedervorlagenList(): void { - this.wiedervorlageList$.next(createEmptyStateResource<WiedervorlageListResource>()); - } - - private forceWiedervorlageReload(): void { - this.wiedervorlage$.next(createEmptyStateResource()); - } - - private navigateToVorgangDetailPage(params: Params): boolean { - return isUndefined(params[WiedervorlageService.encodedWiedervorlageUriParam] && isNotUndefined(params[VorgangService.VORGANG_WITH_EINGANG_URL])); - } - - private getWiedervorlageUri(): ResourceUri { - return this.navigationService.getDecodedParam(WiedervorlageService.encodedWiedervorlageUriParam); - } - - setWiedervorlageLoading(): void { - this.wiedervorlage$.next({ ...this.wiedervorlage$.value, loading: true }); - } - - public createWiedervorlage(wiedervorlage: Wiedervorlage): Observable<StateResource<CommandResource>> { - this.setSubmitInProgressLoading(); - - return this.createCreateWiedervorlageCommand(this.wiedervorlageList$.value.resource, wiedervorlage).pipe( - filter(commandStateResource => !commandStateResource.loading), - tap(commandStateResource => this.proceedAfterReceiveCommand(commandStateResource, this.buildMessage(WiedervorlageMessages.CREATED, wiedervorlage))), - startWith(createEmptyStateResource<CommandResource>(true)) - ); - } - - createCreateWiedervorlageCommand(wiedervorlageListResource: WiedervorlageListResource, wiedervorlage: Wiedervorlage): Observable<StateResource<CommandResource>> { - return this.commandService.createCommand(wiedervorlageListResource, WiedervorlageListLinkRel.CREATE_WIEDERVORLAGE, this.buildCreateWiedervorlageCommand(wiedervorlage)); - } - - private buildCreateWiedervorlageCommand(wiedervorlage: Wiedervorlage): Command { - return <any>{ order: CommandOrder.CREATE_WIEDERVORLAGE, wiedervorlage, body: null }; - } - - public saveWiedervorlage(wiedervorlageResource: WiedervorlageResource, wiedervorlage: Wiedervorlage): Observable<StateResource<CommandResource>> { - this.setSubmitInProgressLoading(); - - return this.createSaveWiedervorlageCommand(wiedervorlageResource, wiedervorlage).pipe( - filter(commandStateResource => !commandStateResource.loading), - tap(commandStateResource => this.proceedAfterReceiveCommand(commandStateResource, this.buildMessage(WiedervorlageMessages.SAVED, wiedervorlage))), - startWith(createEmptyStateResource<CommandResource>(true)) - ); - } - - private setSubmitInProgressLoading(): void { - this.submitInProgress$.next({ ...this.submitInProgress$.value, loading: true }); - } - - createSaveWiedervorlageCommand(wiedervorlageResource: WiedervorlageResource, wiedervorlage: Wiedervorlage): Observable<StateResource<CommandResource>> { - return this.commandService.createCommand(wiedervorlageResource, WiedervorlageLinkRel.EDIT, this.buildEditWiedervorlageCommand(wiedervorlage)); - } - - - private buildEditWiedervorlageCommand(wiedervorlage: Wiedervorlage): CreateWiedervorlageCommand { - return { order: CommandOrder.EDIT_WIEDERVORLAGE, wiedervorlage, body: null }; - } - - proceedAfterReceiveCommand(commandStateResource: StateResource<CommandResource>, message: string): void { - this.submitInProgress$.next({ ...this.submitInProgress$.value, resource: commandStateResource.resource }); - if (isDone(commandStateResource.resource)) { - this.submitInProgress$.next(createStateResource(commandStateResource.resource)); - this.snackbarService.show(commandStateResource.resource, message) - this.setWiedervorlageListReload(); - } else if (hasError(commandStateResource)) { - this.submitInProgress$.next(createStateResource(commandStateResource.resource)); - } - } - - setWiedervorlageListReload(): void { - this.wiedervorlageList$.next({ ...this.wiedervorlageList$.value, reload: true }); - } - - public erledigen(): Observable<StateResource<CommandResource>> { - return this.doAction(this.erledigenCommand$, WiedervorlageLinkRel.ERLEDIGEN, createErledigenCommand, WiedervorlageMessages.ERLEDIGT); - } - - public wiedereroeffnen(): Observable<StateResource<CommandResource>> { - return this.doAction(this.wiedereroeffnenCommand$, WiedervorlageLinkRel.WIEDEREROEFFNEN, createWiedereroeffnenCommand, WiedervorlageMessages.WIEDEREROEFFNET); - } - - private doAction(commandStateSubj: BehaviorSubject<StateResource<CommandResource>>, linkRel: string, commandProvider: () => CreateCommand, snackBarMessage: string): Observable<StateResource<any>> { - commandStateSubj.next(createEmptyStateResource(true)); - - const commandSubscription: Subscription = this.commandService.createCommand(this.wiedervorlage$.value.resource, linkRel, commandProvider()) - .subscribe(commandStateResource => { - if (isDone(commandStateResource.resource)) { - this.handleSource(commandStateResource.resource); - this.showSnackBar(commandStateResource.resource, this.buildMessage(snackBarMessage, this.wiedervorlage$.value.resource)); - commandStateSubj.next(commandStateResource); - commandSubscription.unsubscribe(); - } - }) - - return commandStateSubj.asObservable(); - } - - private handleSource(commandResource: CommandResource): void { - if (isDone(commandResource)) { - this.loadAndSetWiedervorlageByUrl(this.getWiedervorlageUri()); - } - } - - private buildMessage(message: string, wiedervorlage: Wiedervorlage) { - return replacePlaceholder(message, 'betreff', wiedervorlage.betreff); - } - - showSnackBar(commandResource: CommandResource, message: string) { - if (isDone(commandResource)) { - this.snackbarService.show(commandResource, message); - } - } - - public getAttachmentList(wiedervorlage: WiedervorlageResource): Observable<StateResource<BinaryFileListResource>> { - const uri: ResourceUri = getUrl(wiedervorlage); - - if (isNil(this.attachmentListByWiedervorlage[uri])) { - this.attachmentListByWiedervorlage[uri] = new BehaviorSubject(createEmptyStateResource<any>()); - } else { - this.attachmentListByWiedervorlage[uri].next(createEmptyStateResource<any>()); - } - - doIfLoadingRequired(this.attachmentListByWiedervorlage[uri].value, () => this.loadAttachments(wiedervorlage)); - - return this.attachmentListByWiedervorlage[uri].asObservable(); - } - - loadAttachments(wiedervorlage: WiedervorlageResource): void { - this.setAttachmentLoading(wiedervorlage); - if (!isNil(this.attachmentSubscription)) this.attachmentSubscription.unsubscribe(); - this.attachmentSubscription = this.binaryFileService.getFiles(wiedervorlage, WiedervorlageLinkRel.ATTACHMENTS).subscribe(fileList => { - if (fileList.loaded) { - this.attachmentListByWiedervorlage[getUrl(wiedervorlage)].next(fileList); - } - }); - } - - setAttachmentLoading(wiedervorlage: WiedervorlageResource): void { - this.attachmentListByWiedervorlage[getUrl(wiedervorlage)].next({ ...this.attachmentListByWiedervorlage[getUrl(wiedervorlage)].value, loading: true }); - } - - public getSubmitInProgress(): Observable<StateResource<CommandResource>> { - return this.submitInProgress$.asObservable(); - } - - ngOnDestroy(): void { - this.unsubscribe(); - } - - private unsubscribe(): void { - if (!isNil(this.subscription)) this.subscription.unsubscribe(); - } - - public hasEditLink(wiedervorlageUrl: string): Observable<boolean> { - const decodedUrl: string = decodeUrlFromEmbedding(wiedervorlageUrl); - - return this.repository.getWiedervorlage(decodedUrl).pipe( - map(wiedervorlage => hasLink(wiedervorlage, WiedervorlageLinkRel.EDIT)) - ); - } -} \ No newline at end of file + static encodedWiedervorlageUriParam: string = 'wiedervorlageUrl'; + + readonly wiedervorlageList$: BehaviorSubject<StateResource<WiedervorlageListResource>> = + new BehaviorSubject<StateResource<WiedervorlageListResource>>( + createEmptyStateResource<WiedervorlageListResource>(), + ); + readonly wiedervorlage$: BehaviorSubject<StateResource<WiedervorlageResource>> = + new BehaviorSubject<StateResource<WiedervorlageResource>>( + createEmptyStateResource<WiedervorlageResource>(), + ); + + readonly submitInProgress$: BehaviorSubject<StateResource<CommandResource>> = new BehaviorSubject< + StateResource<CommandResource> + >(createEmptyStateResource<CommandResource>()); + + readonly erledigenCommand$: BehaviorSubject<StateResource<CommandResource>> = new BehaviorSubject< + StateResource<CommandResource> + >(createEmptyStateResource<CommandResource>()); + readonly wiedereroeffnenCommand$: BehaviorSubject<StateResource<CommandResource>> = + new BehaviorSubject<StateResource<CommandResource>>( + createEmptyStateResource<CommandResource>(), + ); + + attachmentListByWiedervorlage = <BinaryFileListByWiedervorlageUri>{}; + + private subscription: Subscription; + private attachmentSubscription: Subscription; + + constructor( + private repository: WiedervorlageRepository, + private navigationService: NavigationService, + private commandService: CommandService, + private snackbarService: SnackBarService, + private binaryFileService: BinaryFileService, + private vorgangService: VorgangService, + ) { + this.listenToNavigation(); + } + + public getWiedervorlageList(): Observable<StateResource<WiedervorlageListResource>> { + return combineLatest([ + this.wiedervorlageList$.asObservable(), + this.vorgangService.getVorgangWithEingang(), + ]).pipe( + tap(([wiedervorlageList, vorgangResource]) => { + if (isNotNull(vorgangResource.resource)) { + doIfLoadingRequired(wiedervorlageList, () => + this.loadWiedervorlagenByVorgang(vorgangResource.resource), + ); + } + }), + map(([wiedervorlageList]) => wiedervorlageList), + startWith(createEmptyStateResource<WiedervorlageListResource>(true)), + ); + } + + public getWiedervorlageListByGivenVorgang( + vorgangResource: VorgangResource, + ): Observable<StateResource<WiedervorlageListResource>> { + doIfLoadingRequired(this.wiedervorlageList$.value, () => + this.loadWiedervorlagenByVorgang(vorgangResource), + ); + return this.wiedervorlageList$.asObservable(); + } + + loadWiedervorlagenByVorgang(vorgangResource: VorgangResource): void { + if (hasLink(vorgangResource, VorgangHeaderLinkRel.WIEDERVORLAGEN)) { + const subscription: Subscription = this.repository + .getWiedervorlageList(vorgangResource) + .subscribe((wiedervorlagenList) => { + if (!isNull(wiedervorlagenList)) { + this.setWiedervorlagenList(wiedervorlagenList); + subscription.unsubscribe(); + } + }); + } else { + this.clearWiedervorlagenList(); + } + } + + public loadWiedervorlagenByVorgangStrict( + vorgangResource: VorgangResource, + ): Observable<StateResource<WiedervorlageListResource>> { + return this.repository.getWiedervorlageList(vorgangResource).pipe( + map((wiedervorlagenList) => createStateResource(wiedervorlagenList)), + startWith(createEmptyStateResource<WiedervorlageListResource>(true)), + ); + } + + setWiedervorlageListLoading(): void { + this.wiedervorlageList$.next({ ...this.wiedervorlageList$.value, loading: true }); + } + + setWiedervorlagenList(wiedervorlagenList: WiedervorlageListResource): void { + this.wiedervorlageList$.next(createStateResource(wiedervorlagenList)); + } + + public getWiedervorlage(): Observable<StateResource<WiedervorlageResource>> { + return this.wiedervorlage$.asObservable().pipe( + tap((wiedervorlage) => doIfLoadingRequired(wiedervorlage, () => this.updateWiedervorlage())), + startWith(createEmptyStateResource<WiedervorlageResource>(true)), + ); + } + + private updateWiedervorlage(): void { + this.setWiedervorlageLoading(); + + this.loadAndSetWiedervorlageByUrl(this.getWiedervorlageUri()); + } + + private loadAndSetWiedervorlageByUrl(url: ResourceUri): void { + this.setWiedervorlageLoading(); + + const subscription: Subscription = this.repository + .getWiedervorlage(url) + .subscribe((wiedervorlage) => { + this.wiedervorlage$.next(createStateResource(wiedervorlage)); + subscription.unsubscribe(); + }); + } + + public isNewWiedervorlage(): boolean { + return isEqual( + this.navigationService.getParam(WiedervorlageService.encodedWiedervorlageUriParam), + WiedervorlageRoutes.NEW, + ); + } + + private listenToNavigation(): void { + this.unsubscribe(); + this.subscription = this.navigationService + .urlChanged() + .subscribe((params) => this.onNavigation(params)); + } + + onNavigation(params: Params): void { + if (this.navigateToVorgangDetailPage(params)) { + this.setWiedervorlageListReload(); + this.forceWiedervorlageReload(); + this.submitInProgress$.next(createEmptyStateResource<CommandResource>()); + this.clearAttachmentList(); + } + if (NavigationService.isVorgangListPage(params)) { + this.clearWiedervorlagenList(); + this.submitInProgress$.next(createEmptyStateResource<CommandResource>()); + this.clearAttachmentList(); + } + } + + clearAttachmentList(): void { + this.attachmentListByWiedervorlage = <BinaryFileListByWiedervorlageUri>{}; + } + + clearWiedervorlagenList(): void { + this.wiedervorlageList$.next(createEmptyStateResource<WiedervorlageListResource>()); + } + + private forceWiedervorlageReload(): void { + this.wiedervorlage$.next(createEmptyStateResource()); + } + + private navigateToVorgangDetailPage(params: Params): boolean { + return isUndefined( + params[WiedervorlageService.encodedWiedervorlageUriParam] && + isNotUndefined(params[VorgangService.VORGANG_WITH_EINGANG_URL]), + ); + } + + private getWiedervorlageUri(): ResourceUri { + return this.navigationService.getDecodedParam( + WiedervorlageService.encodedWiedervorlageUriParam, + ); + } + + setWiedervorlageLoading(): void { + this.wiedervorlage$.next({ ...this.wiedervorlage$.value, loading: true }); + } + + public createWiedervorlage( + wiedervorlage: Wiedervorlage, + ): Observable<StateResource<CommandResource>> { + this.setSubmitInProgressLoading(); + + return this.createCreateWiedervorlageCommand( + this.wiedervorlageList$.value.resource, + wiedervorlage, + ).pipe( + filter((commandStateResource) => !commandStateResource.loading), + tap((commandStateResource) => + this.proceedAfterReceiveCommand( + commandStateResource, + this.buildMessage(WiedervorlageMessages.CREATED, wiedervorlage), + ), + ), + startWith(createEmptyStateResource<CommandResource>(true)), + ); + } + + createCreateWiedervorlageCommand( + wiedervorlageListResource: WiedervorlageListResource, + wiedervorlage: Wiedervorlage, + ): Observable<StateResource<CommandResource>> { + return this.commandService.createCommand( + wiedervorlageListResource, + WiedervorlageListLinkRel.CREATE_WIEDERVORLAGE, + this.buildCreateWiedervorlageCommand(wiedervorlage), + ); + } + + private buildCreateWiedervorlageCommand(wiedervorlage: Wiedervorlage): Command { + return <any>{ order: CommandOrder.CREATE_WIEDERVORLAGE, wiedervorlage, body: null }; + } + + public saveWiedervorlage( + wiedervorlageResource: WiedervorlageResource, + wiedervorlage: Wiedervorlage, + ): Observable<StateResource<CommandResource>> { + this.setSubmitInProgressLoading(); + + return this.createSaveWiedervorlageCommand(wiedervorlageResource, wiedervorlage).pipe( + filter((commandStateResource) => !commandStateResource.loading), + tap((commandStateResource) => + this.proceedAfterReceiveCommand( + commandStateResource, + this.buildMessage(WiedervorlageMessages.SAVED, wiedervorlage), + ), + ), + startWith(createEmptyStateResource<CommandResource>(true)), + ); + } + + private setSubmitInProgressLoading(): void { + this.submitInProgress$.next({ ...this.submitInProgress$.value, loading: true }); + } + + createSaveWiedervorlageCommand( + wiedervorlageResource: WiedervorlageResource, + wiedervorlage: Wiedervorlage, + ): Observable<StateResource<CommandResource>> { + return this.commandService.createCommand( + wiedervorlageResource, + WiedervorlageLinkRel.EDIT, + this.buildEditWiedervorlageCommand(wiedervorlage), + ); + } + + private buildEditWiedervorlageCommand(wiedervorlage: Wiedervorlage): CreateWiedervorlageCommand { + return { order: CommandOrder.EDIT_WIEDERVORLAGE, wiedervorlage, body: null }; + } + + proceedAfterReceiveCommand( + commandStateResource: StateResource<CommandResource>, + message: string, + ): void { + this.submitInProgress$.next({ + ...this.submitInProgress$.value, + resource: commandStateResource.resource, + }); + if (isDone(commandStateResource.resource)) { + this.submitInProgress$.next(createStateResource(commandStateResource.resource)); + this.snackbarService.show(commandStateResource.resource, message); + this.setWiedervorlageListReload(); + } else if (hasError(commandStateResource)) { + this.submitInProgress$.next(createStateResource(commandStateResource.resource)); + } + } + + setWiedervorlageListReload(): void { + this.wiedervorlageList$.next({ ...this.wiedervorlageList$.value, reload: true }); + } + + public erledigen(): Observable<StateResource<CommandResource>> { + return this.doAction( + this.erledigenCommand$, + WiedervorlageLinkRel.ERLEDIGEN, + createErledigenCommand, + WiedervorlageMessages.ERLEDIGT, + ); + } + + public wiedereroeffnen(): Observable<StateResource<CommandResource>> { + return this.doAction( + this.wiedereroeffnenCommand$, + WiedervorlageLinkRel.WIEDEREROEFFNEN, + createWiedereroeffnenCommand, + WiedervorlageMessages.WIEDEREROEFFNET, + ); + } + + private doAction( + commandStateSubj: BehaviorSubject<StateResource<CommandResource>>, + linkRel: string, + commandProvider: () => CreateCommand, + snackBarMessage: string, + ): Observable<StateResource<any>> { + commandStateSubj.next(createEmptyStateResource(true)); + + const commandSubscription: Subscription = this.commandService + .createCommand(this.wiedervorlage$.value.resource, linkRel, commandProvider()) + .subscribe((commandStateResource) => { + if (isDone(commandStateResource.resource)) { + this.handleSource(commandStateResource.resource); + this.showSnackBar( + commandStateResource.resource, + this.buildMessage(snackBarMessage, this.wiedervorlage$.value.resource), + ); + commandStateSubj.next(commandStateResource); + commandSubscription.unsubscribe(); + } + }); + + return commandStateSubj.asObservable(); + } + + private handleSource(commandResource: CommandResource): void { + if (isDone(commandResource)) { + this.loadAndSetWiedervorlageByUrl(this.getWiedervorlageUri()); + } + } + + private buildMessage(message: string, wiedervorlage: Wiedervorlage) { + return replacePlaceholder(message, 'betreff', wiedervorlage.betreff); + } + + showSnackBar(commandResource: CommandResource, message: string) { + if (isDone(commandResource)) { + this.snackbarService.show(commandResource, message); + } + } + + public getAttachmentList( + wiedervorlage: WiedervorlageResource, + ): Observable<StateResource<BinaryFileListResource>> { + const uri: ResourceUri = getUrl(wiedervorlage); + + if (isNil(this.attachmentListByWiedervorlage[uri])) { + this.attachmentListByWiedervorlage[uri] = new BehaviorSubject( + createEmptyStateResource<any>(), + ); + } else { + this.attachmentListByWiedervorlage[uri].next(createEmptyStateResource<any>()); + } + + doIfLoadingRequired(this.attachmentListByWiedervorlage[uri].value, () => + this.loadAttachments(wiedervorlage), + ); + + return this.attachmentListByWiedervorlage[uri].asObservable(); + } + + loadAttachments(wiedervorlage: WiedervorlageResource): void { + this.setAttachmentLoading(wiedervorlage); + if (!isNil(this.attachmentSubscription)) this.attachmentSubscription.unsubscribe(); + this.attachmentSubscription = this.binaryFileService + .getFiles(wiedervorlage, WiedervorlageLinkRel.ATTACHMENTS) + .subscribe((fileList) => { + if (fileList.loaded) { + this.attachmentListByWiedervorlage[getUrl(wiedervorlage)].next(fileList); + } + }); + } + + setAttachmentLoading(wiedervorlage: WiedervorlageResource): void { + this.attachmentListByWiedervorlage[getUrl(wiedervorlage)].next({ + ...this.attachmentListByWiedervorlage[getUrl(wiedervorlage)].value, + loading: true, + }); + } + + public getSubmitInProgress(): Observable<StateResource<CommandResource>> { + return this.submitInProgress$.asObservable(); + } + + ngOnDestroy(): void { + this.unsubscribe(); + } + + private unsubscribe(): void { + if (!isNil(this.subscription)) this.subscription.unsubscribe(); + } + + public hasEditLink(wiedervorlageUrl: string): Observable<boolean> { + const decodedUrl: string = decodeUrlFromEmbedding(wiedervorlageUrl); + + return this.repository + .getWiedervorlage(decodedUrl) + .pipe(map((wiedervorlage) => hasLink(wiedervorlage, WiedervorlageLinkRel.EDIT))); + } +} diff --git a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.util.ts b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.util.ts index 6854b8d1062d726ffcd36c805452e3dce3b4d89a..4496205eee11a0bf9d39a8ef6c7c9a1625b19606 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.util.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/lib/wiedervorlage.util.ts @@ -24,9 +24,9 @@ import { CommandOrder, CreateCommand } from '@alfa-client/command-shared'; export function createWiedereroeffnenCommand(): CreateCommand { - return <any>{ order: CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN, body: null }; + return <any>{ order: CommandOrder.WIEDERVORLAGE_WIEDEREROEFFNEN, body: null }; } export function createErledigenCommand(): CreateCommand { - return <any>{ order: CommandOrder.WIEDERVORLAGE_ERLEDIGEN, body: null }; + return <any>{ order: CommandOrder.WIEDERVORLAGE_ERLEDIGEN, body: null }; } diff --git a/alfa-client/libs/wiedervorlage-shared/src/test-setup.ts b/alfa-client/libs/wiedervorlage-shared/src/test-setup.ts index 3183359778d9cc6fcd762b10b7702e215d968cea..c06917eb2b797074cf773160e546b7d4d3461a42 100644 --- a/alfa-client/libs/wiedervorlage-shared/src/test-setup.ts +++ b/alfa-client/libs/wiedervorlage-shared/src/test-setup.ts @@ -25,17 +25,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/wiedervorlage-shared/test/wiedervorlage.ts b/alfa-client/libs/wiedervorlage-shared/test/wiedervorlage.ts index fcefe947966e466bb4a4697f9988005f2329882f..3a922dce162c6dbec5c02fc3567d17615b5f803d 100644 --- a/alfa-client/libs/wiedervorlage-shared/test/wiedervorlage.ts +++ b/alfa-client/libs/wiedervorlage-shared/test/wiedervorlage.ts @@ -25,7 +25,11 @@ import { faker } from '@faker-js/faker'; import { toResource } from 'libs/tech-shared/test/resource'; import { times } from 'lodash-es'; import { WiedervorlageListLinkRel } from '../src/lib/wiedervorlage.linkrel'; -import { Wiedervorlage, WiedervorlageListResource, WiedervorlageResource } from '../src/lib/wiedervorlage.model'; +import { + Wiedervorlage, + WiedervorlageListResource, + WiedervorlageResource, +} from '../src/lib/wiedervorlage.model'; const past = new Date(); const future = new Date(); @@ -34,26 +38,30 @@ past.setDate(past.getDate() - 2); future.setDate(future.getDate() + 2); export function createWiedervorlage(): Wiedervorlage { - return { - done: faker.datatype.boolean(), - betreff: faker.lorem.words(3), - beschreibung: faker.lorem.words(12), - frist: faker.date.between(past, future), - createdAt: faker.date.past(), - attachments: faker.internet.url() - } + return { + done: faker.datatype.boolean(), + betreff: faker.lorem.words(3), + beschreibung: faker.lorem.words(12), + frist: faker.date.between(past, future), + createdAt: faker.date.past(), + attachments: faker.internet.url(), + }; } export function createWiedervorlageResource(linkRelations: string[] = []): WiedervorlageResource { - return toResource(createWiedervorlage(), linkRelations); + return toResource(createWiedervorlage(), linkRelations); } -export function createWiedervorlageResources(linkRelations: string[] = []): WiedervorlageResource[] { - return times(10, () => toResource(createWiedervorlageResource(), [...linkRelations])); +export function createWiedervorlageResources( + linkRelations: string[] = [], +): WiedervorlageResource[] { + return times(10, () => toResource(createWiedervorlageResource(), [...linkRelations])); } -export function createWiedervorlageListResource(linkRelations: string[] = []): WiedervorlageListResource { - return toResource({}, [...linkRelations], { - [WiedervorlageListLinkRel.WIEDERVORLAGE_LIST]: createWiedervorlageResources() - }); +export function createWiedervorlageListResource( + linkRelations: string[] = [], +): WiedervorlageListResource { + return toResource({}, [...linkRelations], { + [WiedervorlageListLinkRel.WIEDERVORLAGE_LIST]: createWiedervorlageResources(), + }); } diff --git a/alfa-client/libs/wiedervorlage-shared/tsconfig.json b/alfa-client/libs/wiedervorlage-shared/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/wiedervorlage-shared/tsconfig.json +++ b/alfa-client/libs/wiedervorlage-shared/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/wiedervorlage-shared/tsconfig.lib.json b/alfa-client/libs/wiedervorlage-shared/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/wiedervorlage-shared/tsconfig.lib.json +++ b/alfa-client/libs/wiedervorlage-shared/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/wiedervorlage-shared/tsconfig.spec.json b/alfa-client/libs/wiedervorlage-shared/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/wiedervorlage-shared/tsconfig.spec.json +++ b/alfa-client/libs/wiedervorlage-shared/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/libs/wiedervorlage/.eslintrc.json b/alfa-client/libs/wiedervorlage/.eslintrc.json index 894a547868f991e5c774ba6c6ed5086111aaf39d..243c51741f65cc7afb3a7d85531c24afdcab5e56 100644 --- a/alfa-client/libs/wiedervorlage/.eslintrc.json +++ b/alfa-client/libs/wiedervorlage/.eslintrc.json @@ -1,36 +1,33 @@ { - "extends": ["../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], - "overrides": [ - { - "files": ["*.ts"], - "extends": [ - "plugin:@nx/angular", - "plugin:@angular-eslint/template/process-inline-templates" - ], - "rules": { - "@angular-eslint/directive-selector": [ - "error", - { - "type": "attribute", - "prefix": "alfa", - "style": "camelCase" - } - ], - "@angular-eslint/component-selector": [ - "error", - { - "type": "element", - "prefix": "alfa", - "style": "kebab-case" - } - ] - } - }, - { - "files": ["*.html"], - "extends": ["plugin:@nx/angular-template"], - "rules": {} - } - ] + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "alfa", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "alfa", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] } diff --git a/alfa-client/libs/wiedervorlage/jest.config.ts b/alfa-client/libs/wiedervorlage/jest.config.ts index 3ed1aaacfacb6141613bc99702cefd4ce5bb959a..bb33d4e5014cb1816994e749255c7a5dd79eb372 100644 --- a/alfa-client/libs/wiedervorlage/jest.config.ts +++ b/alfa-client/libs/wiedervorlage/jest.config.ts @@ -25,24 +25,24 @@ /* eslint-disable */ /* eslint-disable */ export default { - displayName: 'wiedervorlage', - preset: '../../jest.preset.js', - setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], - globals: {}, - coverageDirectory: '../../coverage/libs/wiedervorlage', - snapshotSerializers: [ - 'jest-preset-angular/build/serializers/no-ng-attributes', - 'jest-preset-angular/build/serializers/ng-snapshot', - 'jest-preset-angular/build/serializers/html-comment', - ], - transform: { - '^.+.(ts|mjs|js|html)$': [ - 'jest-preset-angular', - { - tsconfig: '<rootDir>/tsconfig.spec.json', - stringifyContentPathRegex: '\\.(html|svg)$', - }, - ], - }, - transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], + displayName: 'wiedervorlage', + preset: '../../jest.preset.js', + setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'], + globals: {}, + coverageDirectory: '../../coverage/libs/wiedervorlage', + snapshotSerializers: [ + 'jest-preset-angular/build/serializers/no-ng-attributes', + 'jest-preset-angular/build/serializers/ng-snapshot', + 'jest-preset-angular/build/serializers/html-comment', + ], + transform: { + '^.+.(ts|mjs|js|html)$': [ + 'jest-preset-angular', + { + tsconfig: '<rootDir>/tsconfig.spec.json', + stringifyContentPathRegex: '\\.(html|svg)$', + }, + ], + }, + transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'], }; diff --git a/alfa-client/libs/wiedervorlage/project.json b/alfa-client/libs/wiedervorlage/project.json index ccbbd595f4517524da0ad1f7f205d38de16a2d28..d512070f873564f0b6620e7572173623160043e6 100644 --- a/alfa-client/libs/wiedervorlage/project.json +++ b/alfa-client/libs/wiedervorlage/project.json @@ -1,29 +1,26 @@ { - "name": "wiedervorlage", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "projectType": "library", - "sourceRoot": "libs/wiedervorlage/src", - "prefix": "alfa", - "targets": { - "lint": { - "executor": "@nx/eslint:lint", - "options": { - "lintFilePatterns": [ - "libs/wiedervorlage/src/**/*.ts", - "libs/wiedervorlage/src/**/*.html" - ] - }, - "outputs": ["{options.outputFile}"] - }, - "test": { - "executor": "@nx/jest:jest", - "outputs": ["{workspaceRoot}/coverage/libs/wiedervorlage"], - "options": { - "tsConfig": "libs/wiedervorlage/tsconfig.spec.json", - "jestConfig": "libs/wiedervorlage/jest.config.ts", - "passWithNoTests": true - } - } - }, - "tags": [] + "name": "wiedervorlage", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "projectType": "library", + "sourceRoot": "libs/wiedervorlage/src", + "prefix": "alfa", + "targets": { + "lint": { + "executor": "@nx/eslint:lint", + "options": { + "lintFilePatterns": ["libs/wiedervorlage/src/**/*.ts", "libs/wiedervorlage/src/**/*.html"] + }, + "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/jest:jest", + "outputs": ["{workspaceRoot}/coverage/libs/wiedervorlage"], + "options": { + "tsConfig": "libs/wiedervorlage/tsconfig.spec.json", + "jestConfig": "libs/wiedervorlage/jest.config.ts", + "passWithNoTests": true + } + } + }, + "tags": [] } diff --git a/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.html index 057175ea30e7d1ccc27700d2428128359396eda9..6ec80b94d82442322ed1baf0490ca06cd901cbfa 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.html @@ -23,6 +23,10 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-wiedervorlage-create-button *ngIf="vorgang | hasLink: vorgangHeaderLinkRel.WIEDERVORLAGEN" data-test-id="wiedervorlage-create-button" - [wiedervorlageListStateResource]="wiedervorlageListStateResource$ | async" [showAsIconButton]="showAsIconButton"> -</alfa-wiedervorlage-create-button> \ No newline at end of file +<alfa-wiedervorlage-create-button + *ngIf="vorgang | hasLink: vorgangHeaderLinkRel.WIEDERVORLAGEN" + data-test-id="wiedervorlage-create-button" + [wiedervorlageListStateResource]="wiedervorlageListStateResource$ | async" + [showAsIconButton]="showAsIconButton" +> +</alfa-wiedervorlage-create-button> diff --git a/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.spec.ts index e88b66cd6b9a12a0af973eb62d6faa6c886ab32e..42aed9c72ef23b0dbf5965e73f9ce81f1f3345bd 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.spec.ts @@ -35,82 +35,86 @@ import { WiedervorlageCreateButtonComponent } from '../wiedervorlage-list-in-vor import { CreateWiedervorlageButtonContainerComponent } from './create-wiedervorlage-button-container.component'; describe('CreateWiedervorlageButtonContainerComponent', () => { - let component: CreateWiedervorlageButtonContainerComponent; - let fixture: ComponentFixture<CreateWiedervorlageButtonContainerComponent>; - - const wiedervorlageServie = mock(WiedervorlageService); - - const wiedervorlageCreateButton: string = getDataTestIdOf('wiedervorlage-create-button'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - HasLinkPipe, - CreateWiedervorlageButtonContainerComponent, - MockComponent(WiedervorlageCreateButtonComponent) - ], - providers: [ - { - provide: WiedervorlageService, - useValue: wiedervorlageServie - } - ] - }) - }) - - beforeEach(() => { - fixture = TestBed.createComponent(CreateWiedervorlageButtonContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('wiedervorlage create button', () => { - - it('should show if link exists', () => { - component.wiedervorlageListStateResource$ = of(createStateResource(createWiedervorlageListResource())); - component.vorgang = createVorgangWithEingangResource([VorgangHeaderLinkRel.WIEDERVORLAGEN]); - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, wiedervorlageCreateButton); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should hide if link does not exist', () => { - component.vorgang = createVorgangWithEingangResource(); - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, wiedervorlageCreateButton); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) - - describe('load wiedervorlagen', () => { - - beforeEach(() => { - wiedervorlageServie.getWiedervorlageListByGivenVorgang.mockClear(); - }) - - it('should load on existing Link', () => { - const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([VorgangHeaderLinkRel.WIEDERVORLAGEN]); - component.vorgang = vorgangWithEingang; - - component.ngOnChanges(); - - expect(wiedervorlageServie.getWiedervorlageListByGivenVorgang).toHaveBeenCalledWith(vorgangWithEingang); - }) - - it('should NOT load on missing Link', () => { - component.vorgang = createVorgangWithEingangResource(); - - component.ngOnChanges(); - - expect(wiedervorlageServie.getWiedervorlageListByGivenVorgang).not.toHaveBeenCalled(); - }) - }) + let component: CreateWiedervorlageButtonContainerComponent; + let fixture: ComponentFixture<CreateWiedervorlageButtonContainerComponent>; + + const wiedervorlageServie = mock(WiedervorlageService); + + const wiedervorlageCreateButton: string = getDataTestIdOf('wiedervorlage-create-button'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + HasLinkPipe, + CreateWiedervorlageButtonContainerComponent, + MockComponent(WiedervorlageCreateButtonComponent), + ], + providers: [ + { + provide: WiedervorlageService, + useValue: wiedervorlageServie, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CreateWiedervorlageButtonContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('wiedervorlage create button', () => { + it('should show if link exists', () => { + component.wiedervorlageListStateResource$ = of( + createStateResource(createWiedervorlageListResource()), + ); + component.vorgang = createVorgangWithEingangResource([VorgangHeaderLinkRel.WIEDERVORLAGEN]); + + fixture.detectChanges(); + const element = getElementFromFixture(fixture, wiedervorlageCreateButton); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should hide if link does not exist', () => { + component.vorgang = createVorgangWithEingangResource(); + + fixture.detectChanges(); + const element = getElementFromFixture(fixture, wiedervorlageCreateButton); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); + + describe('load wiedervorlagen', () => { + beforeEach(() => { + wiedervorlageServie.getWiedervorlageListByGivenVorgang.mockClear(); + }); + + it('should load on existing Link', () => { + const vorgangWithEingang: VorgangWithEingangResource = createVorgangWithEingangResource([ + VorgangHeaderLinkRel.WIEDERVORLAGEN, + ]); + component.vorgang = vorgangWithEingang; + + component.ngOnChanges(); + + expect(wiedervorlageServie.getWiedervorlageListByGivenVorgang).toHaveBeenCalledWith( + vorgangWithEingang, + ); + }); + + it('should NOT load on missing Link', () => { + component.vorgang = createVorgangWithEingangResource(); + + component.ngOnChanges(); + + expect(wiedervorlageServie.getWiedervorlageListByGivenVorgang).not.toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.ts index c75307f84b82bc80ba339d5ba61cd6f93926696e..3f35145d9d7fa67829f79957089dccb5643b6593 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/create-wiedervorlage-button-container/create-wiedervorlage-button-container.component.ts @@ -29,24 +29,24 @@ import { hasLink } from '@ngxp/rest'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-create-wiedervorlage-button-container', - templateUrl: './create-wiedervorlage-button-container.component.html', - styleUrls: ['./create-wiedervorlage-button-container.component.scss'] + selector: 'alfa-create-wiedervorlage-button-container', + templateUrl: './create-wiedervorlage-button-container.component.html', + styleUrls: ['./create-wiedervorlage-button-container.component.scss'], }) export class CreateWiedervorlageButtonContainerComponent implements OnChanges { + @Input() vorgang: VorgangWithEingangResource; + @Input() showAsIconButton: boolean; - @Input() vorgang: VorgangWithEingangResource; - @Input() showAsIconButton: boolean; + wiedervorlageListStateResource$: Observable<StateResource<WiedervorlageListResource>>; - wiedervorlageListStateResource$: Observable<StateResource<WiedervorlageListResource>>; + readonly vorgangHeaderLinkRel = VorgangHeaderLinkRel; - readonly vorgangHeaderLinkRel = VorgangHeaderLinkRel; + constructor(private wiedervorlageService: WiedervorlageService) {} - constructor(private wiedervorlageService: WiedervorlageService) { } - - ngOnChanges(): void { - if (hasLink(this.vorgang, VorgangHeaderLinkRel.WIEDERVORLAGEN)) { - this.wiedervorlageListStateResource$ = this.wiedervorlageService.getWiedervorlageListByGivenVorgang(this.vorgang); - } - } -} \ No newline at end of file + ngOnChanges(): void { + if (hasLink(this.vorgang, VorgangHeaderLinkRel.WIEDERVORLAGEN)) { + this.wiedervorlageListStateResource$ = + this.wiedervorlageService.getWiedervorlageListByGivenVorgang(this.vorgang); + } + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.html index 31feb82f6148e2dd3e726cdce67d424f388f085b..c6ee075019eaa863e7e29747b9aad49122ff5d24 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.html @@ -23,9 +23,12 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ozgcloud-icon-button-with-spinner *ngIf="wiedervorlage | hasLink: linkRel.ERLEDIGEN" data-test-id="erledigen-icon-button" - [stateResource]="erledigenCommand$ | async" - icon="check_circle_outline" - toolTip="Als erledigt markieren" - (clickEmitter)="erledigen()"> -</ozgcloud-icon-button-with-spinner> \ No newline at end of file +<ozgcloud-icon-button-with-spinner + *ngIf="wiedervorlage | hasLink: linkRel.ERLEDIGEN" + data-test-id="erledigen-icon-button" + [stateResource]="erledigenCommand$ | async" + icon="check_circle_outline" + toolTip="Als erledigt markieren" + (clickEmitter)="erledigen()" +> +</ozgcloud-icon-button-with-spinner> diff --git a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.spec.ts index d7d345d24775b089b74d4be4be4e919024ae8764..aec0df1fd5d60270461684a7e0ae5d3b8b221307 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.spec.ts @@ -31,63 +31,61 @@ import { MockComponent } from 'ng-mocks'; import { ErledigenButtonContainerComponent } from './erledigen-button-container.component'; describe('ErledigenButtonContainerComponent', () => { - let component: ErledigenButtonContainerComponent; - let fixture: ComponentFixture<ErledigenButtonContainerComponent>; + let component: ErledigenButtonContainerComponent; + let fixture: ComponentFixture<ErledigenButtonContainerComponent>; - const erledigenIconButton = '[data-test-id="erledigen-icon-button"]' + const erledigenIconButton = '[data-test-id="erledigen-icon-button"]'; - const wiedervorlageService = mock(WiedervorlageService); + const wiedervorlageService = mock(WiedervorlageService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - ErledigenButtonContainerComponent, - HasLinkPipe, - MockComponent(IconButtonWithSpinnerComponent) - ], - providers: [ - { - provide: WiedervorlageService, - useValue: wiedervorlageService - } - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + ErledigenButtonContainerComponent, + HasLinkPipe, + MockComponent(IconButtonWithSpinnerComponent), + ], + providers: [ + { + provide: WiedervorlageService, + useValue: wiedervorlageService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(ErledigenButtonContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(ErledigenButtonContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('Erledigen Button', () => { + describe('Erledigen Button', () => { + it('should be hidden', () => { + const button = fixture.nativeElement.querySelector(erledigenIconButton); - it('should be hidden', () => { - const button = fixture.nativeElement.querySelector(erledigenIconButton); + expect(button).not.toBeInstanceOf(HTMLElement); + }); - expect(button).not.toBeInstanceOf(HTMLElement); - }); + it('should be visible', () => { + component.wiedervorlage = createWiedervorlageResource([WiedervorlageLinkRel.ERLEDIGEN]); + fixture.detectChanges(); - it('should be visible', () => { - component.wiedervorlage = createWiedervorlageResource([WiedervorlageLinkRel.ERLEDIGEN]); - fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(erledigenIconButton); - const button = fixture.nativeElement.querySelector(erledigenIconButton); + expect(button).toBeInstanceOf(HTMLElement); + }); + }); - expect(button).toBeInstanceOf(HTMLElement); - }); - }) + describe('erledigen', () => { + it('should call service', () => { + component.erledigen(); - describe('erledigen', () => { - - it('should call service', () => { - component.erledigen(); - - expect(wiedervorlageService.erledigen).toHaveBeenCalled(); - }) - }); -}); \ No newline at end of file + expect(wiedervorlageService.erledigen).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.ts index 90902b3753b59d126893008d5c371a71da5a31ce..8e9a818d5520746c2a0070aed8c92f0bd367287c 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/erledigen-button-container/erledigen-button-container.component.ts @@ -24,25 +24,28 @@ import { Component, Input } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { StateResource } from '@alfa-client/tech-shared'; -import { WiedervorlageLinkRel, WiedervorlageResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; +import { + WiedervorlageLinkRel, + WiedervorlageResource, + WiedervorlageService, +} from '@alfa-client/wiedervorlage-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-erledigen-button-container', - templateUrl: './erledigen-button-container.component.html', - styleUrls: ['./erledigen-button-container.component.scss'] + selector: 'alfa-erledigen-button-container', + templateUrl: './erledigen-button-container.component.html', + styleUrls: ['./erledigen-button-container.component.scss'], }) export class ErledigenButtonContainerComponent { + @Input() wiedervorlage: WiedervorlageResource; - @Input() wiedervorlage: WiedervorlageResource; + erledigenCommand$: Observable<StateResource<CommandResource>>; - erledigenCommand$: Observable<StateResource<CommandResource>>; + readonly linkRel = WiedervorlageLinkRel; - readonly linkRel = WiedervorlageLinkRel; + constructor(private wiedervorlageService: WiedervorlageService) {} - constructor(private wiedervorlageService: WiedervorlageService) { } - - erledigen(): void { - this.erledigenCommand$ = this.wiedervorlageService.erledigen(); - } + erledigen(): void { + this.erledigenCommand$ = this.wiedervorlageService.erledigen(); + } } diff --git a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html index d586ce2782546305ef0ed97ed46cc68aabcf68b2..c5124c7ca27cdd2739cb6699175e75e211728711 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.html @@ -23,14 +23,21 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" text="Speichern" data-test-id="speichern-button" - icon="save_alt" - [stateResource]="submitInProgress$ | async" - (clickEmitter)="submit()"> +<ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + text="Speichern" + data-test-id="speichern-button" + icon="save_alt" + [stateResource]="submitInProgress$ | async" + (clickEmitter)="submit()" +> </ozgcloud-stroked-button-with-spinner> -<ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" - icon="save_alt" toolTip="Wiedervorlage speichern" - [stateResource]="submitInProgress$ | async" - (clickEmitter)="submit()"> +<ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + icon="save_alt" + toolTip="Wiedervorlage speichern" + [stateResource]="submitInProgress$ | async" + (clickEmitter)="submit()" +> </ozgcloud-icon-button-with-spinner> diff --git a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.spec.ts index c91d618e65f314f5c48067db85583627b39d7360..f90847210b36e25013422135c954b9085aafcae0 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.spec.ts @@ -27,7 +27,10 @@ import { CommandResource } from '@alfa-client/command-shared'; import { NavigationService } from '@alfa-client/navigation-shared'; import { StateResource, createStateResource } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; import { createCommandResource } from 'libs/command-shared/test/command'; @@ -36,66 +39,67 @@ import { WiedervorlageFormService } from '../wiedervorlage-page-container/wieder import { SubmitWiedervorlageButtonComponent } from './submit-wiedervorlage-button.component'; describe('SubmitWiedervorlageButtonComponent', () => { - let component: SubmitWiedervorlageButtonComponent; - let fixture: ComponentFixture<SubmitWiedervorlageButtonComponent>; + let component: SubmitWiedervorlageButtonComponent; + let fixture: ComponentFixture<SubmitWiedervorlageButtonComponent>; - const wiedervorlageService = mock(WiedervorlageService); - const navigationService = mock(NavigationService); - const wiedervorlageFormService = mock(WiedervorlageFormService); - const activatedRoute = mock(ActivatedRoute); + const wiedervorlageService = mock(WiedervorlageService); + const navigationService = mock(NavigationService); + const wiedervorlageFormService = mock(WiedervorlageFormService); + const activatedRoute = mock(ActivatedRoute); - const commandWithError: StateResource<CommandResource> = createStateResource(createCommandResource([CommandLinkRel.EFFECTED_RESOURCE])); + const commandWithError: StateResource<CommandResource> = createStateResource( + createCommandResource([CommandLinkRel.EFFECTED_RESOURCE]), + ); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - SubmitWiedervorlageButtonComponent, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent) - ], - providers: [ - { - provide: WiedervorlageService, - useValue: wiedervorlageService - }, - { - provide: WiedervorlageFormService, - useValue: wiedervorlageFormService - }, - { - provide: NavigationService, - useValue: navigationService - }, - { - provide: ActivatedRoute, - useValue: activatedRoute - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + SubmitWiedervorlageButtonComponent, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + providers: [ + { + provide: WiedervorlageService, + useValue: wiedervorlageService, + }, + { + provide: WiedervorlageFormService, + useValue: wiedervorlageFormService, + }, + { + provide: NavigationService, + useValue: navigationService, + }, + { + provide: ActivatedRoute, + useValue: activatedRoute, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(SubmitWiedervorlageButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(SubmitWiedervorlageButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('navigateIfCommandIsDone', () => { + describe('navigateIfCommandIsDone', () => { + it('should navigate on success', () => { + component.navigateIfCommandIsDone(commandWithError); - it('should navigate on success', () => { - component.navigateIfCommandIsDone(commandWithError); + expect(navigationService.navigateRelativeTo).toHaveBeenCalled(); + }); - expect(navigationService.navigateRelativeTo).toHaveBeenCalled(); - }) + it('should NOT navigate on loading', () => { + component.navigateIfCommandIsDone({ ...commandWithError, loading: true }); - it('should NOT navigate on loading', () => { - component.navigateIfCommandIsDone({ ...commandWithError, loading: true }); - - expect(navigationService.navigateRelativeTo).toHaveBeenCalledWith('../../', activatedRoute); - }) - }) + expect(navigationService.navigateRelativeTo).toHaveBeenCalledWith('../../', activatedRoute); + }); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.ts b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.ts index 2a8bf6ce5cf973fa80490c7c5a1128ffa4f0e811..a05b7c38f9a5330639a4debd6ca90a1979065a60 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/submit-wiedervorlage-button/submit-wiedervorlage-button.component.ts @@ -32,39 +32,38 @@ import { filter, tap } from 'rxjs/operators'; import { WiedervorlageFormService } from '../wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice'; @Component({ - selector: 'alfa-submit-wiedervorlage-button', - templateUrl: './submit-wiedervorlage-button.component.html', - styleUrls: ['./submit-wiedervorlage-button.component.scss'] + selector: 'alfa-submit-wiedervorlage-button', + templateUrl: './submit-wiedervorlage-button.component.html', + styleUrls: ['./submit-wiedervorlage-button.component.scss'], }) export class SubmitWiedervorlageButtonComponent { + @Input() showAsIconButton: boolean = false; - @Input() showAsIconButton: boolean = false; + submitInProgress$: Observable<StateResource<any>>; - submitInProgress$: Observable<StateResource<any>>; + constructor( + private wiedervorlageService: WiedervorlageService, + private formService: WiedervorlageFormService, + private navigationService: NavigationService, + private route: ActivatedRoute, + ) { + this.submitInProgress$ = this.wiedervorlageService.getSubmitInProgress(); + } - constructor( - private wiedervorlageService: WiedervorlageService, - private formService: WiedervorlageFormService, - private navigationService: NavigationService, - private route: ActivatedRoute - ) { - this.submitInProgress$ = this.wiedervorlageService.getSubmitInProgress(); - } + submit(): void { + this.submitInProgress$ = this.formService.submit().pipe( + filter((command) => !command.loading), + tap((commandWithError) => this.navigateIfCommandIsDone(commandWithError)), + ); + } - submit(): void { - this.submitInProgress$ = this.formService.submit().pipe( - filter(command => !command.loading), - tap(commandWithError => this.navigateIfCommandIsDone(commandWithError)), - ); - } + navigateIfCommandIsDone(command: StateResource<CommandResource>): void { + if (!command.loading && isDone(command.resource)) { + this.navigateToVorgangDetailPage(); + } + } - navigateIfCommandIsDone(command: StateResource<CommandResource>): void { - if (!command.loading && isDone(command.resource)) { - this.navigateToVorgangDetailPage(); - } - } - - private navigateToVorgangDetailPage(): void { - this.navigationService.navigateRelativeTo('../../', this.route); - } -} \ No newline at end of file + private navigateToVorgangDetailPage(): void { + this.navigationService.navigateRelativeTo('../../', this.route); + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.html index 09aa60017e8cc4c805800ea5f947542095ecc7b9..17b9a2405cd87e942873b1c43ead27507aace64a 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.html @@ -23,9 +23,12 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<ozgcloud-icon-button-with-spinner *ngIf="wiedervorlage | hasLink: linkRel.WIEDEREROEFFNEN" data-test-id="wiedereroeffnen-icon-button" - [stateResource]="wiedereroeffnenCommand$ | async" - icon="check_circle_outline" - toolTip="Als offen markieren" - (clickEmitter)="wiedereroeffnen()"> -</ozgcloud-icon-button-with-spinner> \ No newline at end of file +<ozgcloud-icon-button-with-spinner + *ngIf="wiedervorlage | hasLink: linkRel.WIEDEREROEFFNEN" + data-test-id="wiedereroeffnen-icon-button" + [stateResource]="wiedereroeffnenCommand$ | async" + icon="check_circle_outline" + toolTip="Als offen markieren" + (clickEmitter)="wiedereroeffnen()" +> +</ozgcloud-icon-button-with-spinner> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.spec.ts index 0ec5060cfdc0cdd6714edc2d770b4eea362e0cae..07328c7bdf130b159628f65a61d32cbe179d5c32 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.spec.ts @@ -31,63 +31,61 @@ import { MockComponent } from 'ng-mocks'; import { WiedereroeffnenButtonContainerComponent } from './wiedereroeffnen-button-container.component'; describe('WiedereroeffnenButtonContainerComponent', () => { - let component: WiedereroeffnenButtonContainerComponent; - let fixture: ComponentFixture<WiedereroeffnenButtonContainerComponent>; + let component: WiedereroeffnenButtonContainerComponent; + let fixture: ComponentFixture<WiedereroeffnenButtonContainerComponent>; - const wiedereroeffnenIconButton = '[data-test-id="wiedereroeffnen-icon-button"]' + const wiedereroeffnenIconButton = '[data-test-id="wiedereroeffnen-icon-button"]'; - const wiedervorlageService = mock(WiedervorlageService); + const wiedervorlageService = mock(WiedervorlageService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedereroeffnenButtonContainerComponent, - HasLinkPipe, - MockComponent(IconButtonWithSpinnerComponent) - ], - providers: [ - { - provide: WiedervorlageService, - useValue: wiedervorlageService - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedereroeffnenButtonContainerComponent, + HasLinkPipe, + MockComponent(IconButtonWithSpinnerComponent), + ], + providers: [ + { + provide: WiedervorlageService, + useValue: wiedervorlageService, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(WiedereroeffnenButtonContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(WiedereroeffnenButtonContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('Wiedereroeffnen Button', () => { + describe('Wiedereroeffnen Button', () => { + it('should be hidden', () => { + const button = fixture.nativeElement.querySelector(wiedereroeffnenIconButton); - it('should be hidden', () => { - const button = fixture.nativeElement.querySelector(wiedereroeffnenIconButton); + expect(button).not.toBeInstanceOf(HTMLElement); + }); - expect(button).not.toBeInstanceOf(HTMLElement); - }); + it('should be visible', () => { + component.wiedervorlage = createWiedervorlageResource([WiedervorlageLinkRel.WIEDEREROEFFNEN]); + fixture.detectChanges(); - it('should be visible', () => { - component.wiedervorlage = createWiedervorlageResource([WiedervorlageLinkRel.WIEDEREROEFFNEN]); - fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(wiedereroeffnenIconButton); - const button = fixture.nativeElement.querySelector(wiedereroeffnenIconButton); + expect(button).toBeInstanceOf(HTMLElement); + }); + }); - expect(button).toBeInstanceOf(HTMLElement); - }); - }) + describe('wiedereroeffnen', () => { + it('should call service', () => { + component.wiedereroeffnen(); - describe('wiedereroeffnen', () => { - - it('should call service', () => { - component.wiedereroeffnen(); - - expect(wiedervorlageService.wiedereroeffnen).toHaveBeenCalled(); - }) - }); + expect(wiedervorlageService.wiedereroeffnen).toHaveBeenCalled(); + }); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.ts index d6cba7c12f3b830c06db38522fb228a0946c0a0f..0f662e0a8c8f5631852affe98f6f8fce4d5b15e7 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedereroeffnen-button-container/wiedereroeffnen-button-container.component.ts @@ -24,25 +24,28 @@ import { Component, Input } from '@angular/core'; import { CommandResource } from '@alfa-client/command-shared'; import { StateResource } from '@alfa-client/tech-shared'; -import { WiedervorlageLinkRel, WiedervorlageResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; +import { + WiedervorlageLinkRel, + WiedervorlageResource, + WiedervorlageService, +} from '@alfa-client/wiedervorlage-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-wiedereroeffnen-button-container', - templateUrl: './wiedereroeffnen-button-container.component.html', - styleUrls: ['./wiedereroeffnen-button-container.component.scss'] + selector: 'alfa-wiedereroeffnen-button-container', + templateUrl: './wiedereroeffnen-button-container.component.html', + styleUrls: ['./wiedereroeffnen-button-container.component.scss'], }) export class WiedereroeffnenButtonContainerComponent { + @Input() wiedervorlage: WiedervorlageResource; - @Input() wiedervorlage: WiedervorlageResource; + wiedereroeffnenCommand$: Observable<StateResource<CommandResource>>; - wiedereroeffnenCommand$: Observable<StateResource<CommandResource>>; + readonly linkRel = WiedervorlageLinkRel; - readonly linkRel = WiedervorlageLinkRel; + constructor(private wiedervorlageService: WiedervorlageService) {} - constructor(private wiedervorlageService: WiedervorlageService) { } - - wiedereroeffnen(): void { - this.wiedereroeffnenCommand$ = this.wiedervorlageService.wiedereroeffnen(); - } -} \ No newline at end of file + wiedereroeffnen(): void { + this.wiedereroeffnenCommand$ = this.wiedervorlageService.wiedereroeffnen(); + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.html index 08c3f24402592b93307c2920fa8abebe27a93626..318dc392f33c5b6ceea0d7711b3a0b9fd1ff89a3 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.html @@ -23,6 +23,8 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<alfa-wiedervorlage-list-in-vorgang data-test-id="wiedervorlagen-in-vorgang" - [wiedervorlageListStateResource]="wiedervorlagenStateResource$ | async"> +<alfa-wiedervorlage-list-in-vorgang + data-test-id="wiedervorlagen-in-vorgang" + [wiedervorlageListStateResource]="wiedervorlagenStateResource$ | async" +> </alfa-wiedervorlage-list-in-vorgang> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts index adeb5ea27b2d2a816bfe80e809d7f7ac988a9213..3a9e772adb3b0d99face77c6ebf5baabbf28d22f 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.spec.ts @@ -26,85 +26,96 @@ import { createStateResource, HasLinkPipe, StateResource } from '@alfa-client/te import { mock } from '@alfa-client/test-utils'; import { VorgangResource } from '@alfa-client/vorgang-shared'; import { WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; -import { createVorgangResource, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; +import { + createVorgangResource, + createVorgangWithEingangResource, +} from 'libs/vorgang-shared/test/vorgang'; import { MockComponent } from 'ng-mocks'; import { WiedervorlageListInVorgangContainerComponent } from './wiedervorlage-list-in-vorgang-container.component'; import { WiedervorlageListInVorgangComponent } from './wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component'; import { KommentarListInVorgangContainerComponent } from '@alfa-client/kommentar'; describe('WiedervorlageListInVorgangContainerComponent', () => { - let component: WiedervorlageListInVorgangContainerComponent; - let fixture: ComponentFixture<WiedervorlageListInVorgangContainerComponent>; - - const wiedervorlageService = mock(WiedervorlageService); - - const vorgangStateResource: StateResource<VorgangResource> = createStateResource(createVorgangResource()); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageListInVorgangContainerComponent, - HasLinkPipe, - MockComponent(WiedervorlageListInVorgangComponent) - ], - providers: [ - { - provide: WiedervorlageService, - useValue: wiedervorlageService - } - ] - }).compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlageListInVorgangContainerComponent); - component = fixture.componentInstance; - component.vorgangStateResource = vorgangStateResource; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnChanges', () => { - - it('should call wiedervorlageService to get wiedervorlageList', () => { - component.ngOnChanges(); - - expect(wiedervorlageService.getWiedervorlageListByGivenVorgang).toHaveBeenCalledWith(vorgangStateResource.resource); - }) - - it('should call reloadWiedervorlageListOnVorgangReload', () => { - const reloadWiedervorlageListOnVorgangReload = jest.spyOn(component, 'reloadWiedervorlageListOnVorgangReload').mockReturnThis(); - - component.ngOnChanges(); - - expect(reloadWiedervorlageListOnVorgangReload).toHaveBeenCalled(); - }); - }) - - describe('reloadWiedervorlageListOnVorgangReload', () => { - - beforeEach(() => { - wiedervorlageService.setWiedervorlageListReload.mockClear(); - }); - - it('should call wiedervorlageService', () => { - component.vorgangStateResource = { ...createStateResource(createVorgangResource()), reload: true }; - - component.reloadWiedervorlageListOnVorgangReload(); - - expect(wiedervorlageService.setWiedervorlageListReload).toBeCalled(); - }); - - it('should not call wiedervorlageService', () => { - component.vorgangStateResource = { ...createStateResource(createVorgangResource()), reload: false }; - - component.reloadWiedervorlageListOnVorgangReload(); - - expect(wiedervorlageService.setWiedervorlageListReload).not.toBeCalled(); - }); - - }) -}); \ No newline at end of file + let component: WiedervorlageListInVorgangContainerComponent; + let fixture: ComponentFixture<WiedervorlageListInVorgangContainerComponent>; + + const wiedervorlageService = mock(WiedervorlageService); + + const vorgangStateResource: StateResource<VorgangResource> = + createStateResource(createVorgangResource()); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageListInVorgangContainerComponent, + HasLinkPipe, + MockComponent(WiedervorlageListInVorgangComponent), + ], + providers: [ + { + provide: WiedervorlageService, + useValue: wiedervorlageService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageListInVorgangContainerComponent); + component = fixture.componentInstance; + component.vorgangStateResource = vorgangStateResource; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnChanges', () => { + it('should call wiedervorlageService to get wiedervorlageList', () => { + component.ngOnChanges(); + + expect(wiedervorlageService.getWiedervorlageListByGivenVorgang).toHaveBeenCalledWith( + vorgangStateResource.resource, + ); + }); + + it('should call reloadWiedervorlageListOnVorgangReload', () => { + const reloadWiedervorlageListOnVorgangReload = jest + .spyOn(component, 'reloadWiedervorlageListOnVorgangReload') + .mockReturnThis(); + + component.ngOnChanges(); + + expect(reloadWiedervorlageListOnVorgangReload).toHaveBeenCalled(); + }); + }); + + describe('reloadWiedervorlageListOnVorgangReload', () => { + beforeEach(() => { + wiedervorlageService.setWiedervorlageListReload.mockClear(); + }); + + it('should call wiedervorlageService', () => { + component.vorgangStateResource = { + ...createStateResource(createVorgangResource()), + reload: true, + }; + + component.reloadWiedervorlageListOnVorgangReload(); + + expect(wiedervorlageService.setWiedervorlageListReload).toBeCalled(); + }); + + it('should not call wiedervorlageService', () => { + component.vorgangStateResource = { + ...createStateResource(createVorgangResource()), + reload: false, + }; + + component.reloadWiedervorlageListOnVorgangReload(); + + expect(wiedervorlageService.setWiedervorlageListReload).not.toBeCalled(); + }); + }); +}); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.ts index 49fe6965add3012ce162c82fc2cff7ce44d49501..489d0fabcfe9258b70da7c82eb70691ccf74a11e 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang-container.component.ts @@ -28,28 +28,30 @@ import { WiedervorlageListResource, WiedervorlageService } from '@alfa-client/wi import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-wiedervorlage-list-in-vorgang-container', - templateUrl: './wiedervorlage-list-in-vorgang-container.component.html', - styleUrls: ['./wiedervorlage-list-in-vorgang-container.component.scss'] + selector: 'alfa-wiedervorlage-list-in-vorgang-container', + templateUrl: './wiedervorlage-list-in-vorgang-container.component.html', + styleUrls: ['./wiedervorlage-list-in-vorgang-container.component.scss'], }) export class WiedervorlageListInVorgangContainerComponent implements OnChanges { + @Input() vorgangStateResource: StateResource<VorgangResource>; - @Input() vorgangStateResource: StateResource<VorgangResource>; + wiedervorlagenStateResource$: Observable<StateResource<WiedervorlageListResource>>; - wiedervorlagenStateResource$: Observable<StateResource<WiedervorlageListResource>>; + readonly vorgangLinkRel = VorgangHeaderLinkRel; - readonly vorgangLinkRel = VorgangHeaderLinkRel; + constructor(private wiedervorlageService: WiedervorlageService) {} - constructor(private wiedervorlageService: WiedervorlageService) { } + ngOnChanges(): void { + this.reloadWiedervorlageListOnVorgangReload(); + this.wiedervorlagenStateResource$ = + this.wiedervorlageService.getWiedervorlageListByGivenVorgang( + this.vorgangStateResource.resource, + ); + } - ngOnChanges(): void { - this.reloadWiedervorlageListOnVorgangReload(); - this.wiedervorlagenStateResource$ = this.wiedervorlageService.getWiedervorlageListByGivenVorgang(this.vorgangStateResource.resource); - } - - reloadWiedervorlageListOnVorgangReload(): void { - if (this.vorgangStateResource.reload) { - this.wiedervorlageService.setWiedervorlageListReload(); - } - } -} \ No newline at end of file + reloadWiedervorlageListOnVorgangReload(): void { + if (this.vorgangStateResource.reload) { + this.wiedervorlageService.setWiedervorlageListReload(); + } + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.html index a3e8a2574504fc7699ce9fb06490ff00571fd754..906e12c1879146fa8a4b525fba14c771bee8c1be 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.html @@ -24,19 +24,27 @@ --> <ng-container *ngIf="wiedervorlageListStateResource?.resource as wiedervorlageListResource"> - - <div class="create-button" *ngIf="wiedervorlageListResource | hasLink: wiedervorlageListLinkRel.CREATE_WIEDERVORLAGE"> - <a [routerLink]="'wiedervorlage/' + wiedervorlageRoute.NEW" tabindex="-1"> - - <ozgcloud-stroked-button-with-spinner *ngIf="!showAsIconButton" data-test-id="create-wiedervorlage" - class="create-button" text="Wiedervorlage" icon="add"> - </ozgcloud-stroked-button-with-spinner> - - <ozgcloud-icon-button-with-spinner *ngIf="showAsIconButton" data-test-id="create-wiedervorlage-icon-button" - icon="update" toolTip="Wiedervorlage erstellen"> - </ozgcloud-icon-button-with-spinner> - - </a> - </div> - -</ng-container> \ No newline at end of file + <div + class="create-button" + *ngIf="wiedervorlageListResource | hasLink: wiedervorlageListLinkRel.CREATE_WIEDERVORLAGE" + > + <a [routerLink]="'wiedervorlage/' + wiedervorlageRoute.NEW" tabindex="-1"> + <ozgcloud-stroked-button-with-spinner + *ngIf="!showAsIconButton" + data-test-id="create-wiedervorlage" + class="create-button" + text="Wiedervorlage" + icon="add" + > + </ozgcloud-stroked-button-with-spinner> + + <ozgcloud-icon-button-with-spinner + *ngIf="showAsIconButton" + data-test-id="create-wiedervorlage-icon-button" + icon="update" + toolTip="Wiedervorlage erstellen" + > + </ozgcloud-icon-button-with-spinner> + </a> + </div> +</ng-container> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.spec.ts index 80c70e1eb681b225f5e424897dc4cceed1e5cad6..d8746410c929aa0d4c228dd22a6884a3cf1c2bf9 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.spec.ts @@ -24,7 +24,10 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { HasLinkPipe, createStateResource } from '@alfa-client/tech-shared'; -import { IconButtonWithSpinnerComponent, OzgcloudStrokedButtonWithSpinnerComponent } from '@alfa-client/ui'; +import { + IconButtonWithSpinnerComponent, + OzgcloudStrokedButtonWithSpinnerComponent, +} from '@alfa-client/ui'; import { WiedervorlageListLinkRel } from '@alfa-client/wiedervorlage-shared'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { createWiedervorlageListResource } from 'libs/wiedervorlage-shared/test/wiedervorlage'; @@ -32,54 +35,57 @@ import { MockComponent } from 'ng-mocks'; import { WiedervorlageCreateButtonComponent } from './wiedervorlage-create-button.component'; describe('WiedervorlageCreateButtonComponent', () => { - let component: WiedervorlageCreateButtonComponent; - let fixture: ComponentFixture<WiedervorlageCreateButtonComponent>; + let component: WiedervorlageCreateButtonComponent; + let fixture: ComponentFixture<WiedervorlageCreateButtonComponent>; - const wiedervorlageButton: string = getDataTestIdOf('create-wiedervorlage'); + const wiedervorlageButton: string = getDataTestIdOf('create-wiedervorlage'); - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageCreateButtonComponent, - HasLinkPipe, - MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), - MockComponent(IconButtonWithSpinnerComponent) - ], - imports: [ - RouterTestingModule - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageCreateButtonComponent, + HasLinkPipe, + MockComponent(OzgcloudStrokedButtonWithSpinnerComponent), + MockComponent(IconButtonWithSpinnerComponent), + ], + imports: [RouterTestingModule], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlageCreateButtonComponent); - component = fixture.componentInstance; - component.wiedervorlageListStateResource = createStateResource(createWiedervorlageListResource()); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageCreateButtonComponent); + component = fixture.componentInstance; + component.wiedervorlageListStateResource = createStateResource( + createWiedervorlageListResource(), + ); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('create Wiedervorlage button', () => { + describe('create Wiedervorlage button', () => { + it('should be visible', () => { + component.wiedervorlageListStateResource = createStateResource( + createWiedervorlageListResource([WiedervorlageListLinkRel.CREATE_WIEDERVORLAGE]), + ); - it('should be visible', () => { - component.wiedervorlageListStateResource = createStateResource(createWiedervorlageListResource([WiedervorlageListLinkRel.CREATE_WIEDERVORLAGE])); + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(wiedervorlageButton); - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(wiedervorlageButton); + expect(button).toBeInstanceOf(HTMLElement); + }); - expect(button).toBeInstanceOf(HTMLElement); - }) + it('should be hidden', () => { + component.wiedervorlageListStateResource = createStateResource( + createWiedervorlageListResource(), + ); - it('should be hidden', () => { - component.wiedervorlageListStateResource = createStateResource(createWiedervorlageListResource()); + fixture.detectChanges(); + const button = fixture.nativeElement.querySelector(wiedervorlageButton); - fixture.detectChanges(); - const button = fixture.nativeElement.querySelector(wiedervorlageButton); - - expect(button).not.toBeInstanceOf(HTMLElement); - }) - }) -}) \ No newline at end of file + expect(button).not.toBeInstanceOf(HTMLElement); + }); + }); +}); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.ts index e89a1d5786a47f303e7b9afb87c2fd0eca77238a..6ebd62777a1ca0caca471bc687bd61bdf0ceae0b 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-create-button/wiedervorlage-create-button.component.ts @@ -23,18 +23,21 @@ */ import { Component, Input } from '@angular/core'; import { StateResource } from '@alfa-client/tech-shared'; -import { WiedervorlageListLinkRel, WiedervorlageListResource, WiedervorlageRoutes } from '@alfa-client/wiedervorlage-shared'; +import { + WiedervorlageListLinkRel, + WiedervorlageListResource, + WiedervorlageRoutes, +} from '@alfa-client/wiedervorlage-shared'; @Component({ - selector: 'alfa-wiedervorlage-create-button', - templateUrl: './wiedervorlage-create-button.component.html', - styleUrls: ['./wiedervorlage-create-button.component.scss'] + selector: 'alfa-wiedervorlage-create-button', + templateUrl: './wiedervorlage-create-button.component.html', + styleUrls: ['./wiedervorlage-create-button.component.scss'], }) export class WiedervorlageCreateButtonComponent { + @Input() wiedervorlageListStateResource: StateResource<WiedervorlageListResource>; + @Input() showAsIconButton: boolean = false; - @Input() wiedervorlageListStateResource: StateResource<WiedervorlageListResource>; - @Input() showAsIconButton: boolean = false; - - readonly wiedervorlageListLinkRel = WiedervorlageListLinkRel; - readonly wiedervorlageRoute = WiedervorlageRoutes; -} \ No newline at end of file + readonly wiedervorlageListLinkRel = WiedervorlageListLinkRel; + readonly wiedervorlageRoute = WiedervorlageRoutes; +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.html index 9cb348697924df594af76b1cbc1f1723d869b983..62717bd101780a3e2c58031f1a1404640613ffcb 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.html @@ -24,7 +24,8 @@ --> <alfa-vertical-binary-file-list - [fileListResource]="attachments$ | async" - [deletable]="false" - data-test-id="wiedervorlage-attachment-list"> -</alfa-vertical-binary-file-list> \ No newline at end of file + [fileListResource]="attachments$ | async" + [deletable]="false" + data-test-id="wiedervorlage-attachment-list" +> +</alfa-vertical-binary-file-list> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.scss index 9429d42de678880757027a7955b57d8e6b6c5061..48745d54f42f7e77c1f4fc36e449539f68db266a 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.scss @@ -22,11 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: flex; - margin: 0 -4px; + display: flex; + margin: 0 -4px; } .attachments { - display: flex; - flex-wrap: wrap; + display: flex; + flex-wrap: wrap; } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.spec.ts index 64148807582090ec91f72c8e682182ceb7b3b654..1b9bb621d1659d3b002a52a1ecae5ebde0d47085 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.spec.ts @@ -31,34 +31,34 @@ import { WiedervorlageAttachmentListContainerComponent } from './wiedervorlage-a import { VerticalBinaryFileListComponent } from '@alfa-client/binary-file'; describe('WiedervorlageAttachmentListContainerComponent', () => { - let component: WiedervorlageAttachmentListContainerComponent; - let fixture: ComponentFixture<WiedervorlageAttachmentListContainerComponent>; + let component: WiedervorlageAttachmentListContainerComponent; + let fixture: ComponentFixture<WiedervorlageAttachmentListContainerComponent>; - const wiedervorlageService = { ...mock(WiedervorlageService), getAttachmentList: () => of(null) }; + const wiedervorlageService = { ...mock(WiedervorlageService), getAttachmentList: () => of(null) }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageAttachmentListContainerComponent, - ToEmbeddedResourcesPipe, - MockComponent(VerticalBinaryFileListComponent) - ], - providers: [ - { - provide: WiedervorlageService, - useValue: wiedervorlageService - } - ] - }) - }) + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageAttachmentListContainerComponent, + ToEmbeddedResourcesPipe, + MockComponent(VerticalBinaryFileListComponent), + ], + providers: [ + { + provide: WiedervorlageService, + useValue: wiedervorlageService, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlageAttachmentListContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageAttachmentListContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.ts index 6d1f45878bb71497591248170103d0d977039b43..c26b9f8f8443764c8ae34038ca49306db8c4b317 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-attachment-list-container/wiedervorlage-attachment-list-container.component.ts @@ -28,25 +28,24 @@ import { WiedervorlageResource, WiedervorlageService } from '@alfa-client/wieder import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-wiedervorlage-attachment-list-container', - templateUrl: './wiedervorlage-attachment-list-container.component.html', - styleUrls: ['./wiedervorlage-attachment-list-container.component.scss'] + selector: 'alfa-wiedervorlage-attachment-list-container', + templateUrl: './wiedervorlage-attachment-list-container.component.html', + styleUrls: ['./wiedervorlage-attachment-list-container.component.scss'], }) export class WiedervorlageAttachmentListContainerComponent implements OnChanges { + @Input() wiedervorlage: WiedervorlageResource; - @Input() wiedervorlage: WiedervorlageResource; + attachments$: Observable<StateResource<BinaryFileListResource>>; - attachments$: Observable<StateResource<BinaryFileListResource>>; + constructor(public service: WiedervorlageService) {} - constructor(public service: WiedervorlageService) { } + ngOnChanges(changes: SimpleChanges): void { + if (changes.wiedervorlage) { + this.loadAttachments(); + } + } - ngOnChanges(changes: SimpleChanges): void { - if (changes.wiedervorlage) { - this.loadAttachments(); - } - } - - loadAttachments(): void { - this.attachments$ = this.service.getAttachmentList(this.wiedervorlage); - } -} \ No newline at end of file + loadAttachments(): void { + this.attachments$ = this.service.getAttachmentList(this.wiedervorlage); + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.html index 06bfd73dda15844989289fcb471d877eb207a285..4689f52a493cd656849645151b4f1b19281f9d99 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.html @@ -23,8 +23,11 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<button mat-icon-button [ngClass]="{ 'is-open': expanded }" - [attr.aria-label]="'Bereich ' + (expanded? 'reduzieren': 'erweitern')" - (click)="toggle.emit()"> - <mat-icon>chevron_right</mat-icon> -</button> \ No newline at end of file +<button + mat-icon-button + [ngClass]="{ 'is-open': expanded }" + [attr.aria-label]="'Bereich ' + (expanded ? 'reduzieren' : 'erweitern')" + (click)="toggle.emit()" +> + <mat-icon>chevron_right</mat-icon> +</button> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.scss index 9a989711a505ab878abb9d3d57d91156aca589eb..7f16613b56869ba02edd69913b0937a018874046 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.scss @@ -22,18 +22,18 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ button { - width: 32px; - height: 32px; - line-height: 32px; + width: 32px; + height: 32px; + line-height: 32px; - mat-icon { - transition: transform 0.1s ease-in-out; - padding-right: 4px; - } + mat-icon { + transition: transform 0.1s ease-in-out; + padding-right: 4px; + } - &.is-open { - mat-icon { - transform: rotate(90deg); - } - } -} \ No newline at end of file + &.is-open { + mat-icon { + transform: rotate(90deg); + } + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.spec.ts index ca9ac675390005b3a651de519c4b713d01c3b7fc..1f6064162e05df12a11dbc7e48bab5f09c55cac8 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.spec.ts @@ -26,27 +26,22 @@ import { MatIcon } from '@angular/material/icon'; import { WiedervorlageInVorgangExpandButtonComponent } from './wiedervorlage-in-vorgang-expand-button.component'; describe('WiedervorlageInVorgangExpandButtonComponent', () => { - let component: WiedervorlageInVorgangExpandButtonComponent; - let fixture: ComponentFixture<WiedervorlageInVorgangExpandButtonComponent>; + let component: WiedervorlageInVorgangExpandButtonComponent; + let fixture: ComponentFixture<WiedervorlageInVorgangExpandButtonComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - MatIcon, - WiedervorlageInVorgangExpandButtonComponent - ], - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [MatIcon, WiedervorlageInVorgangExpandButtonComponent], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent( - WiedervorlageInVorgangExpandButtonComponent - ); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageInVorgangExpandButtonComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.ts index de141c7d424f654f0789d4ca3f71b9a2124f735f..dc50b8da667b4b45f662faed123f418b4c48eca4 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang-expand-button/wiedervorlage-in-vorgang-expand-button.component.ts @@ -24,13 +24,12 @@ import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ - selector: 'alfa-wiedervorlage-in-vorgang-expand-button', - templateUrl: './wiedervorlage-in-vorgang-expand-button.component.html', - styleUrls: ['./wiedervorlage-in-vorgang-expand-button.component.scss'], + selector: 'alfa-wiedervorlage-in-vorgang-expand-button', + templateUrl: './wiedervorlage-in-vorgang-expand-button.component.html', + styleUrls: ['./wiedervorlage-in-vorgang-expand-button.component.scss'], }) export class WiedervorlageInVorgangExpandButtonComponent { + @Input() expanded: boolean; - @Input() expanded: boolean; - - @Output() toggle: EventEmitter<void> = new EventEmitter(); + @Output() toggle: EventEmitter<void> = new EventEmitter(); } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.html index b2f395e9040db6fa7dac5151310b25b3037f4ebe..8f22382ce7fa032dcc18833d833fbac8d705de24 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.html @@ -23,41 +23,57 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<div [attr.data-test-id]="(wiedervorlageResource.betreff | convertForDataTest)" class="container"> - - <div class="row"> - <alfa-wiedervorlage-status data-test-class="status" - [matTooltip]="wiedervorlageResource.frist | toTrafficLightTooltip" [wiedervorlageResource]="wiedervorlageResource"> - </alfa-wiedervorlage-status> - - <alfa-link-with-user-name-tooltip-container - *ngIf="wiedervorlageResource | hasLink: linkRel.EDIT; else content" - routerLinkString="wiedervorlage/{{ wiedervorlageResource | toResourceUri }}" - [tooltipTemplate]="tooltip" - [resource]="wiedervorlageResource" - [linkRel]="linkRel.CREATED_BY" - data-test-class="link"> - - <ng-container *ngTemplateOutlet="content"></ng-container> - </alfa-link-with-user-name-tooltip-container> - - <ng-template #content> - <span class="date" data-test-class="frist">{{ wiedervorlageResource.frist | formatToPrettyDate }}</span> - <span class="name" data-test-class="betreff">{{ wiedervorlageResource.betreff }}</span> - </ng-template> - - <alfa-wiedervorlage-in-vorgang-expand-button *ngIf="wiedervorlageResource.beschreibung || wiedervorlageResource.attachments.length > 0" data-test-class="expand-button" - [expanded]="expanded" - (toggle)="toggle()"> - </alfa-wiedervorlage-in-vorgang-expand-button> - </div> - <div *ngIf="expanded" data-test-class="expandable" class="expandable"> - <alfa-text-with-user-name-tooltip-container *ngIf="wiedervorlageResource.beschreibung" - [tooltipTemplate]="tooltip" [text]="wiedervorlageResource.beschreibung" [resource]="wiedervorlageResource" [linkRel]="linkRel.CREATED_BY"> - </alfa-text-with-user-name-tooltip-container> - - <alfa-wiedervorlage-attachment-list-container *ngIf="wiedervorlageResource | hasLink: linkRel.ATTACHMENTS" data-test-id="wiedervorlage-attachment-list-in-vorgang" - [wiedervorlage]="wiedervorlageResource" class="attachments"> - </alfa-wiedervorlage-attachment-list-container> - </div> -</div> \ No newline at end of file +<div [attr.data-test-id]="wiedervorlageResource.betreff | convertForDataTest" class="container"> + <div class="row"> + <alfa-wiedervorlage-status + data-test-class="status" + [matTooltip]="wiedervorlageResource.frist | toTrafficLightTooltip" + [wiedervorlageResource]="wiedervorlageResource" + > + </alfa-wiedervorlage-status> + + <alfa-link-with-user-name-tooltip-container + *ngIf="wiedervorlageResource | hasLink: linkRel.EDIT; else content" + routerLinkString="wiedervorlage/{{ wiedervorlageResource | toResourceUri }}" + [tooltipTemplate]="tooltip" + [resource]="wiedervorlageResource" + [linkRel]="linkRel.CREATED_BY" + data-test-class="link" + > + <ng-container *ngTemplateOutlet="content"></ng-container> + </alfa-link-with-user-name-tooltip-container> + + <ng-template #content> + <span class="date" data-test-class="frist">{{ + wiedervorlageResource.frist | formatToPrettyDate + }}</span> + <span class="name" data-test-class="betreff">{{ wiedervorlageResource.betreff }}</span> + </ng-template> + + <alfa-wiedervorlage-in-vorgang-expand-button + *ngIf="wiedervorlageResource.beschreibung || wiedervorlageResource.attachments.length > 0" + data-test-class="expand-button" + [expanded]="expanded" + (toggle)="toggle()" + > + </alfa-wiedervorlage-in-vorgang-expand-button> + </div> + <div *ngIf="expanded" data-test-class="expandable" class="expandable"> + <alfa-text-with-user-name-tooltip-container + *ngIf="wiedervorlageResource.beschreibung" + [tooltipTemplate]="tooltip" + [text]="wiedervorlageResource.beschreibung" + [resource]="wiedervorlageResource" + [linkRel]="linkRel.CREATED_BY" + > + </alfa-text-with-user-name-tooltip-container> + + <alfa-wiedervorlage-attachment-list-container + *ngIf="wiedervorlageResource | hasLink: linkRel.ATTACHMENTS" + data-test-id="wiedervorlage-attachment-list-in-vorgang" + [wiedervorlage]="wiedervorlageResource" + class="attachments" + > + </alfa-wiedervorlage-attachment-list-container> + </div> +</div> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.scss index 6ab6f38968e14107db7e3c060d61244701331f21..74b8040cbcaa0ffb689c79ed4ee607a7698fbf20 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.scss @@ -22,56 +22,56 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - display: block; + display: block; } .container { - display: inline-flex; - flex-direction: column; - max-width: 100%; + display: inline-flex; + flex-direction: column; + max-width: 100%; } .row { - display: inline-flex; - align-items: center; + display: inline-flex; + align-items: center; } .name { - overflow: hidden; - text-overflow: ellipsis; - margin-right: 4px; - padding-right: 4px; + overflow: hidden; + text-overflow: ellipsis; + margin-right: 4px; + padding-right: 4px; } .date { - margin-left: 4px; - width: 87px; - flex-shrink: 0; - flex-grow: 0; + margin-left: 4px; + width: 87px; + flex-shrink: 0; + flex-grow: 0; } p { - display: inline-block; - margin-bottom: 4px; + display: inline-block; + margin-bottom: 4px; } button { - width: 32px; - height: 32px; - line-height: 32px; + width: 32px; + height: 32px; + line-height: 32px; - mat-icon { - transition: transform 0.1s ease-in-out; - padding-right: 4px; - } + mat-icon { + transition: transform 0.1s ease-in-out; + padding-right: 4px; + } - &.is-open { - mat-icon { - transform: rotate(90deg); - } - } + &.is-open { + mat-icon { + transform: rotate(90deg); + } + } } .expandable { - margin-left: 26px; -} \ No newline at end of file + margin-left: 26px; +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.spec.ts index 01ca2d2a11be4b491ae016d5b6694de96d94d463..f6442e1fe17610a68eb694d0d3ab5676244ba8db 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.spec.ts @@ -29,10 +29,20 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MAT_DATE_LOCALE } from '@angular/material/core'; import { MatIcon } from '@angular/material/icon'; import { RouterTestingModule } from '@angular/router/testing'; -import { ConvertForDataTestPipe, FormatToPrettyDatePipe, HasLinkPipe, ToResourceUriPipe, ToTrafficLightTooltipPipe, formatFullDate } from '@alfa-client/tech-shared'; +import { + ConvertForDataTestPipe, + FormatToPrettyDatePipe, + HasLinkPipe, + ToResourceUriPipe, + ToTrafficLightTooltipPipe, + formatFullDate, +} from '@alfa-client/tech-shared'; import { dispatchEventFromFixture } from '@alfa-client/test-utils'; import { ExpansionPanelComponent } from '@alfa-client/ui'; -import { LinkWithUserNameTooltipContainerComponent, TextWithUserNameTooltipContainerComponent } from '@alfa-client/user-profile'; +import { + LinkWithUserNameTooltipContainerComponent, + TextWithUserNameTooltipContainerComponent, +} from '@alfa-client/user-profile'; import { WiedervorlageResource } from '@alfa-client/wiedervorlage-shared'; import { MatTooltipDirective } from 'libs/ui/src/lib/ui/mattooltip/mattooltip.directive'; import { createWiedervorlageResource } from 'libs/wiedervorlage-shared/test/wiedervorlage'; @@ -45,87 +55,86 @@ import { WiedervorlageInVorgangComponent } from './wiedervorlage-in-vorgang.comp registerLocaleData(localeDe, 'de', localeDeExtra); describe('WiedervorlageInVorgangComponent', () => { - let component: WiedervorlageInVorgangComponent; - let fixture: ComponentFixture<WiedervorlageInVorgangComponent>; - - const expandable: string = '[data-test-class="expandable"]'; - const expandButton: string = '[data-test-class="expand-button"]'; - const wiedervorlage: WiedervorlageResource = createWiedervorlageResource(); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageInVorgangComponent, - FormatToPrettyDatePipe, - ToResourceUriPipe, - ToTrafficLightTooltipPipe, - ConvertForDataTestPipe, - MatIcon, - MatTooltipDirective, - HasLinkPipe, - MockComponent(ExpansionPanelComponent), - MockComponent(WiedervorlageStatusComponent), - MockComponent(WiedervorlageAttachmentListContainerComponent), - MockComponent(WiedervorlageInVorgangExpandButtonComponent), - MockComponent(LinkWithUserNameTooltipContainerComponent), - MockComponent(TextWithUserNameTooltipContainerComponent) - ], - imports: [ - RouterTestingModule - ], - providers: [ - { provide: LOCALE_ID, useValue: 'de' }, - { provide: MAT_DATE_LOCALE, useValue: 'de-DE' } - ] - }) - }); - - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlageInVorgangComponent); - component = fixture.componentInstance; - component.wiedervorlageResource = wiedervorlage; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('tooltip', () => { - - it('should build Tooltip', () => { - const expectedTooltip: string = `${wiedervorlage.betreff}, erstellt am ${formatFullDate(wiedervorlage.createdAt)} von`; - - const tooltip: string = component.formatTooltip(); - - expect(tooltip).toContain(expectedTooltip); - }) - }) - - it('should have data test id', () => { - component.wiedervorlageResource = { ...createWiedervorlageResource(), betreff: 'Hier steht ein Betreff' }; - fixture.detectChanges(); - - const element = fixture.nativeElement.querySelector('[data-test-id="Hier_steht_ein_Betreff"]'); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - describe('beschreibung', () => { - - it('should be hidden initially', () => { - const betreff = fixture.nativeElement.querySelector(expandable); - - expect(betreff).not.toBeInstanceOf(HTMLElement); - }) - - it('should be visible on click', () => { - dispatchEventFromFixture(fixture, expandButton, 'toggle'); - fixture.detectChanges(); - - const betreff = fixture.nativeElement.querySelector(expandable); - - expect(betreff).toBeInstanceOf(HTMLElement); - }) - }) -}); \ No newline at end of file + let component: WiedervorlageInVorgangComponent; + let fixture: ComponentFixture<WiedervorlageInVorgangComponent>; + + const expandable: string = '[data-test-class="expandable"]'; + const expandButton: string = '[data-test-class="expand-button"]'; + const wiedervorlage: WiedervorlageResource = createWiedervorlageResource(); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageInVorgangComponent, + FormatToPrettyDatePipe, + ToResourceUriPipe, + ToTrafficLightTooltipPipe, + ConvertForDataTestPipe, + MatIcon, + MatTooltipDirective, + HasLinkPipe, + MockComponent(ExpansionPanelComponent), + MockComponent(WiedervorlageStatusComponent), + MockComponent(WiedervorlageAttachmentListContainerComponent), + MockComponent(WiedervorlageInVorgangExpandButtonComponent), + MockComponent(LinkWithUserNameTooltipContainerComponent), + MockComponent(TextWithUserNameTooltipContainerComponent), + ], + imports: [RouterTestingModule], + providers: [ + { provide: LOCALE_ID, useValue: 'de' }, + { provide: MAT_DATE_LOCALE, useValue: 'de-DE' }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageInVorgangComponent); + component = fixture.componentInstance; + component.wiedervorlageResource = wiedervorlage; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('tooltip', () => { + it('should build Tooltip', () => { + const expectedTooltip: string = `${wiedervorlage.betreff}, erstellt am ${formatFullDate(wiedervorlage.createdAt)} von`; + + const tooltip: string = component.formatTooltip(); + + expect(tooltip).toContain(expectedTooltip); + }); + }); + + it('should have data test id', () => { + component.wiedervorlageResource = { + ...createWiedervorlageResource(), + betreff: 'Hier steht ein Betreff', + }; + fixture.detectChanges(); + + const element = fixture.nativeElement.querySelector('[data-test-id="Hier_steht_ein_Betreff"]'); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + describe('beschreibung', () => { + it('should be hidden initially', () => { + const betreff = fixture.nativeElement.querySelector(expandable); + + expect(betreff).not.toBeInstanceOf(HTMLElement); + }); + + it('should be visible on click', () => { + dispatchEventFromFixture(fixture, expandButton, 'toggle'); + fixture.detectChanges(); + + const betreff = fixture.nativeElement.querySelector(expandable); + + expect(betreff).toBeInstanceOf(HTMLElement); + }); + }); +}); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.ts index 5b151ef40ae77dc37337f9560e23b19657f95202..2ecd0d57737a93cf1e131fe685d6479a2f4ce71a 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-in-vorgang/wiedervorlage-in-vorgang.component.ts @@ -23,35 +23,38 @@ */ import { Component, Input, OnInit } from '@angular/core'; import { formatFullDate, replacePlaceholders } from '@alfa-client/tech-shared'; -import { WiedervorlageLinkRel, WiedervorlageMessages, WiedervorlageResource } from '@alfa-client/wiedervorlage-shared'; +import { + WiedervorlageLinkRel, + WiedervorlageMessages, + WiedervorlageResource, +} from '@alfa-client/wiedervorlage-shared'; @Component({ - selector: 'alfa-wiedervorlage-in-vorgang', - templateUrl: './wiedervorlage-in-vorgang.component.html', - styleUrls: ['./wiedervorlage-in-vorgang.component.scss'] + selector: 'alfa-wiedervorlage-in-vorgang', + templateUrl: './wiedervorlage-in-vorgang.component.html', + styleUrls: ['./wiedervorlage-in-vorgang.component.scss'], }) export class WiedervorlageInVorgangComponent implements OnInit { + @Input() wiedervorlageResource: WiedervorlageResource; - @Input() wiedervorlageResource: WiedervorlageResource; + tooltip: string; + expanded: boolean; - tooltip: string; - expanded: boolean; + readonly linkRel = WiedervorlageLinkRel; - readonly linkRel = WiedervorlageLinkRel; + ngOnInit(): void { + this.tooltip = this.formatTooltip(); + } - ngOnInit(): void { - this.tooltip = this.formatTooltip(); - } + formatTooltip(): string { + const replacement = { + betreff: this.wiedervorlageResource.betreff, + createdAt: formatFullDate(this.wiedervorlageResource.createdAt), + }; + return replacePlaceholders(WiedervorlageMessages.TOOLTIP, replacement); + } - formatTooltip(): string { - const replacement = { - betreff: this.wiedervorlageResource.betreff, - createdAt: formatFullDate(this.wiedervorlageResource.createdAt) - } - return replacePlaceholders(WiedervorlageMessages.TOOLTIP, replacement); - } - - toggle(): void { - this.expanded = !this.expanded; - } + toggle(): void { + this.expanded = !this.expanded; + } } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.html index 70b1a9e7861b9e03c32fc63033da7eb3814e9ffe..8b4c1a7f64581a5aec215757f19c5291fa663345 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.html @@ -24,19 +24,25 @@ --> <ozgcloud-spinner [stateResource]="wiedervorlageListStateResource"> - <ng-container *ngIf="wiedervorlageListStateResource.resource as wiedervorlageList"> - - <ozgcloud-expansion-panel headline="Wiedervorlagen"> - - <ng-container *ngFor="let wiedervorlageResource of (wiedervorlageList | toEmbeddedResources: wiedervorlageListLinkRel.WIEDERVORLAGE_LIST)"> - <alfa-wiedervorlage-in-vorgang data-test-id="wiedervorlage-in-vorgang" - [wiedervorlageResource]="wiedervorlageResource"> - </alfa-wiedervorlage-in-vorgang> - </ng-container> - - </ozgcloud-expansion-panel> - - <alfa-wiedervorlage-create-button [wiedervorlageListStateResource]="wiedervorlageListStateResource" class="create-button"></alfa-wiedervorlage-create-button> - - </ng-container> + <ng-container *ngIf="wiedervorlageListStateResource.resource as wiedervorlageList"> + <ozgcloud-expansion-panel headline="Wiedervorlagen"> + <ng-container + *ngFor=" + let wiedervorlageResource of wiedervorlageList + | toEmbeddedResources: wiedervorlageListLinkRel.WIEDERVORLAGE_LIST + " + > + <alfa-wiedervorlage-in-vorgang + data-test-id="wiedervorlage-in-vorgang" + [wiedervorlageResource]="wiedervorlageResource" + > + </alfa-wiedervorlage-in-vorgang> + </ng-container> + </ozgcloud-expansion-panel> + + <alfa-wiedervorlage-create-button + [wiedervorlageListStateResource]="wiedervorlageListStateResource" + class="create-button" + ></alfa-wiedervorlage-create-button> + </ng-container> </ozgcloud-spinner> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.scss index 7ce7444e8f309a77b8b841301b4b16ccc6b980ab..a74bde54782798d3ac0bfb8470a6ecb0736d9fbf 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.scss @@ -22,6 +22,6 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .create-button { - display: block; - margin-left: 56px; + display: block; + margin-left: 56px; } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.spec.ts index 1caec737f2a5a29d35bd2e1dbb19a4016b64958a..5d3be1d1cba579f3c76d5278193c9e23593f5760 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.spec.ts @@ -31,29 +31,32 @@ import { WiedervorlageInVorgangComponent } from './wiedervorlage-in-vorgang/wied import { WiedervorlageListInVorgangComponent } from './wiedervorlage-list-in-vorgang.component'; describe('WiedervorlageListInVorgangComponent', () => { - let component: WiedervorlageListInVorgangComponent; - let fixture: ComponentFixture<WiedervorlageListInVorgangComponent>; + let component: WiedervorlageListInVorgangComponent; + let fixture: ComponentFixture<WiedervorlageListInVorgangComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [WiedervorlageListInVorgangComponent, - MockComponent(SpinnerComponent), - MockComponent(ExpansionPanelComponent), - MockComponent(WiedervorlageInVorgangComponent), - MockComponent(WiedervorlageCreateButtonComponent), - ToEmbeddedResourcesPipe - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageListInVorgangComponent, + MockComponent(SpinnerComponent), + MockComponent(ExpansionPanelComponent), + MockComponent(WiedervorlageInVorgangComponent), + MockComponent(WiedervorlageCreateButtonComponent), + ToEmbeddedResourcesPipe, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlageListInVorgangComponent); - component = fixture.componentInstance; - component.wiedervorlageListStateResource = createStateResource(createWiedervorlageListResource()); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageListInVorgangComponent); + component = fixture.componentInstance; + component.wiedervorlageListStateResource = createStateResource( + createWiedervorlageListResource(), + ); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }) + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.ts index ad901696d67cb41c05735a74b07876f37236bdd1..5fc5396575eec528a415013e07b34f588516b40b 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-container/wiedervorlage-list-in-vorgang/wiedervorlage-list-in-vorgang.component.ts @@ -23,16 +23,18 @@ */ import { Component, Input } from '@angular/core'; import { StateResource } from '@alfa-client/tech-shared'; -import { WiedervorlageListLinkRel, WiedervorlageListResource } from '@alfa-client/wiedervorlage-shared'; +import { + WiedervorlageListLinkRel, + WiedervorlageListResource, +} from '@alfa-client/wiedervorlage-shared'; @Component({ - selector: 'alfa-wiedervorlage-list-in-vorgang', - templateUrl: './wiedervorlage-list-in-vorgang.component.html', - styleUrls: ['./wiedervorlage-list-in-vorgang.component.scss'] + selector: 'alfa-wiedervorlage-list-in-vorgang', + templateUrl: './wiedervorlage-list-in-vorgang.component.html', + styleUrls: ['./wiedervorlage-list-in-vorgang.component.scss'], }) export class WiedervorlageListInVorgangComponent { + @Input() wiedervorlageListStateResource: StateResource<WiedervorlageListResource>; - @Input() wiedervorlageListStateResource: StateResource<WiedervorlageListResource>; - - readonly wiedervorlageListLinkRel = WiedervorlageListLinkRel; -} \ No newline at end of file + readonly wiedervorlageListLinkRel = WiedervorlageListLinkRel; +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/_wiedervorlage-list-in-vorgang-list-container.theme.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/_wiedervorlage-list-in-vorgang-list-container.theme.scss index 1bb062fc03a5f09d401303cc3ef8539a79859478..cd6163b02b9341b31c08786b0cf1eaee5e20b372 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/_wiedervorlage-list-in-vorgang-list-container.theme.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/_wiedervorlage-list-in-vorgang-list-container.theme.scss @@ -24,9 +24,9 @@ @import 'variables'; alfa-wiedervorlage-list-in-vorgang-list-container .foreground { - background-color: $background; + background-color: $background; } body.dark alfa-wiedervorlage-list-in-vorgang-list-container .foreground { - background-color: $dark-background; -} \ No newline at end of file + background-color: $dark-background; +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.html index 67ba7ec35af1a6229320e495c196bf6c749b6f98..33413a6f5ddd3bc2a5e0468eb9f658fc075ad1b9 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.html @@ -24,26 +24,29 @@ --> <div *ngIf="wiedervorlagenStateResource$ | async as wiedervorlagenStateResource" class="foreground"> - <table aria-label="Wiedervorlagenliste"> - <tr> - <th scope="col">Wiedervorlage</th> - <th scope="col"><span>Status</span></th> - <th scope="col">Frist</th> - </tr> - <tr *ngFor="let wiedervorlageResource of wiedervorlagenStateResource.resource"> - <td class="name" data-test-class="betreff">{{ wiedervorlageResource.betreff }}</td> - <td> - <div class="status"> - <alfa-wiedervorlage-status - [matTooltip]="wiedervorlageResource.frist | toTrafficLightTooltip" - [wiedervorlageResource]="wiedervorlageResource" - data-test-class="status"> - </alfa-wiedervorlage-status> - </div> - </td> - <td> - <div class="date">{{ wiedervorlageResource.frist | formatToPrettyDate }}</div> - </td> - </tr> - </table> + <table aria-label="Wiedervorlagenliste"> + <tr> + <th scope="col">Wiedervorlage</th> + <th scope="col"><span>Status</span></th> + <th scope="col">Frist</th> + </tr> + <tr *ngFor="let wiedervorlageResource of wiedervorlagenStateResource.resource"> + <td class="name" data-test-class="betreff"> + {{ wiedervorlageResource.betreff }} + </td> + <td> + <div class="status"> + <alfa-wiedervorlage-status + [matTooltip]="wiedervorlageResource.frist | toTrafficLightTooltip" + [wiedervorlageResource]="wiedervorlageResource" + data-test-class="status" + > + </alfa-wiedervorlage-status> + </div> + </td> + <td> + <div class="date">{{ wiedervorlageResource.frist | formatToPrettyDate }}</div> + </td> + </tr> + </table> </div> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.scss index e5bf1fb6613f89b23ddc9eb579d7b770ce346bc7..cf6085e289d610b35a4bcb876db1f1069242ff89 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.scss @@ -22,57 +22,57 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ :host { - position: absolute; - right: 0; - top: 100%; - padding: 8px 0; - z-index: 1; + position: absolute; + right: 0; + top: 100%; + padding: 8px 0; + z-index: 1; - &.up { - top: initial; - bottom: 100%; - } + &.up { + top: initial; + bottom: 100%; + } } .foreground { - border-radius: 8px; - box-shadow: 0 0 10px rgba(#000, 0.4); - padding: 8px 12px; + border-radius: 8px; + box-shadow: 0 0 10px rgba(#000, 0.4); + padding: 8px 12px; } .row { - display: flex; - padding: 4px 0; + display: flex; + padding: 4px 0; } .name { - text-align: left; + text-align: left; } .status { - margin-left: 8px; - margin-right: -2px; + margin-left: 8px; + margin-right: -2px; } .date { - text-align: left; - width: 72px; + text-align: left; + width: 72px; } td, th { - margin: 0; - padding: 4px; + margin: 0; + padding: 4px; } th { - text-align: left; - span { - display: none; - } + text-align: left; + span { + display: none; + } } table { - border-collapse: collapse; - border-spacing: 0; + border-collapse: collapse; + border-spacing: 0; } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.spec.ts index a763421f3e505880b6fb2813dbeca487ba116a59..75ab10717c2841090bd7ac8ff5ae5f504fff248f 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.spec.ts @@ -22,7 +22,11 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { FormatToPrettyDatePipe, ToTrafficLightTooltipPipe, createStateResource } from '@alfa-client/tech-shared'; +import { + FormatToPrettyDatePipe, + ToTrafficLightTooltipPipe, + createStateResource, +} from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; import { MatTooltipDirective } from '@alfa-client/ui'; import { WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; @@ -33,36 +37,39 @@ import { WiedervorlageStatusComponent } from '../wiedervorlage-status/wiedervorl import { WiedervorlageListInVorgangListContainerComponent } from './wiedervorlage-list-in-vorgang-list-container.component'; describe('WiedervorlageListInVorgangListContainerComponent', () => { - let component: WiedervorlageListInVorgangListContainerComponent; - let fixture: ComponentFixture<WiedervorlageListInVorgangListContainerComponent>; + let component: WiedervorlageListInVorgangListContainerComponent; + let fixture: ComponentFixture<WiedervorlageListInVorgangListContainerComponent>; - const wiedervorlageService = { ...mock(WiedervorlageService), getWiedervorlageListResource: () => of(createStateResource(createWiedervorlageListResource())) }; + const wiedervorlageService = { + ...mock(WiedervorlageService), + getWiedervorlageListResource: () => of(createStateResource(createWiedervorlageListResource())), + }; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageListInVorgangListContainerComponent, - MatTooltipDirective, - FormatToPrettyDatePipe, - ToTrafficLightTooltipPipe, - MockComponent(WiedervorlageStatusComponent) - ], - providers: [ - { - provide: WiedervorlageService, - useValue: wiedervorlageService - } - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageListInVorgangListContainerComponent, + MatTooltipDirective, + FormatToPrettyDatePipe, + ToTrafficLightTooltipPipe, + MockComponent(WiedervorlageStatusComponent), + ], + providers: [ + { + provide: WiedervorlageService, + useValue: wiedervorlageService, + }, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlageListInVorgangListContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageListInVorgangListContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.ts index b2792971291dd2982264f9663ce7275bfb7b043f..bec447cfd1e743eef007ef98511dfb179341ab1a 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-list-in-vorgang-list-container/wiedervorlage-list-in-vorgang-list-container.component.ts @@ -22,50 +22,73 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { AfterViewInit, Component, ElementRef, Input, OnChanges } from '@angular/core'; -import { createEmptyStateResource, createStateResource, StateResource } from '@alfa-client/tech-shared'; +import { + createEmptyStateResource, + createStateResource, + StateResource, +} from '@alfa-client/tech-shared'; import { VorgangResource } from '@alfa-client/vorgang-shared'; -import { WiedervorlageLinkRel, WiedervorlageListLinkRel, WiedervorlageResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; +import { + WiedervorlageLinkRel, + WiedervorlageListLinkRel, + WiedervorlageResource, + WiedervorlageService, +} from '@alfa-client/wiedervorlage-shared'; import { getEmbeddedResource, hasLink } from '@ngxp/rest'; import { isNil, isNull } from 'lodash-es'; import { Observable } from 'rxjs'; import { filter, map, startWith } from 'rxjs/operators'; @Component({ - selector: 'alfa-wiedervorlage-list-in-vorgang-list-container', - templateUrl: './wiedervorlage-list-in-vorgang-list-container.component.html', - styleUrls: ['./wiedervorlage-list-in-vorgang-list-container.component.scss'] + selector: 'alfa-wiedervorlage-list-in-vorgang-list-container', + templateUrl: './wiedervorlage-list-in-vorgang-list-container.component.html', + styleUrls: ['./wiedervorlage-list-in-vorgang-list-container.component.scss'], }) export class WiedervorlageListInVorgangListContainerComponent implements OnChanges, AfterViewInit { + @Input() vorgang: VorgangResource; - @Input() vorgang: VorgangResource; + wiedervorlagenStateResource$: Observable<StateResource<WiedervorlageResource[]>>; - wiedervorlagenStateResource$: Observable<StateResource<WiedervorlageResource[]>>; + public readonly wiedervorlageListLinkRel = WiedervorlageListLinkRel; - public readonly wiedervorlageListLinkRel = WiedervorlageListLinkRel; + constructor( + private wiedervorlageService: WiedervorlageService, + private elementRef: ElementRef, + ) {} - constructor( - private wiedervorlageService: WiedervorlageService, - private elementRef: ElementRef - ) { } + ngOnChanges(): void { + if (!isNil(this.vorgang)) { + this.loadWiedervorlagen(); + } + } - ngOnChanges(): void { - if (!isNil(this.vorgang)) { - this.loadWiedervorlagen(); - } - } + ngAfterViewInit(): void { + if (this.elementRef.nativeElement.getBoundingClientRect().bottom >= window.innerHeight) { + this.elementRef.nativeElement.classList.add('up'); + } + } - ngAfterViewInit(): void { - if (this.elementRef.nativeElement.getBoundingClientRect().bottom >= window.innerHeight) { - this.elementRef.nativeElement.classList.add('up'); - } - } - - loadWiedervorlagen(): void { - this.wiedervorlagenStateResource$ = this.wiedervorlageService.loadWiedervorlagenByVorgangStrict(this.vorgang).pipe( - filter(listStateResource => !isNull(listStateResource.resource)), - map(listStateResource => getEmbeddedResource<WiedervorlageResource[]>(listStateResource.resource, this.wiedervorlageListLinkRel.WIEDERVORLAGE_LIST)), - map(wiedervorlagen => createStateResource(wiedervorlagen ? wiedervorlagen.filter(wiedervorlage => hasLink(wiedervorlage, WiedervorlageLinkRel.ERLEDIGEN)) : [])), - startWith(createEmptyStateResource<WiedervorlageResource[]>()) - ); - } + loadWiedervorlagen(): void { + this.wiedervorlagenStateResource$ = this.wiedervorlageService + .loadWiedervorlagenByVorgangStrict(this.vorgang) + .pipe( + filter((listStateResource) => !isNull(listStateResource.resource)), + map((listStateResource) => + getEmbeddedResource<WiedervorlageResource[]>( + listStateResource.resource, + this.wiedervorlageListLinkRel.WIEDERVORLAGE_LIST, + ), + ), + map((wiedervorlagen) => + createStateResource( + wiedervorlagen ? + wiedervorlagen.filter((wiedervorlage) => + hasLink(wiedervorlage, WiedervorlageLinkRel.ERLEDIGEN), + ) + : [], + ), + ), + startWith(createEmptyStateResource<WiedervorlageResource[]>()), + ); + } } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.html index b100f5c8eba6918d529577fb9d20313bdaa7a6a2..6a7b3a3dc586c3a9b3e005e20265e7b7a644c8ae 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.html @@ -24,16 +24,14 @@ --> <ng-container *ngIf="wiedervorlageListStateResource$ | async as wiedervorlageListStateResource"> - <ng-container *ngIf="wiedervorlageListStateResource.resource"> - - <ozgcloud-spinner [stateResource]="wiedervorlageStateResource$ | async"> - - <alfa-wiedervorlage-page data-test-id="wiedervorlage-page" - [wiedervorlageListStateResource]="wiedervorlageListStateResource" - [wiedervorlageStateResource]="wiedervorlageStateResource$ | async"> - </alfa-wiedervorlage-page> - - </ozgcloud-spinner> - - </ng-container> -</ng-container> \ No newline at end of file + <ng-container *ngIf="wiedervorlageListStateResource.resource"> + <ozgcloud-spinner [stateResource]="wiedervorlageStateResource$ | async"> + <alfa-wiedervorlage-page + data-test-id="wiedervorlage-page" + [wiedervorlageListStateResource]="wiedervorlageListStateResource" + [wiedervorlageStateResource]="wiedervorlageStateResource$ | async" + > + </alfa-wiedervorlage-page> + </ozgcloud-spinner> + </ng-container> +</ng-container> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.spec.ts index ec69ceaaf357ab065dc37232ddc561f0440fccce..399d895a20d993b94a16a7e0c9bbbc0ba3128d0a 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.spec.ts @@ -22,109 +22,125 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { StateResource, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared'; +import { + StateResource, + createEmptyStateResource, + createStateResource, +} from '@alfa-client/tech-shared'; import { getElementFromFixture, mock } from '@alfa-client/test-utils'; import { SpinnerComponent } from '@alfa-client/ui'; import { WiedervorlageResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; import { cold, hot } from 'jest-marbles'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; -import { createWiedervorlageListResource, createWiedervorlageResource } from 'libs/wiedervorlage-shared/test/wiedervorlage'; +import { + createWiedervorlageListResource, + createWiedervorlageResource, +} from 'libs/wiedervorlage-shared/test/wiedervorlage'; import { MockComponent } from 'ng-mocks'; import { Observable, of } from 'rxjs'; import { WiedervorlagePageContainerComponent } from './wiedervorlage-page-container.component'; import { WiedervorlagePageComponent } from './wiedervorlage-page/wiedervorlage-page.component'; describe('WiedervorlagePageContainerComponent', () => { - let component: WiedervorlagePageContainerComponent; - let fixture: ComponentFixture<WiedervorlagePageContainerComponent>; - - const wiedervorlagePage: string = getDataTestIdOf('wiedervorlage-page'); - const wiedervorlageService = mock(WiedervorlageService); - - beforeEach(async () => { - TestBed.configureTestingModule({ - declarations: [ - WiedervorlagePageContainerComponent, - MockComponent(SpinnerComponent), - MockComponent(WiedervorlagePageComponent) - ], - providers: [ - { - provide: WiedervorlageService, - useValue: wiedervorlageService - } - ] - }) - }); - - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlagePageContainerComponent); - component = fixture.componentInstance; - wiedervorlageService.isNewWiedervorlage.mockReturnValue(of(true)); - wiedervorlageService.getWiedervorlage.mockReturnValue(of(createStateResource(createWiedervorlageResource()))); - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ng after content init', () => { - - it('should load wiedervorlageList', () => { - component.ngAfterContentInit(); - - expect(wiedervorlageService.getWiedervorlageList).toHaveBeenCalled(); - }) - - it('should get wiedervorlage', () => { - component.getWiedervorlage = jest.fn().mockReturnValue(of(createStateResource(createWiedervorlageResource()))); - - component.ngAfterContentInit(); - - expect(component.getWiedervorlage).toHaveBeenCalled(); - }) - }) - - describe('getWiedervorlage', () => { - - it('should call service if not new', () => { - const wiedervorlageStateResource: StateResource<WiedervorlageResource> = createStateResource(createWiedervorlageResource()); - wiedervorlageService.getWiedervorlage.mockReturnValue(cold('a' , { a: wiedervorlageStateResource })); - wiedervorlageService.isNewWiedervorlage.mockReturnValue(false); - - const wiedervorlage: Observable<StateResource<WiedervorlageResource>> = component.getWiedervorlage(); - - expect(wiedervorlage).toBeObservable(hot('a', { a: wiedervorlageStateResource })); - }) - - it.skip('should return empty stateResource if new', () => { - wiedervorlageService.isNewWiedervorlage.mockReturnValue(true); - - const wiedervorlage: Observable<StateResource<WiedervorlageResource>> = component.getWiedervorlage(); - - expect(wiedervorlage).toBeObservable(hot('a', { a: createEmptyStateResource() })); - }) - }) - - describe.skip('FIXME :/: wiedervoralge page', () => { - - it('should show on existing wiedervorlageList resource', () => { - wiedervorlageService.getWiedervorlageList.mockReturnValue(of(createStateResource(createWiedervorlageListResource()))); - - component.ngAfterContentInit(); - const element = getElementFromFixture(fixture, wiedervorlagePage); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should not show by empty wiedervorlageList resource', () => { - wiedervorlageService.getWiedervorlageList.mockReturnValue(of(createEmptyStateResource())); - - component.ngAfterContentInit(); - const element = getElementFromFixture(fixture, wiedervorlagePage); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) -}); \ No newline at end of file + let component: WiedervorlagePageContainerComponent; + let fixture: ComponentFixture<WiedervorlagePageContainerComponent>; + + const wiedervorlagePage: string = getDataTestIdOf('wiedervorlage-page'); + const wiedervorlageService = mock(WiedervorlageService); + + beforeEach(async () => { + TestBed.configureTestingModule({ + declarations: [ + WiedervorlagePageContainerComponent, + MockComponent(SpinnerComponent), + MockComponent(WiedervorlagePageComponent), + ], + providers: [ + { + provide: WiedervorlageService, + useValue: wiedervorlageService, + }, + ], + }); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlagePageContainerComponent); + component = fixture.componentInstance; + wiedervorlageService.isNewWiedervorlage.mockReturnValue(of(true)); + wiedervorlageService.getWiedervorlage.mockReturnValue( + of(createStateResource(createWiedervorlageResource())), + ); + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ng after content init', () => { + it('should load wiedervorlageList', () => { + component.ngAfterContentInit(); + + expect(wiedervorlageService.getWiedervorlageList).toHaveBeenCalled(); + }); + + it('should get wiedervorlage', () => { + component.getWiedervorlage = jest + .fn() + .mockReturnValue(of(createStateResource(createWiedervorlageResource()))); + + component.ngAfterContentInit(); + + expect(component.getWiedervorlage).toHaveBeenCalled(); + }); + }); + + describe('getWiedervorlage', () => { + it('should call service if not new', () => { + const wiedervorlageStateResource: StateResource<WiedervorlageResource> = createStateResource( + createWiedervorlageResource(), + ); + wiedervorlageService.getWiedervorlage.mockReturnValue( + cold('a', { a: wiedervorlageStateResource }), + ); + wiedervorlageService.isNewWiedervorlage.mockReturnValue(false); + + const wiedervorlage: Observable<StateResource<WiedervorlageResource>> = + component.getWiedervorlage(); + + expect(wiedervorlage).toBeObservable(hot('a', { a: wiedervorlageStateResource })); + }); + + it.skip('should return empty stateResource if new', () => { + wiedervorlageService.isNewWiedervorlage.mockReturnValue(true); + + const wiedervorlage: Observable<StateResource<WiedervorlageResource>> = + component.getWiedervorlage(); + + expect(wiedervorlage).toBeObservable(hot('a', { a: createEmptyStateResource() })); + }); + }); + + describe.skip('FIXME :/: wiedervoralge page', () => { + it('should show on existing wiedervorlageList resource', () => { + wiedervorlageService.getWiedervorlageList.mockReturnValue( + of(createStateResource(createWiedervorlageListResource())), + ); + + component.ngAfterContentInit(); + const element = getElementFromFixture(fixture, wiedervorlagePage); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should not show by empty wiedervorlageList resource', () => { + wiedervorlageService.getWiedervorlageList.mockReturnValue(of(createEmptyStateResource())); + + component.ngAfterContentInit(); + const element = getElementFromFixture(fixture, wiedervorlagePage); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); +}); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.ts index ea9b8be4d5264002010ac5fb3ceed2aa22d07e0a..c1d512f922d959164beae4fc2de2d97757143b19 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page-container.component.ts @@ -23,33 +23,38 @@ */ import { AfterContentInit, Component } from '@angular/core'; import { StateResource, createEmptyStateResource } from '@alfa-client/tech-shared'; -import { WiedervorlageListResource, WiedervorlageResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; +import { + WiedervorlageListResource, + WiedervorlageResource, + WiedervorlageService, +} from '@alfa-client/wiedervorlage-shared'; import { Observable, of, startWith } from 'rxjs'; import { WiedervorlageFormService } from './wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice'; @Component({ - selector: 'alfa-wiedervorlage-page-container', - templateUrl: './wiedervorlage-page-container.component.html', - styleUrls: ['./wiedervorlage-page-container.component.scss'], - providers: [WiedervorlageFormService] + selector: 'alfa-wiedervorlage-page-container', + templateUrl: './wiedervorlage-page-container.component.html', + styleUrls: ['./wiedervorlage-page-container.component.scss'], + providers: [WiedervorlageFormService], }) export class WiedervorlagePageContainerComponent implements AfterContentInit { + wiedervorlageListStateResource$: Observable<StateResource<WiedervorlageListResource>>; + wiedervorlageStateResource$: Observable<StateResource<WiedervorlageResource>>; - wiedervorlageListStateResource$: Observable<StateResource<WiedervorlageListResource>>; - wiedervorlageStateResource$: Observable<StateResource<WiedervorlageResource>>; + constructor(private wiedervorlageService: WiedervorlageService) {} - constructor(private wiedervorlageService: WiedervorlageService) { } + ngAfterContentInit(): void { + this.wiedervorlageListStateResource$ = this.wiedervorlageService.getWiedervorlageList(); + this.wiedervorlageStateResource$ = this.getWiedervorlage().pipe( + startWith(createEmptyStateResource<WiedervorlageResource>(true)), + ); + } - ngAfterContentInit(): void { - this.wiedervorlageListStateResource$ = this.wiedervorlageService.getWiedervorlageList(); - this.wiedervorlageStateResource$ = this.getWiedervorlage().pipe(startWith(createEmptyStateResource<WiedervorlageResource>(true))); - } - - getWiedervorlage(): Observable<StateResource<WiedervorlageResource>> { - if(this.wiedervorlageService.isNewWiedervorlage()){ - return of(createEmptyStateResource<WiedervorlageResource>()); - } else { - return this.wiedervorlageService.getWiedervorlage(); - } - } -} \ No newline at end of file + getWiedervorlage(): Observable<StateResource<WiedervorlageResource>> { + if (this.wiedervorlageService.isNewWiedervorlage()) { + return of(createEmptyStateResource<WiedervorlageResource>()); + } else { + return this.wiedervorlageService.getWiedervorlage(); + } + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.html index ede46db22d54c95acde79a99cad52a11342bcede..f6411b20b224015340fe00810a4c4af479d79b6d 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.html @@ -25,5 +25,7 @@ --> <ozgcloud-back-button linkTo="../.." label="zurück zur Detailseite"></ozgcloud-back-button> <alfa-erledigen-button-container [wiedervorlage]="wiedervorlage"></alfa-erledigen-button-container> -<alfa-wiedereroeffnen-button-container [wiedervorlage]="wiedervorlage"></alfa-wiedereroeffnen-button-container> +<alfa-wiedereroeffnen-button-container + [wiedervorlage]="wiedervorlage" +></alfa-wiedereroeffnen-button-container> <alfa-submit-wiedervorlage-button [showAsIconButton]="true"></alfa-submit-wiedervorlage-button> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.scss index 688daf0a90438b6fb05da882249e70d2811355df..7e09d057c1d9b65934edb37077bb8cc2e8cf4511 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.scss @@ -22,5 +22,5 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .back-button { - margin-right: 6px; + margin-right: 6px; } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.spec.ts index 657f4482aad01a7bb722c1ae64ef780cfdfc00b1..1f5351d8138815228ad59ba7e6fb7125b3b9d41a 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.spec.ts @@ -31,29 +31,29 @@ import { WiedereroeffnenButtonContainerComponent } from '../../../wiedereroeffne import { WiedervorlageActionButtonsComponent } from './wiedervorlage-action-buttons.component'; describe('WiedervorlageActionButtonsComponent', () => { - let component: WiedervorlageActionButtonsComponent; - let fixture: ComponentFixture<WiedervorlageActionButtonsComponent>; + let component: WiedervorlageActionButtonsComponent; + let fixture: ComponentFixture<WiedervorlageActionButtonsComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageActionButtonsComponent, - MatIcon, - MockComponent(BackButtonComponent), - MockComponent(SubmitWiedervorlageButtonComponent), - MockComponent(ErledigenButtonContainerComponent), - MockComponent(WiedereroeffnenButtonContainerComponent) - ] - }) - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageActionButtonsComponent, + MatIcon, + MockComponent(BackButtonComponent), + MockComponent(SubmitWiedervorlageButtonComponent), + MockComponent(ErledigenButtonContainerComponent), + MockComponent(WiedereroeffnenButtonContainerComponent), + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlageActionButtonsComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageActionButtonsComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.ts index 6ec0bfb065747918eb4106056764e4796451b809..0fd8df4baa743563b2f0205c01abd4abf3a0f24d 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-action-buttons/wiedervorlage-action-buttons.component.ts @@ -25,11 +25,10 @@ import { Component, Input } from '@angular/core'; import { WiedervorlageResource } from '@alfa-client/wiedervorlage-shared'; @Component({ - selector: 'alfa-wiedervorlage-action-buttons', - templateUrl: './wiedervorlage-action-buttons.component.html', - styleUrls: ['./wiedervorlage-action-buttons.component.scss'] + selector: 'alfa-wiedervorlage-action-buttons', + templateUrl: './wiedervorlage-action-buttons.component.html', + styleUrls: ['./wiedervorlage-action-buttons.component.scss'], }) export class WiedervorlageActionButtonsComponent { - - @Input() wiedervorlage: WiedervorlageResource; -} \ No newline at end of file + @Input() wiedervorlage: WiedervorlageResource; +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.html index 3b9ada9bb87ea4f7fbd187e463d8e7773dbbe173..694c6eecc9c9f5d9d4140c7358a66ed0fc0e827c 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.html @@ -24,7 +24,11 @@ --> <ng-container *ngIf="vorgangStatResource$ | async as vorgangStatResource"> - <alfa-wiedervorlage-breadcrumb *ngIf="vorgangStatResource.resource" data-test-id="wiedervorlage-breadcrumb" - [vorgang]="vorgangStatResource.resource" [wiedervorlage]="wiedervorlage"> - </alfa-wiedervorlage-breadcrumb> -</ng-container> \ No newline at end of file + <alfa-wiedervorlage-breadcrumb + *ngIf="vorgangStatResource.resource" + data-test-id="wiedervorlage-breadcrumb" + [vorgang]="vorgangStatResource.resource" + [wiedervorlage]="wiedervorlage" + > + </alfa-wiedervorlage-breadcrumb> +</ng-container> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.spec.ts index 231976edfcf875dde66649ee0efc002e0834cdd7..1aab12aa7586c34f25fd2b677b2a809430513c7d 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.spec.ts @@ -33,66 +33,63 @@ import { WiedervorlageBreadcrumbContainerComponent } from './wiedervorlage-bread import { WiedervorlageBreadcrumbComponent } from './wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component'; describe('WiedervorlageBreadcrumbContainerComponent', () => { - let component: WiedervorlageBreadcrumbContainerComponent; - let fixture: ComponentFixture<WiedervorlageBreadcrumbContainerComponent>; - - const vorgangService = mock(VorgangService); - - const wiedervorlageBreadcrumb: string = getDataTestIdOf('wiedervorlage-breadcrumb'); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageBreadcrumbContainerComponent, - MockComponent(WiedervorlageBreadcrumbComponent) - ], - providers: [ - { - provide: VorgangService, - useValue: vorgangService - } - ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlageBreadcrumbContainerComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnChanges', () => { - - it('should call vorgangService to get vorgang', () => { - component.ngOnChanges(); - - expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); - }) - }) - - describe('breadcrumb', () => { - - it('should show if vorgang loaded', () => { - component.vorgangStatResource$ = of(createStateResource(createVorgangResource())); - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, wiedervorlageBreadcrumb); - - expect(element).toBeInstanceOf(HTMLElement); - }) - - it('should not show if vorgang not laoded', () => { - component.vorgangStatResource$ = of(createEmptyStateResource<VorgangResource>()); - - fixture.detectChanges(); - const element = getElementFromFixture(fixture, wiedervorlageBreadcrumb); - - expect(element).not.toBeInstanceOf(HTMLElement); - }) - }) -}) + let component: WiedervorlageBreadcrumbContainerComponent; + let fixture: ComponentFixture<WiedervorlageBreadcrumbContainerComponent>; + + const vorgangService = mock(VorgangService); + + const wiedervorlageBreadcrumb: string = getDataTestIdOf('wiedervorlage-breadcrumb'); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageBreadcrumbContainerComponent, + MockComponent(WiedervorlageBreadcrumbComponent), + ], + providers: [ + { + provide: VorgangService, + useValue: vorgangService, + }, + ], + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageBreadcrumbContainerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnChanges', () => { + it('should call vorgangService to get vorgang', () => { + component.ngOnChanges(); + + expect(vorgangService.getVorgangWithEingang).toHaveBeenCalled(); + }); + }); + + describe('breadcrumb', () => { + it('should show if vorgang loaded', () => { + component.vorgangStatResource$ = of(createStateResource(createVorgangResource())); + + fixture.detectChanges(); + const element = getElementFromFixture(fixture, wiedervorlageBreadcrumb); + + expect(element).toBeInstanceOf(HTMLElement); + }); + + it('should not show if vorgang not laoded', () => { + component.vorgangStatResource$ = of(createEmptyStateResource<VorgangResource>()); + + fixture.detectChanges(); + const element = getElementFromFixture(fixture, wiedervorlageBreadcrumb); + + expect(element).not.toBeInstanceOf(HTMLElement); + }); + }); +}); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.ts index 226452456ced802d774293ec7dd26e669d15cffd..b0a5d539423e3c1f665cbb7c4818aaeb6e57bea1 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb-container.component.ts @@ -28,19 +28,18 @@ import { WiedervorlageResource } from '@alfa-client/wiedervorlage-shared'; import { Observable } from 'rxjs'; @Component({ - selector: 'alfa-wiedervorlage-breadcrumb-container', - templateUrl: './wiedervorlage-breadcrumb-container.component.html', - styleUrls: ['./wiedervorlage-breadcrumb-container.component.scss'] + selector: 'alfa-wiedervorlage-breadcrumb-container', + templateUrl: './wiedervorlage-breadcrumb-container.component.html', + styleUrls: ['./wiedervorlage-breadcrumb-container.component.scss'], }) export class WiedervorlageBreadcrumbContainerComponent implements OnChanges { + @Input() wiedervorlage: WiedervorlageResource; - @Input() wiedervorlage: WiedervorlageResource; + vorgangStatResource$: Observable<StateResource<VorgangResource>>; - vorgangStatResource$: Observable<StateResource<VorgangResource>>; + constructor(private vorgangService: VorgangService) {} - constructor(private vorgangService: VorgangService) { } - - ngOnChanges(): void { - this.vorgangStatResource$ = this.vorgangService.getVorgangWithEingang(); - } + ngOnChanges(): void { + this.vorgangStatResource$ = this.vorgangService.getVorgangWithEingang(); + } } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/_wiedervorlage-breadcrumb.theme.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/_wiedervorlage-breadcrumb.theme.scss index 83d71fb4e96097c43d8f56bb48718798321f5ce5..501b551416037b18082a9a8131e199ff0cd0c71f 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/_wiedervorlage-breadcrumb.theme.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/_wiedervorlage-breadcrumb.theme.scss @@ -25,13 +25,13 @@ @use '@angular/material' as mat; @mixin breadcrumb($theme) { - $color-config: mat.get-color-config($theme); - $primary: map.get($color-config, 'primary'); + $color-config: mat.get-color-config($theme); + $primary: map.get($color-config, 'primary'); - alfa-breadcrumb, - alfa-vorgang-in-postfach-breadcrumb { - a { - color: mat.get-color-from-palette($primary); - } - } + alfa-breadcrumb, + alfa-vorgang-in-postfach-breadcrumb { + a { + color: mat.get-color-from-palette($primary); + } + } } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.scss index 799ca154698da0a9bcc0d552f4364bb9d05f2442..aec918f0e6ec45b7cb161e4fd7a59f18b7d9a4c5 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.scss @@ -24,23 +24,23 @@ @import 'variables'; :host { - display: block; - font-size: 18px; - margin: 0 -4px 24px -4px; + display: block; + font-size: 18px; + margin: 0 -4px 24px -4px; - ::ng-deep span { - margin: 0 4px; - } + ::ng-deep span { + margin: 0 4px; + } - a { - text-decoration: none; - outline: 0; - margin: -3px; - padding: 3px; + a { + text-decoration: none; + outline: 0; + margin: -3px; + padding: 3px; - &:focus { - border-radius: 12px; - background-color: rgba(#777, 0.16); - } - } -} \ No newline at end of file + &:focus { + border-radius: 12px; + background-color: rgba(#777, 0.16); + } + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.spec.ts index 9d47005d8573a18c87beb4c1e25af6d542295b88..e5fcd73f9f83d983a029ee1f307c88a721df8cf8 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.spec.ts @@ -32,38 +32,36 @@ import { MockComponent } from 'ng-mocks'; import { WiedervorlageBreadcrumbComponent } from './wiedervorlage-breadcrumb.component'; describe('BreadcrumbComponent', () => { - let component: WiedervorlageBreadcrumbComponent; - let fixture: ComponentFixture<WiedervorlageBreadcrumbComponent>; + let component: WiedervorlageBreadcrumbComponent; + let fixture: ComponentFixture<WiedervorlageBreadcrumbComponent>; - const vorgangService = mock(VorgangService); + const vorgangService = mock(VorgangService); - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [ - RouterTestingModule - ], - declarations: [ - WiedervorlageBreadcrumbComponent, - ToResourceUriPipe, - MockComponent(AktenzeichenComponent), - MockComponent(SpinnerComponent) - ], - providers: [ - { - provide: VorgangService, - useValue: vorgangService - } - ] - }) - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [RouterTestingModule], + declarations: [ + WiedervorlageBreadcrumbComponent, + ToResourceUriPipe, + MockComponent(AktenzeichenComponent), + MockComponent(SpinnerComponent), + ], + providers: [ + { + provide: VorgangService, + useValue: vorgangService, + }, + ], + }); + }); - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlageBreadcrumbComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageBreadcrumbComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.ts index 370bd46b8413506654a489b00d72bf04548240c7..d4f5108551db4bc9e246f30efb74d8ff36137003 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-breadcrumb-container/wiedervorlage-breadcrumb/wiedervorlage-breadcrumb.component.ts @@ -26,20 +26,19 @@ import { VorgangResource } from '@alfa-client/vorgang-shared'; import { WiedervorlageMessages, WiedervorlageResource } from '@alfa-client/wiedervorlage-shared'; @Component({ - selector: 'alfa-wiedervorlage-breadcrumb', - templateUrl: './wiedervorlage-breadcrumb.component.html', - styleUrls: ['./wiedervorlage-breadcrumb.component.scss'] + selector: 'alfa-wiedervorlage-breadcrumb', + templateUrl: './wiedervorlage-breadcrumb.component.html', + styleUrls: ['./wiedervorlage-breadcrumb.component.scss'], }) export class WiedervorlageBreadcrumbComponent implements OnChanges { + @Input() vorgang: VorgangResource; + @Input() wiedervorlage: WiedervorlageResource; - @Input() vorgang: VorgangResource; - @Input() wiedervorlage: WiedervorlageResource; + betreff: string; - betreff: string; - - ngOnChanges(changes: SimpleChanges) { - if (changes.wiedervorlage) { - this.betreff = this.wiedervorlage ? this.wiedervorlage.betreff : WiedervorlageMessages.NEW; - } - } -} \ No newline at end of file + ngOnChanges(changes: SimpleChanges) { + if (changes.wiedervorlage) { + this.betreff = this.wiedervorlage ? this.wiedervorlage.betreff : WiedervorlageMessages.NEW; + } + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.html index 7f28f7d8864fbcfaaad4be9f9205620cf4d84fff..c90498fb6fd7f0555c399ffc1403cbca28f01d6c 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.html @@ -24,22 +24,26 @@ --> <form class="form" [formGroup]="formService.form"> - - <ozgcloud-text-editor label="Betreff" [formControlName]="formServiceClass.FIELD_BETREFF"> - </ozgcloud-text-editor> - - <ozgcloud-textarea-editor label="Beschreibung" [formControlName]="formServiceClass.FIELD_BESCHREIBUNG"> - </ozgcloud-textarea-editor> - - <ozgcloud-date-editor class="date" label="Frist" [formControlName]="formServiceClass.FIELD_FRIST"> - </ozgcloud-date-editor> - - <alfa-binary-file-attachment-container data-test-id="wiedervorlage-attachment-list" - [existFiles]="attachments$ | async" - [formArrayName]="formServiceClass.FIELD_ATTACHMENTS" - [uploadStateResource]="wiedervorlageListStateResource" - [linkRelUploadAttachment]="wiedervorlageListLinkrel.UPLOAD_FILE"> - </alfa-binary-file-attachment-container> - - <alfa-submit-wiedervorlage-button class="submit-button"></alfa-submit-wiedervorlage-button> + <ozgcloud-text-editor label="Betreff" [formControlName]="formServiceClass.FIELD_BETREFF"> + </ozgcloud-text-editor> + + <ozgcloud-textarea-editor + label="Beschreibung" + [formControlName]="formServiceClass.FIELD_BESCHREIBUNG" + > + </ozgcloud-textarea-editor> + + <ozgcloud-date-editor class="date" label="Frist" [formControlName]="formServiceClass.FIELD_FRIST"> + </ozgcloud-date-editor> + + <alfa-binary-file-attachment-container + data-test-id="wiedervorlage-attachment-list" + [existFiles]="attachments$ | async" + [formArrayName]="formServiceClass.FIELD_ATTACHMENTS" + [uploadStateResource]="wiedervorlageListStateResource" + [linkRelUploadAttachment]="wiedervorlageListLinkrel.UPLOAD_FILE" + > + </alfa-binary-file-attachment-container> + + <alfa-submit-wiedervorlage-button class="submit-button"></alfa-submit-wiedervorlage-button> </form> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.scss index eb6a7b6a7abf739c392a61af0877672bc6bdedea..5f106452a824f5a97e00604e55b95f71ab2e1837 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.scss @@ -22,20 +22,20 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .form { - display: flex; - flex-direction: column; - max-width: 560px; + display: flex; + flex-direction: column; + max-width: 560px; - .date { - max-width: 200px; - } + .date { + max-width: 200px; + } - .submit-button { - margin: 16px 0; - } + .submit-button { + margin: 16px 0; + } - ::ng-deep mat-form-field { - width: 100%; - margin: 4px 0; - } + ::ng-deep mat-form-field { + width: 100%; + margin: 4px 0; + } } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts index 1a128428638419cfcaf44efbdc4619467bed792e..03c957fcb24ac964fd1a43b972fa30b1685d37b5 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.spec.ts @@ -28,7 +28,11 @@ import { BinaryFileAttachmentContainerComponent } from '@alfa-client/binary-file import { BinaryFileListResource } from '@alfa-client/binary-file-shared'; import { Mock, mock, useFromMock } from '@alfa-client/test-utils'; import { DateEditorComponent, TextAreaEditorComponent, TextEditorComponent } from '@alfa-client/ui'; -import { WiedervorlageLinkRel, WiedervorlageResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; +import { + WiedervorlageLinkRel, + WiedervorlageResource, + WiedervorlageService, +} from '@alfa-client/wiedervorlage-shared'; import { createBinaryFileListResource } from 'libs/binary-file-shared/test/binary-file'; import { createWiedervorlageResource } from 'libs/wiedervorlage-shared/test/wiedervorlage'; import { MockComponent } from 'ng-mocks'; @@ -38,116 +42,118 @@ import { WiedervorlageFormComponent } from './wiedervorlage-form.component'; import { WiedervorlageFormService } from './wiedervorlage.formservice'; describe('WiedervorlageFormComponent', () => { - let component: WiedervorlageFormComponent; - let fixture: ComponentFixture<WiedervorlageFormComponent>; - - const formService = new WiedervorlageFormService(new UntypedFormBuilder(), useFromMock(mock(WiedervorlageService))); - const wiedervorlageService: Mock<WiedervorlageService> = mock(WiedervorlageService); - const wiedervorlage: WiedervorlageResource = createWiedervorlageResource(); - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageFormComponent, - MockComponent(DateEditorComponent), - MockComponent(TextEditorComponent), - MockComponent(TextAreaEditorComponent), - MockComponent(BinaryFileAttachmentContainerComponent), - MockComponent(SubmitWiedervorlageButtonComponent) - ], - imports: [ - ReactiveFormsModule - ], - providers: [ - { - provide: WiedervorlageFormService, - useValue: formService - }, - { - provide: WiedervorlageService, - useValue: wiedervorlageService - } - ] - }) - }); - - beforeEach(() => { - formService.patch = jest.fn(); - - fixture = TestBed.createComponent(WiedervorlageFormComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); - - describe('ngOnChanges', () => { - - const simpleChanges: SimpleChanges = <any>{ wiedervorlage }; - - beforeEach(() => { - component.wiedervorlage = wiedervorlage; - component.patchWiedervorlage = jest.fn(); - component.updateAttachments = jest.fn(); - }) - - it('should call patchWiedervorlage', () => { - component.ngOnChanges(simpleChanges); - - expect(component.patchWiedervorlage).toHaveBeenCalled(); - }) - - it('should call updateAttachments', () => { - component.ngOnChanges(simpleChanges); - - expect(component.updateAttachments).toHaveBeenCalled(); - }) - }) - - describe('updateAttachments', () => { - - const binaryFileListResource: BinaryFileListResource = createBinaryFileListResource(); - - beforeEach(() => { - wiedervorlageService.getAttachmentList.mockReturnValue(of(binaryFileListResource)); - }) - - it('should call wiedervorlage service to get attachments if links exists', () => { - const wiedervorlageWithAttachments: WiedervorlageResource = createWiedervorlageResource([WiedervorlageLinkRel.ATTACHMENTS]); - component.wiedervorlage = wiedervorlageWithAttachments; - - component.updateAttachments(); - - expect(wiedervorlageService.getAttachmentList).toHaveBeenCalledWith(wiedervorlageWithAttachments); - }) - - it('should NOT call wiedervorlage service if link is not present', () => { - component.wiedervorlage = wiedervorlage; - - component.updateAttachments(); - - expect(wiedervorlageService.getAttachmentList).not.toHaveBeenCalledWith(wiedervorlage); - }) - }) - - describe('patch wiedervorlage', () => { - - it('should NOT patch by formservice', () => { - component.wiedervorlage = null; - - component.patchWiedervorlage(); - - expect(formService.patch).not.toHaveBeenCalled(); - }) - - it('should patch by formservice', () => { - component.wiedervorlage = wiedervorlage; - - component.patchWiedervorlage(); - - expect(formService.patch).toHaveBeenCalledWith(wiedervorlage); - }) - }) + let component: WiedervorlageFormComponent; + let fixture: ComponentFixture<WiedervorlageFormComponent>; + + const formService = new WiedervorlageFormService( + new UntypedFormBuilder(), + useFromMock(mock(WiedervorlageService)), + ); + const wiedervorlageService: Mock<WiedervorlageService> = mock(WiedervorlageService); + const wiedervorlage: WiedervorlageResource = createWiedervorlageResource(); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageFormComponent, + MockComponent(DateEditorComponent), + MockComponent(TextEditorComponent), + MockComponent(TextAreaEditorComponent), + MockComponent(BinaryFileAttachmentContainerComponent), + MockComponent(SubmitWiedervorlageButtonComponent), + ], + imports: [ReactiveFormsModule], + providers: [ + { + provide: WiedervorlageFormService, + useValue: formService, + }, + { + provide: WiedervorlageService, + useValue: wiedervorlageService, + }, + ], + }); + }); + + beforeEach(() => { + formService.patch = jest.fn(); + + fixture = TestBed.createComponent(WiedervorlageFormComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); + + describe('ngOnChanges', () => { + const simpleChanges: SimpleChanges = <any>{ wiedervorlage }; + + beforeEach(() => { + component.wiedervorlage = wiedervorlage; + component.patchWiedervorlage = jest.fn(); + component.updateAttachments = jest.fn(); + }); + + it('should call patchWiedervorlage', () => { + component.ngOnChanges(simpleChanges); + + expect(component.patchWiedervorlage).toHaveBeenCalled(); + }); + + it('should call updateAttachments', () => { + component.ngOnChanges(simpleChanges); + + expect(component.updateAttachments).toHaveBeenCalled(); + }); + }); + + describe('updateAttachments', () => { + const binaryFileListResource: BinaryFileListResource = createBinaryFileListResource(); + + beforeEach(() => { + wiedervorlageService.getAttachmentList.mockReturnValue(of(binaryFileListResource)); + }); + + it('should call wiedervorlage service to get attachments if links exists', () => { + const wiedervorlageWithAttachments: WiedervorlageResource = createWiedervorlageResource([ + WiedervorlageLinkRel.ATTACHMENTS, + ]); + component.wiedervorlage = wiedervorlageWithAttachments; + + component.updateAttachments(); + + expect(wiedervorlageService.getAttachmentList).toHaveBeenCalledWith( + wiedervorlageWithAttachments, + ); + }); + + it('should NOT call wiedervorlage service if link is not present', () => { + component.wiedervorlage = wiedervorlage; + + component.updateAttachments(); + + expect(wiedervorlageService.getAttachmentList).not.toHaveBeenCalledWith(wiedervorlage); + }); + }); + + describe('patch wiedervorlage', () => { + it('should NOT patch by formservice', () => { + component.wiedervorlage = null; + + component.patchWiedervorlage(); + + expect(formService.patch).not.toHaveBeenCalled(); + }); + + it('should patch by formservice', () => { + component.wiedervorlage = wiedervorlage; + + component.patchWiedervorlage(); + + expect(formService.patch).toHaveBeenCalledWith(wiedervorlage); + }); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.ts index f5cac8c30c1a88914993f8d74780f84471b752cf..a11f4b598a1470518354e778c7c658c2266c9d80 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage-form.component.ts @@ -24,7 +24,13 @@ import { Component, Input, OnChanges, SimpleChanges } from '@angular/core'; import { BinaryFileListLinkRel, BinaryFileResource } from '@alfa-client/binary-file-shared'; import { StateResource, getEmbeddedResources, isNotNil } from '@alfa-client/tech-shared'; -import { WiedervorlageLinkRel, WiedervorlageListLinkRel, WiedervorlageListResource, WiedervorlageResource, WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; +import { + WiedervorlageLinkRel, + WiedervorlageListLinkRel, + WiedervorlageListResource, + WiedervorlageResource, + WiedervorlageService, +} from '@alfa-client/wiedervorlage-shared'; import { hasLink } from '@ngxp/rest'; import { isNull } from 'lodash-es'; import { Observable, of } from 'rxjs'; @@ -33,44 +39,50 @@ import { WiedervorlageFormService } from './wiedervorlage.formservice'; //TODO Container Component zwischenschalten @Component({ - selector: 'alfa-wiedervorlage-form', - templateUrl: './wiedervorlage-form.component.html', - styleUrls: ['./wiedervorlage-form.component.scss'] + selector: 'alfa-wiedervorlage-form', + templateUrl: './wiedervorlage-form.component.html', + styleUrls: ['./wiedervorlage-form.component.scss'], }) export class WiedervorlageFormComponent implements OnChanges { + @Input() wiedervorlageListStateResource: StateResource<WiedervorlageListResource>; + @Input() wiedervorlage: WiedervorlageResource; - @Input() wiedervorlageListStateResource: StateResource<WiedervorlageListResource>; - @Input() wiedervorlage: WiedervorlageResource; + attachments$: Observable<BinaryFileResource[]> = of([]); - attachments$: Observable<BinaryFileResource[]> = of([]); + readonly formServiceClass = WiedervorlageFormService; + readonly wiedervorlageListLinkrel = WiedervorlageListLinkRel; - readonly formServiceClass = WiedervorlageFormService; - readonly wiedervorlageListLinkrel = WiedervorlageListLinkRel; + constructor( + public formService: WiedervorlageFormService, + private wiedervorlageService: WiedervorlageService, + ) {} - constructor(public formService: WiedervorlageFormService, private wiedervorlageService: WiedervorlageService) { } + ngOnChanges(changes: SimpleChanges): void { + if (changes.wiedervorlage && isNotNil(this.wiedervorlage)) { + this.updateAttachments(); + this.patchWiedervorlage(); + } + } - ngOnChanges(changes: SimpleChanges): void { - if (changes.wiedervorlage && isNotNil(this.wiedervorlage)) { - this.updateAttachments(); - this.patchWiedervorlage(); - } - } - - updateAttachments(): void { - if (hasLink(this.wiedervorlage, WiedervorlageLinkRel.ATTACHMENTS)) { - this.attachments$ = this.wiedervorlageService.getAttachmentList(this.wiedervorlage) - .pipe(map(attachmentList => getEmbeddedResources<BinaryFileResource>( - attachmentList, - BinaryFileListLinkRel.FILE_LIST) - )); - } else { - this.attachments$ = of([]); - } - - } - patchWiedervorlage(): void { - if (!isNull(this.wiedervorlage)) { - this.formService.patch(this.wiedervorlage); - } - } -} \ No newline at end of file + updateAttachments(): void { + if (hasLink(this.wiedervorlage, WiedervorlageLinkRel.ATTACHMENTS)) { + this.attachments$ = this.wiedervorlageService + .getAttachmentList(this.wiedervorlage) + .pipe( + map((attachmentList) => + getEmbeddedResources<BinaryFileResource>( + attachmentList, + BinaryFileListLinkRel.FILE_LIST, + ), + ), + ); + } else { + this.attachments$ = of([]); + } + } + patchWiedervorlage(): void { + if (!isNull(this.wiedervorlage)) { + this.formService.patch(this.wiedervorlage); + } + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.spec.ts index e2f5b417e835e9cd1512eb6314b4c327c6222941..c556c3afbcc160088ce0c003c2fa33df3b177887 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.spec.ts @@ -35,50 +35,51 @@ import { WiedervorlageFormService } from './wiedervorlage.formservice'; registerLocaleData(localeDe, 'de', localeDeExtra); describe('WiedervorlageFormService', () => { - let formService: WiedervorlageFormService; - let wiedervorlageService: Mock<WiedervorlageService>; + let formService: WiedervorlageFormService; + let wiedervorlageService: Mock<WiedervorlageService>; - const formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); - const wiedervorlageResource: WiedervorlageResource = createWiedervorlageResource(); + const formBuilder: UntypedFormBuilder = new UntypedFormBuilder(); + const wiedervorlageResource: WiedervorlageResource = createWiedervorlageResource(); - beforeEach(() => { - wiedervorlageService = mock(WiedervorlageService); + beforeEach(() => { + wiedervorlageService = mock(WiedervorlageService); - formService = new WiedervorlageFormService(formBuilder, useFromMock(wiedervorlageService)); - }) + formService = new WiedervorlageFormService(formBuilder, useFromMock(wiedervorlageService)); + }); - it('should create', () => { - expect(formService).toBeTruthy(); - }); + it('should create', () => { + expect(formService).toBeTruthy(); + }); - it('should have default date in 14 days', () => { - const date = new Date(); - date.setDate(date.getDate() + 14); + it('should have default date in 14 days', () => { + const date = new Date(); + date.setDate(date.getDate() + 14); - expect(formService.form.controls[WiedervorlageFormService.FIELD_FRIST].value.getDate()).toBe(date.getDate()); - }) + expect(formService.form.controls[WiedervorlageFormService.FIELD_FRIST].value.getDate()).toBe( + date.getDate(), + ); + }); - describe('submit', () => { + describe('submit', () => { + beforeEach(() => { + wiedervorlageService.createWiedervorlage.mockReturnValue(of(createEmptyStateResource())); + wiedervorlageService.saveWiedervorlage.mockReturnValue(of(createEmptyStateResource())); + }); - beforeEach(() => { - wiedervorlageService.createWiedervorlage.mockReturnValue(of(createEmptyStateResource())); - wiedervorlageService.saveWiedervorlage.mockReturnValue(of(createEmptyStateResource())); - }) + it('should call createWiedervorlage', () => { + formService.source = null; - it('should call createWiedervorlage', () => { - formService.source = null; + formService.submit(); - formService.submit(); + expect(wiedervorlageService.createWiedervorlage).toHaveBeenCalled(); + }); - expect(wiedervorlageService.createWiedervorlage).toHaveBeenCalled(); - }) + it('should call saveWiedervorlage', () => { + formService.source = wiedervorlageResource; - it('should call saveWiedervorlage', () => { - formService.source = wiedervorlageResource; + formService.submit(); - formService.submit(); - - expect(wiedervorlageService.saveWiedervorlage).toHaveBeenCalled(); - }) - }) -}) + expect(wiedervorlageService.saveWiedervorlage).toHaveBeenCalled(); + }); + }); +}); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts index 11f2f950d635859aa6cd4983c1098c76f9307d33..e408b02599759b92ad1a6e42c505b3e0110133ae 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-form/wiedervorlage.formservice.ts @@ -22,51 +22,60 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Injectable } from '@angular/core'; -import { UntypedFormArray, UntypedFormBuilder, UntypedFormControl, UntypedFormGroup } from '@angular/forms'; -import { AbstractFormService, createFutureDate, formatForDatabase, StateResource } from '@alfa-client/tech-shared'; +import { + UntypedFormArray, + UntypedFormBuilder, + UntypedFormControl, + UntypedFormGroup, +} from '@angular/forms'; +import { + AbstractFormService, + createFutureDate, + formatForDatabase, + StateResource, +} from '@alfa-client/tech-shared'; import { Wiedervorlage, WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; import { Observable } from 'rxjs'; @Injectable() export class WiedervorlageFormService extends AbstractFormService { + static readonly FIELD_BETREFF = 'betreff'; + static readonly FIELD_BESCHREIBUNG = 'beschreibung'; + static readonly FIELD_FRIST = 'frist'; + static readonly FIELD_ATTACHMENTS = 'attachments'; - static readonly FIELD_BETREFF = 'betreff'; - static readonly FIELD_BESCHREIBUNG = 'beschreibung'; - static readonly FIELD_FRIST = 'frist'; - static readonly FIELD_ATTACHMENTS = 'attachments'; + static readonly FIELD_PATH_PREFIX = 'wiedervorlage'; - static readonly FIELD_PATH_PREFIX = 'wiedervorlage'; + constructor( + formBuilder: UntypedFormBuilder, + private wiedervorlageService: WiedervorlageService, + ) { + super(formBuilder); + } - constructor( - formBuilder: UntypedFormBuilder, - private wiedervorlageService: WiedervorlageService - ) { - super(formBuilder); - } + protected initForm(): UntypedFormGroup { + return this.formBuilder.group({ + [WiedervorlageFormService.FIELD_BETREFF]: new UntypedFormControl(null), + [WiedervorlageFormService.FIELD_FRIST]: new UntypedFormControl(createFutureDate(14)), + [WiedervorlageFormService.FIELD_BESCHREIBUNG]: new UntypedFormControl(), + [WiedervorlageFormService.FIELD_ATTACHMENTS]: new UntypedFormArray([]), + }); + } - protected initForm(): UntypedFormGroup { - return this.formBuilder.group({ - [WiedervorlageFormService.FIELD_BETREFF]: new UntypedFormControl(null), - [WiedervorlageFormService.FIELD_FRIST]: new UntypedFormControl(createFutureDate(14)), - [WiedervorlageFormService.FIELD_BESCHREIBUNG]: new UntypedFormControl(), - [WiedervorlageFormService.FIELD_ATTACHMENTS]: new UntypedFormArray([]), - }) - } + protected getPathPrefix(): string { + return WiedervorlageFormService.FIELD_PATH_PREFIX; + } - protected getPathPrefix(): string { - return WiedervorlageFormService.FIELD_PATH_PREFIX; - } + protected doSubmit(): Observable<StateResource<any>> { + if (this.isPatch()) { + return this.wiedervorlageService.saveWiedervorlage(this.getSourceValue(), this.getValue()); + } else { + return this.wiedervorlageService.createWiedervorlage(this.getValue()); + } + } - protected doSubmit(): Observable<StateResource<any>> { - if (this.isPatch()) { - return this.wiedervorlageService.saveWiedervorlage(this.getSourceValue(), this.getValue()); - } else { - return this.wiedervorlageService.createWiedervorlage(this.getValue()); - } - } - - getValue(): Wiedervorlage { - const formValue = super.getFormValue(); - return { ...formValue, frist: formatForDatabase(formValue.frist) }; - } -} \ No newline at end of file + getValue(): Wiedervorlage { + const formValue = super.getFormValue(); + return { ...formValue, frist: formatForDatabase(formValue.frist) }; + } +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.html index 70907cca0114a9ee391d6e9a7fb1a0c973ca67d6..446fa38d1702e33b0714444d9c4c63c0082a297e 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.html @@ -24,25 +24,34 @@ --> <ozgcloud-spinner [stateResource]="wiedervorlageStateResource"> - - <ozgcloud-subnavigation data-test-id="subnavigation-wiedervorlage" class="mat-app-background"> - <alfa-wiedervorlage-action-buttons [wiedervorlage]="wiedervorlageStateResource.resource"> - </alfa-wiedervorlage-action-buttons> - </ozgcloud-subnavigation> - - <div class="l-scroll-area--full"> - <div class="wrapper"> - <alfa-wiedervorlage-breadcrumb-container [wiedervorlage]=" wiedervorlageStateResource.resource"></alfa-wiedervorlage-breadcrumb-container> - - <alfa-wiedervorlage-status class="status" [wiedervorlageResource]="wiedervorlageStateResource.resource" [diameter]="16"> - <span>{{wiedervorlageStateResource.resource && wiedervorlageStateResource.resource.done ? "erledigt" : "offen"}}</span> - </alfa-wiedervorlage-status> - - <alfa-wiedervorlage-form - [wiedervorlage]="wiedervorlageStateResource.resource" - [wiedervorlageListStateResource]="wiedervorlageListStateResource"> - </alfa-wiedervorlage-form> - </div> - </div> - -</ozgcloud-spinner> \ No newline at end of file + <ozgcloud-subnavigation data-test-id="subnavigation-wiedervorlage" class="mat-app-background"> + <alfa-wiedervorlage-action-buttons [wiedervorlage]="wiedervorlageStateResource.resource"> + </alfa-wiedervorlage-action-buttons> + </ozgcloud-subnavigation> + + <div class="l-scroll-area--full"> + <div class="wrapper"> + <alfa-wiedervorlage-breadcrumb-container + [wiedervorlage]="wiedervorlageStateResource.resource" + ></alfa-wiedervorlage-breadcrumb-container> + + <alfa-wiedervorlage-status + class="status" + [wiedervorlageResource]="wiedervorlageStateResource.resource" + [diameter]="16" + > + <span>{{ + wiedervorlageStateResource.resource && wiedervorlageStateResource.resource.done ? + 'erledigt' + : 'offen' + }}</span> + </alfa-wiedervorlage-status> + + <alfa-wiedervorlage-form + [wiedervorlage]="wiedervorlageStateResource.resource" + [wiedervorlageListStateResource]="wiedervorlageListStateResource" + > + </alfa-wiedervorlage-form> + </div> + </div> +</ozgcloud-spinner> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.scss index 24f803c8ceb3b5e40d64d0d4f02bd4543c763970..7b23bf20f0313571fc53837d688a1c0561680527 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.scss @@ -22,9 +22,9 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ .wrapper { - padding: 24px 28px; + padding: 24px 28px; } .status { - margin: 8px 0; + margin: 8px 0; } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.spec.ts index 57f2ec7c9b83ca929f33c65b1cc9ada9013132f5..7a949c2008e54b4d2b2041db9877e4d1531e2977 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.spec.ts @@ -33,31 +33,31 @@ import { WiedervorlageFormComponent } from './wiedervorlage-form/wiedervorlage-f import { WiedervorlagePageComponent } from './wiedervorlage-page.component'; describe('WiedervorlagePageComponent', () => { - let component: WiedervorlagePageComponent; - let fixture: ComponentFixture<WiedervorlagePageComponent>; + let component: WiedervorlagePageComponent; + let fixture: ComponentFixture<WiedervorlagePageComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlagePageComponent, - MockComponent(SubnavigationComponent), - MockComponent(WiedervorlageActionButtonsComponent), - MockComponent(WiedervorlageFormComponent), - MockComponent(SpinnerComponent), - MockComponent(WiedervorlageBreadcrumbContainerComponent), - MockComponent(WiedervorlageStatusComponent) - ] - }).compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlagePageComponent, + MockComponent(SubnavigationComponent), + MockComponent(WiedervorlageActionButtonsComponent), + MockComponent(WiedervorlageFormComponent), + MockComponent(SpinnerComponent), + MockComponent(WiedervorlageBreadcrumbContainerComponent), + MockComponent(WiedervorlageStatusComponent), + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlagePageComponent); - component = fixture.componentInstance; - component.wiedervorlageStateResource = createStateResource(createWiedervorlageResource()); - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlagePageComponent); + component = fixture.componentInstance; + component.wiedervorlageStateResource = createStateResource(createWiedervorlageResource()); + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); -}) \ No newline at end of file + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.ts index 182b17c907b9e1b340fdbedf94cb9049c2854d48..967d4228019e9bc1cd4279c0a42ce709076871d7 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-page-container/wiedervorlage-page/wiedervorlage-page.component.ts @@ -23,15 +23,17 @@ */ import { Component, Input } from '@angular/core'; import { StateResource } from '@alfa-client/tech-shared'; -import { WiedervorlageListResource, WiedervorlageResource } from '@alfa-client/wiedervorlage-shared'; +import { + WiedervorlageListResource, + WiedervorlageResource, +} from '@alfa-client/wiedervorlage-shared'; @Component({ - selector: 'alfa-wiedervorlage-page', - templateUrl: './wiedervorlage-page.component.html', - styleUrls: ['./wiedervorlage-page.component.scss'] + selector: 'alfa-wiedervorlage-page', + templateUrl: './wiedervorlage-page.component.html', + styleUrls: ['./wiedervorlage-page.component.scss'], }) export class WiedervorlagePageComponent { - - @Input() wiedervorlageListStateResource: StateResource<WiedervorlageListResource>; - @Input() wiedervorlageStateResource: StateResource<WiedervorlageResource>; + @Input() wiedervorlageListStateResource: StateResource<WiedervorlageListResource>; + @Input() wiedervorlageStateResource: StateResource<WiedervorlageResource>; } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.html b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.html index bc963354d7669650de15f6fe4479eab5aba372eb..d402a8522f669b6d4c6b7590c69845462a8edb43 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.html +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.html @@ -24,15 +24,24 @@ --> <ng-container *ngIf="wiedervorlageResource; else newWiedervorlageStatus"> - <div class="dot" - [style.width]="diameter + 'px'" [style.height]="diameter + 'px'" - [ngClass]="[wiedervorlageResource.frist | toTrafficLight, wiedervorlageResource.done ? 'erledigt' : '']" data-test-class="dot"> - <mat-icon class="done" *ngIf="wiedervorlageResource.done" data-test-class="done-icon">done</mat-icon> - </div> + <div + class="dot" + [style.width]="diameter + 'px'" + [style.height]="diameter + 'px'" + [ngClass]="[ + wiedervorlageResource.frist | toTrafficLight, + wiedervorlageResource.done ? 'erledigt' : '' + ]" + data-test-class="dot" + > + <mat-icon class="done" *ngIf="wiedervorlageResource.done" data-test-class="done-icon" + >done</mat-icon + > + </div> </ng-container> <ng-template #newWiedervorlageStatus> - <div class="dot" [style.width]="diameter + 'px'" [style.height]="diameter + 'px'"></div> + <div class="dot" [style.width]="diameter + 'px'" [style.height]="diameter + 'px'"></div> </ng-template> <span class="content"><ng-content></ng-content></span> diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.scss b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.scss index 52008d1959b6cb02151b9311346a5c1c6623557c..e6c6c5d1e66c8987237fc8d6e491383030103a7a 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.scss +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.scss @@ -26,42 +26,42 @@ @import 'variables'; :host { - display: flex; - align-items: center; + display: flex; + align-items: center; } .dot { - border-radius: 50%; - border: 1px solid darken(#E4E4E4, 30%); - background-color: #E4E4E4; - flex-shrink: 0; - margin-right: 4px; - display: flex; - position: relative; + border-radius: 50%; + border: 1px solid darken(#e4e4e4, 30%); + background-color: #e4e4e4; + flex-shrink: 0; + margin-right: 4px; + display: flex; + position: relative; - .mat-icon { - position: absolute; - left: -2px; - top: 50%; - transform: translateY(-50%); - font-size: 20px; - } + .mat-icon { + position: absolute; + left: -2px; + top: 50%; + transform: translateY(-50%); + font-size: 20px; + } - &.red:not(.erledigt) { - background-color: mat.get-color-from-palette($warnPalette); - border-color: mat.get-color-from-palette($warnPalette, darker); - } + &.red:not(.erledigt) { + background-color: mat.get-color-from-palette($warnPalette); + border-color: mat.get-color-from-palette($warnPalette, darker); + } - &.yellow:not(.erledigt) { - background-color: mat.get-color-from-palette($accentPalette); - border-color: mat.get-color-from-palette($accentPalette, darker); - } + &.yellow:not(.erledigt) { + background-color: mat.get-color-from-palette($accentPalette); + border-color: mat.get-color-from-palette($accentPalette, darker); + } } .content { - margin-left: 4px; + margin-left: 4px; } .done { - color: green; + color: green; } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.spec.ts index 7373f89988ae5d22bf79f1859c83131482b1de7d..e256cd43b662deb73056374fee28c375a879a7c6 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.spec.ts @@ -32,54 +32,53 @@ import { WiedervorlageStatusComponent } from './wiedervorlage-status.component'; const doneIcon: string = '[data-test-class="done-icon"]'; describe('WiedervorlageStatusComponent', () => { - let component: WiedervorlageStatusComponent; - let fixture: ComponentFixture<WiedervorlageStatusComponent>; + let component: WiedervorlageStatusComponent; + let fixture: ComponentFixture<WiedervorlageStatusComponent>; - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - WiedervorlageStatusComponent, - ToTrafficLightPipe, - MockDirective(MatTooltipDirective), - MatIcon - ] - }) - .compileComponents(); - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ + WiedervorlageStatusComponent, + ToTrafficLightPipe, + MockDirective(MatTooltipDirective), + MatIcon, + ], + }).compileComponents(); + }); - beforeEach(() => { - fixture = TestBed.createComponent(WiedervorlageStatusComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); + beforeEach(() => { + fixture = TestBed.createComponent(WiedervorlageStatusComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); - it('should create', () => { - expect(component).toBeTruthy(); - }); + it('should create', () => { + expect(component).toBeTruthy(); + }); - describe('status dot', () => { - it('should have no icon initially', () => { - const doneIconElement = fixture.nativeElement.querySelector(doneIcon); + describe('status dot', () => { + it('should have no icon initially', () => { + const doneIconElement = fixture.nativeElement.querySelector(doneIcon); - expect(doneIconElement).not.toBeInstanceOf(HTMLElement); - }) + expect(doneIconElement).not.toBeInstanceOf(HTMLElement); + }); - it('should have no icon if wiedervorlage is not done', () => { - component.wiedervorlageResource = { ...createWiedervorlageResource(), done: false }; - fixture.detectChanges(); + it('should have no icon if wiedervorlage is not done', () => { + component.wiedervorlageResource = { ...createWiedervorlageResource(), done: false }; + fixture.detectChanges(); - const doneIconElement = fixture.nativeElement.querySelector(doneIcon); + const doneIconElement = fixture.nativeElement.querySelector(doneIcon); - expect(doneIconElement).not.toBeInstanceOf(HTMLElement); - }) + expect(doneIconElement).not.toBeInstanceOf(HTMLElement); + }); - it('should have icon if wiedervorlage is done', () => { - component.wiedervorlageResource = { ...createWiedervorlageResource(), done: true }; - fixture.detectChanges(); + it('should have icon if wiedervorlage is done', () => { + component.wiedervorlageResource = { ...createWiedervorlageResource(), done: true }; + fixture.detectChanges(); - const doneIconElement = fixture.nativeElement.querySelector(doneIcon); + const doneIconElement = fixture.nativeElement.querySelector(doneIcon); - expect(doneIconElement).toBeInstanceOf(HTMLElement); - }) - }) + expect(doneIconElement).toBeInstanceOf(HTMLElement); + }); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.ts index 0fd1bd673b949cf2011be13ffb86a9d4811c3aab..2b1f617ed551bace97865eac7122652e6bd8e369 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage-status/wiedervorlage-status.component.ts @@ -27,9 +27,9 @@ import { WiedervorlageResource } from '@alfa-client/wiedervorlage-shared'; @Component({ selector: 'alfa-wiedervorlage-status', templateUrl: './wiedervorlage-status.component.html', - styleUrls: ['./wiedervorlage-status.component.scss'] + styleUrls: ['./wiedervorlage-status.component.scss'], }) export class WiedervorlageStatusComponent { - @Input() wiedervorlageResource: WiedervorlageResource; - @Input() diameter: number = 12; + @Input() wiedervorlageResource: WiedervorlageResource; + @Input() diameter: number = 12; } diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.guard.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.guard.spec.ts index 602dda36a2b08998c60d2457cd72361182c6b133..64089451c87ad1d5887116252251f89fab2173ea 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.guard.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.guard.spec.ts @@ -23,7 +23,12 @@ */ import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; -import { ActivatedRouteSnapshot, CanActivateFn, RouterStateSnapshot, UrlSegment } from '@angular/router'; +import { + ActivatedRouteSnapshot, + CanActivateFn, + RouterStateSnapshot, + UrlSegment, +} from '@angular/router'; import faker from '@faker-js/faker'; import { encodeUrlForEmbedding } from '@alfa-client/tech-shared'; import { mock } from '@alfa-client/test-utils'; @@ -34,150 +39,159 @@ import { EMPTY, Observable, of } from 'rxjs'; import * as RouterHelper from '@angular/router'; import * as Guard from './wiedervorlage.guard'; -const next: ActivatedRouteSnapshot = { params: { wiedervorlageUrl: '', vorgangWithEingangUrl: '' } } as unknown as ActivatedRouteSnapshot; -const state: RouterStateSnapshot = { root: { url: [<UrlSegment>{}] } } as unknown as RouterStateSnapshot; +const next: ActivatedRouteSnapshot = { + params: { wiedervorlageUrl: '', vorgangWithEingangUrl: '' }, +} as unknown as ActivatedRouteSnapshot; +const state: RouterStateSnapshot = { + root: { url: [<UrlSegment>{}] }, +} as unknown as RouterStateSnapshot; describe('wiedervorlageGuard', () => { - const wiedervorlageService = mock(WiedervorlageService); - const snackbarService = mock(SnackBarService); - const createUrlTreeForVorgang = jest.spyOn(Guard, 'createUrlTreeForVorgang').mockReturnValue(<RouterHelper.UrlTree>{}); - - beforeEach(() => { - TestBed.configureTestingModule({ - providers: [ - { - provide: WiedervorlageService, - useValue: wiedervorlageService - }, - { - provide: SnackBarService, - useValue: snackbarService - } - ] - }); - - jest.spyOn(wiedervorlageService, 'hasEditLink').mockReturnValue(EMPTY); - }); - - - it('should be created', () => { - const guard = TestBed.runInInjectionContext(() => Guard.wiedervorlageGuard(next, state)) as unknown as CanActivateFn; - - expect(guard).toBeTruthy(); - }); - - describe('wiedervorlageGuard', () => { - - it('should call wiedervorlageService.hasEditLink', () => { - const spy = jest.spyOn(wiedervorlageService, 'hasEditLink'); - next.params['wiedervorlageUrl'] = encodeUrlForEmbedding(faker.internet.url()); - - TestBed.runInInjectionContext(() => Guard.wiedervorlageGuard(next, state)) as unknown as CanActivateFn; - - expect(spy).toHaveBeenCalled(); - }) - - it('should return UrlTree object', (done) => { - jest.spyOn(wiedervorlageService, 'hasEditLink').mockReturnValue(of(false)); - - TestBed.runInInjectionContext(() => ( - Guard.wiedervorlageGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe( - result => { - expect(result).toBeInstanceOf(Object); - done(); - } - ) - ) as unknown as CanActivateFn; - }) - - it('should return true', (done) => { - jest.spyOn(wiedervorlageService, 'hasEditLink').mockReturnValue(of(true)); - - TestBed.runInInjectionContext(() => ( - Guard.wiedervorlageGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe( - result => { - expect(result).toBeTruthy(); - done(); - } - ) - ) as unknown as CanActivateFn; - }) - - it.skip('should call handleError if error occurs', (done) => { - jest.spyOn(wiedervorlageService, 'hasEditLink').mockReturnValue(of(new Error())); - const spy = jest.spyOn(Guard, 'handleError'); - - TestBed.runInInjectionContext(() => ( - Guard.wiedervorlageGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe( - () => { - expect(spy).toHaveBeenCalled(); - done(); - } - ) - ) as unknown as CanActivateFn; - }) - }) - - describe('handleLinkCheck', () => { - it('should return true if hasLink is true', () => { - const hasLink = true; - - const result = Guard.handleLinkCheck(hasLink, null, null); - - expect(result).toBeTruthy(); - }) - - it('should call showSnackbar if hasLink is false', () => { - const hasLink = false; - const spy = jest.spyOn(Guard, 'showSnackbar'); - - Guard.handleLinkCheck(hasLink, next, snackbarService as unknown as SnackBarService); - - expect(spy).toHaveBeenCalled(); - }) - - it('should call createUrlTreeForVorgang if hasLink is false', () => { - const hasLink = false; - jest.spyOn(Guard, 'showSnackbar'); - - Guard.handleLinkCheck(hasLink, next, snackbarService as unknown as SnackBarService); - - expect(createUrlTreeForVorgang).toHaveBeenCalled(); - }) - }) - - describe('showSnackbar', () => { - const showError = jest.spyOn(snackbarService, 'showError'); - - it('should call snackbarService.showError', () => { - Guard.showSnackbar(snackbarService as unknown as SnackBarService); - - expect(showError).toHaveBeenCalledWith('Im Status "Zu löschen" ist die Bearbeitung von Wiedervorlagen nicht möglich.'); - }) - }) - - describe('handleError', () => { - it('should return Observable<UrlTree> if HTTP Status 403', () => { - const error = createHttpError(HttpStatusCode.Forbidden); - - const res: RouterHelper.UrlTree = Guard.handleError(error, next); - - expect(res).toBeInstanceOf(Object); - - }) - - it('should return nothing if HTTP Status is not 403', () => { - const error = createHttpError(HttpStatusCode.Unauthorized); - - function monitorErrorThrowing() { - Guard.handleError(error, next); - } - - expect(monitorErrorThrowing).toThrow(); - }) - }) - - function createHttpError(status: HttpStatusCode): any { - return { error: new HttpErrorResponse({ status }) }; - } + const wiedervorlageService = mock(WiedervorlageService); + const snackbarService = mock(SnackBarService); + const createUrlTreeForVorgang = jest + .spyOn(Guard, 'createUrlTreeForVorgang') + .mockReturnValue(<RouterHelper.UrlTree>{}); + + beforeEach(() => { + TestBed.configureTestingModule({ + providers: [ + { + provide: WiedervorlageService, + useValue: wiedervorlageService, + }, + { + provide: SnackBarService, + useValue: snackbarService, + }, + ], + }); + + jest.spyOn(wiedervorlageService, 'hasEditLink').mockReturnValue(EMPTY); + }); + + it('should be created', () => { + const guard = TestBed.runInInjectionContext(() => + Guard.wiedervorlageGuard(next, state), + ) as unknown as CanActivateFn; + + expect(guard).toBeTruthy(); + }); + + describe('wiedervorlageGuard', () => { + it('should call wiedervorlageService.hasEditLink', () => { + const spy = jest.spyOn(wiedervorlageService, 'hasEditLink'); + next.params['wiedervorlageUrl'] = encodeUrlForEmbedding(faker.internet.url()); + + TestBed.runInInjectionContext(() => + Guard.wiedervorlageGuard(next, state), + ) as unknown as CanActivateFn; + + expect(spy).toHaveBeenCalled(); + }); + + it('should return UrlTree object', (done) => { + jest.spyOn(wiedervorlageService, 'hasEditLink').mockReturnValue(of(false)); + + TestBed.runInInjectionContext(() => + (Guard.wiedervorlageGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe( + (result) => { + expect(result).toBeInstanceOf(Object); + done(); + }, + ), + ) as unknown as CanActivateFn; + }); + + it('should return true', (done) => { + jest.spyOn(wiedervorlageService, 'hasEditLink').mockReturnValue(of(true)); + + TestBed.runInInjectionContext(() => + (Guard.wiedervorlageGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe( + (result) => { + expect(result).toBeTruthy(); + done(); + }, + ), + ) as unknown as CanActivateFn; + }); + + it.skip('should call handleError if error occurs', (done) => { + jest.spyOn(wiedervorlageService, 'hasEditLink').mockReturnValue(of(new Error())); + const spy = jest.spyOn(Guard, 'handleError'); + + TestBed.runInInjectionContext(() => + (Guard.wiedervorlageGuard(next, state) as Observable<RouterHelper.UrlTree>).subscribe( + () => { + expect(spy).toHaveBeenCalled(); + done(); + }, + ), + ) as unknown as CanActivateFn; + }); + }); + + describe('handleLinkCheck', () => { + it('should return true if hasLink is true', () => { + const hasLink = true; + + const result = Guard.handleLinkCheck(hasLink, null, null); + + expect(result).toBeTruthy(); + }); + + it('should call showSnackbar if hasLink is false', () => { + const hasLink = false; + const spy = jest.spyOn(Guard, 'showSnackbar'); + + Guard.handleLinkCheck(hasLink, next, snackbarService as unknown as SnackBarService); + + expect(spy).toHaveBeenCalled(); + }); + + it('should call createUrlTreeForVorgang if hasLink is false', () => { + const hasLink = false; + jest.spyOn(Guard, 'showSnackbar'); + + Guard.handleLinkCheck(hasLink, next, snackbarService as unknown as SnackBarService); + + expect(createUrlTreeForVorgang).toHaveBeenCalled(); + }); + }); + + describe('showSnackbar', () => { + const showError = jest.spyOn(snackbarService, 'showError'); + + it('should call snackbarService.showError', () => { + Guard.showSnackbar(snackbarService as unknown as SnackBarService); + + expect(showError).toHaveBeenCalledWith( + 'Im Status "Zu löschen" ist die Bearbeitung von Wiedervorlagen nicht möglich.', + ); + }); + }); + + describe('handleError', () => { + it('should return Observable<UrlTree> if HTTP Status 403', () => { + const error = createHttpError(HttpStatusCode.Forbidden); + + const res: RouterHelper.UrlTree = Guard.handleError(error, next); + + expect(res).toBeInstanceOf(Object); + }); + + it('should return nothing if HTTP Status is not 403', () => { + const error = createHttpError(HttpStatusCode.Unauthorized); + + function monitorErrorThrowing() { + Guard.handleError(error, next); + } + + expect(monitorErrorThrowing).toThrow(); + }); + }); + + function createHttpError(status: HttpStatusCode): any { + return { error: new HttpErrorResponse({ status }) }; + } }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.guard.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.guard.ts index 59aa1eb1fcc2bef21e6717bf984b576a8b2346b2..c31a717186974b259f2ccc84930aa12a47d4c8f0 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.guard.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.guard.ts @@ -22,7 +22,13 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { inject } from '@angular/core'; -import { ActivatedRouteSnapshot, CanActivateFn, RouterStateSnapshot, UrlTree, createUrlTreeFromSnapshot } from '@angular/router'; +import { + ActivatedRouteSnapshot, + CanActivateFn, + RouterStateSnapshot, + UrlTree, + createUrlTreeFromSnapshot, +} from '@angular/router'; import { isForbidden } from '@alfa-client/tech-shared'; import { SnackBarService } from '@alfa-client/ui'; import { WiedervorlageService } from '@alfa-client/wiedervorlage-shared'; @@ -30,43 +36,52 @@ import { Observable, catchError, map, of } from 'rxjs'; import * as Guard from './wiedervorlage.guard'; -export const wiedervorlageGuard: CanActivateFn = (next: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean | UrlTree> | UrlTree => { - const wiedervorlageService = inject(WiedervorlageService) - const snackbarService = inject(SnackBarService); +export const wiedervorlageGuard: CanActivateFn = ( + next: ActivatedRouteSnapshot, + state: RouterStateSnapshot, +): boolean | Observable<boolean | UrlTree> | UrlTree => { + const wiedervorlageService = inject(WiedervorlageService); + const snackbarService = inject(SnackBarService); - const wiedervorlageUrl = next.params['wiedervorlageUrl']; - if (wiedervorlageUrl === 'neu') { - return true; - } + const wiedervorlageUrl = next.params['wiedervorlageUrl']; + if (wiedervorlageUrl === 'neu') { + return true; + } - return wiedervorlageService.hasEditLink(wiedervorlageUrl).pipe( - map(hasLink => Guard.handleLinkCheck(hasLink, next, snackbarService)), - catchError((err) => of(Guard.handleError(err, next))) - ); + return wiedervorlageService.hasEditLink(wiedervorlageUrl).pipe( + map((hasLink) => Guard.handleLinkCheck(hasLink, next, snackbarService)), + catchError((err) => of(Guard.handleError(err, next))), + ); }; -export function handleLinkCheck(hasLink: boolean, next: ActivatedRouteSnapshot, snackbarService: SnackBarService): boolean | UrlTree { - if (hasLink) { - return true; - } +export function handleLinkCheck( + hasLink: boolean, + next: ActivatedRouteSnapshot, + snackbarService: SnackBarService, +): boolean | UrlTree { + if (hasLink) { + return true; + } - Guard.showSnackbar(snackbarService); + Guard.showSnackbar(snackbarService); - return Guard.createUrlTreeForVorgang(next); + return Guard.createUrlTreeForVorgang(next); } export function showSnackbar(snackbarService: SnackBarService): void { - snackbarService.showError('Im Status "Zu löschen" ist die Bearbeitung von Wiedervorlagen nicht möglich.'); + snackbarService.showError( + 'Im Status "Zu löschen" ist die Bearbeitung von Wiedervorlagen nicht möglich.', + ); } export function handleError(err: any, next: ActivatedRouteSnapshot): UrlTree { - if (isForbidden(err.error.status)) { - return Guard.createUrlTreeForVorgang(next); - } + if (isForbidden(err.error.status)) { + return Guard.createUrlTreeForVorgang(next); + } - throw err; + throw err; } export function createUrlTreeForVorgang(next: ActivatedRouteSnapshot): UrlTree { - return createUrlTreeFromSnapshot(next, ['/vorgang', next.params['vorgangWithEingangUrl']]); -} \ No newline at end of file + return createUrlTreeFromSnapshot(next, ['/vorgang', next.params['vorgangWithEingangUrl']]); +} diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.spec.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.spec.ts index bb7ccec56106f55e45d20f9f6f897c0d63c87d09..615a2b9538f01162f210929f741b0c972150a991 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.spec.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.spec.ts @@ -25,13 +25,13 @@ import { TestBed } from '@angular/core/testing'; import { WiedervorlageModule } from './wiedervorlage.module'; describe('WiedervorlageModule', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [WiedervorlageModule], - }) - }); + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [WiedervorlageModule], + }); + }); - it('should create', () => { - expect(WiedervorlageModule).toBeDefined(); - }); + it('should create', () => { + expect(WiedervorlageModule).toBeDefined(); + }); }); diff --git a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts index 9ef4c46b99cafbc3f48d7a625bc0cfc016232f9c..6e00e592bad7252dd3f375d439adbef4f17cd2d7 100644 --- a/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts +++ b/alfa-client/libs/wiedervorlage/src/lib/wiedervorlage.module.ts @@ -51,50 +51,50 @@ import { WiedervorlageStatusComponent } from './wiedervorlage-status/wiedervorla import { wiedervorlageGuard } from './wiedervorlage.guard'; const routes: Routes = [ - { - path: 'wiedervorlage/:wiedervorlageUrl', - component: WiedervorlagePageContainerComponent, - title: 'Wiedervorlage zum Vorgang | Alfa', - canActivate: [wiedervorlageGuard], - }, + { + path: 'wiedervorlage/:wiedervorlageUrl', + component: WiedervorlagePageContainerComponent, + title: 'Wiedervorlage zum Vorgang | Alfa', + canActivate: [wiedervorlageGuard], + }, ]; @NgModule({ - imports: [ - CommonModule, - RouterModule.forChild(routes), - UiModule, - VorgangSharedModule, - TechSharedModule, - VorgangSharedUiModule, - BinaryFileModule, - UserProfileModule - ], - declarations: [ - WiedervorlagePageComponent, - WiedervorlageInVorgangComponent, - WiedervorlageFormComponent, - WiedervorlageBreadcrumbComponent, - WiedervorlageListInVorgangContainerComponent, - WiedervorlageListInVorgangComponent, - WiedervorlageActionButtonsComponent, - WiedervorlagePageContainerComponent, - WiedervorlageStatusComponent, - WiedervorlageCreateButtonComponent, - WiedervorlageListInVorgangListContainerComponent, - SubmitWiedervorlageButtonComponent, - WiedereroeffnenButtonContainerComponent, - ErledigenButtonContainerComponent, - CreateWiedervorlageButtonContainerComponent, - WiedervorlageAttachmentListContainerComponent, - WiedervorlageBreadcrumbContainerComponent, - WiedervorlageInVorgangExpandButtonComponent, - ], - providers: [DatePipe], - exports: [ - WiedervorlageListInVorgangContainerComponent, - WiedervorlageListInVorgangListContainerComponent, - CreateWiedervorlageButtonContainerComponent, - ] + imports: [ + CommonModule, + RouterModule.forChild(routes), + UiModule, + VorgangSharedModule, + TechSharedModule, + VorgangSharedUiModule, + BinaryFileModule, + UserProfileModule, + ], + declarations: [ + WiedervorlagePageComponent, + WiedervorlageInVorgangComponent, + WiedervorlageFormComponent, + WiedervorlageBreadcrumbComponent, + WiedervorlageListInVorgangContainerComponent, + WiedervorlageListInVorgangComponent, + WiedervorlageActionButtonsComponent, + WiedervorlagePageContainerComponent, + WiedervorlageStatusComponent, + WiedervorlageCreateButtonComponent, + WiedervorlageListInVorgangListContainerComponent, + SubmitWiedervorlageButtonComponent, + WiedereroeffnenButtonContainerComponent, + ErledigenButtonContainerComponent, + CreateWiedervorlageButtonContainerComponent, + WiedervorlageAttachmentListContainerComponent, + WiedervorlageBreadcrumbContainerComponent, + WiedervorlageInVorgangExpandButtonComponent, + ], + providers: [DatePipe], + exports: [ + WiedervorlageListInVorgangContainerComponent, + WiedervorlageListInVorgangListContainerComponent, + CreateWiedervorlageButtonContainerComponent, + ], }) -export class WiedervorlageModule { } +export class WiedervorlageModule {} diff --git a/alfa-client/libs/wiedervorlage/src/test-setup.ts b/alfa-client/libs/wiedervorlage/src/test-setup.ts index 5870fdabb6470fd0f6f3f63be3d4f6b8041b4dd2..e09d95a1bd4455db9bfd16809b94659c30a83956 100644 --- a/alfa-client/libs/wiedervorlage/src/test-setup.ts +++ b/alfa-client/libs/wiedervorlage/src/test-setup.ts @@ -26,17 +26,13 @@ import 'jest-preset-angular/setup-jest'; import { getTestBed } from '@angular/core/testing'; import { - BrowserDynamicTestingModule, - platformBrowserDynamicTesting + BrowserDynamicTestingModule, + platformBrowserDynamicTesting, } from '@angular/platform-browser-dynamic/testing'; getTestBed().resetTestEnvironment(); -getTestBed().initTestEnvironment( - BrowserDynamicTestingModule, - platformBrowserDynamicTesting(), - { - teardown: { destroyAfterEach: false }, - errorOnUnknownProperties: true, - errorOnUnknownElements: true - } -); +getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), { + teardown: { destroyAfterEach: false }, + errorOnUnknownProperties: true, + errorOnUnknownElements: true, +}); diff --git a/alfa-client/libs/wiedervorlage/tsconfig.json b/alfa-client/libs/wiedervorlage/tsconfig.json index 3d3a2a0498aafea3513d0d915e99d166d927fbe0..03261df5a47903bb7d4de17fbef9e9a14b048bed 100644 --- a/alfa-client/libs/wiedervorlage/tsconfig.json +++ b/alfa-client/libs/wiedervorlage/tsconfig.json @@ -1,16 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "compilerOptions": { - "target": "es2020" - } + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "compilerOptions": { + "target": "es2020" + } } diff --git a/alfa-client/libs/wiedervorlage/tsconfig.lib.json b/alfa-client/libs/wiedervorlage/tsconfig.lib.json index 5c763d5c2e6756dfbfd73ec05e0ce8fc76aff8c4..464f01e6b2b218c0f70e15ac25dd8580bdc38f6e 100644 --- a/alfa-client/libs/wiedervorlage/tsconfig.lib.json +++ b/alfa-client/libs/wiedervorlage/tsconfig.lib.json @@ -1,19 +1,19 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "target": "es2015", - "declaration": true, - "declarationMap": true, - "inlineSources": true, - "types": [], - "lib": ["dom", "es2018"] - }, - "angularCompilerOptions": { - "skipTemplateCodegen": true, - "strictMetadataEmit": true, - "enableResourceInlining": true - }, - "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], - "include": ["**/*.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "target": "es2015", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [], + "lib": ["dom", "es2018"] + }, + "angularCompilerOptions": { + "skipTemplateCodegen": true, + "strictMetadataEmit": true, + "enableResourceInlining": true + }, + "exclude": ["src/test-setup.ts", "**/*.spec.ts", "jest.config.ts"], + "include": ["**/*.ts"] } diff --git a/alfa-client/libs/wiedervorlage/tsconfig.spec.json b/alfa-client/libs/wiedervorlage/tsconfig.spec.json index 21d2cf38c41c4f5585c5756cceba2c2850dba0bf..3a690070a7f5e48080dd36522d6a0db384d940aa 100644 --- a/alfa-client/libs/wiedervorlage/tsconfig.spec.json +++ b/alfa-client/libs/wiedervorlage/tsconfig.spec.json @@ -1,12 +1,12 @@ { - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"], - "target": "ES2022", - "useDefineForClassFields": false - }, - "files": ["src/test-setup.ts"], - "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"], + "target": "ES2022", + "useDefineForClassFields": false + }, + "files": ["src/test-setup.ts"], + "include": ["**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] } diff --git a/alfa-client/nx.json b/alfa-client/nx.json index 2f6388329d7151b978b5cd4e46188b17d5459596..848237a025ee7fb9252b85e090a073afd6929346 100644 --- a/alfa-client/nx.json +++ b/alfa-client/nx.json @@ -1,93 +1,98 @@ { - "affected": { - "defaultBase": "master" - }, - "cli": { - "analytics": "96410a10-f846-4f96-b18f-6da7a28dea2d" - }, - "generators": { - "@nx/angular:application": { - "style": "scss", - "linter": "eslint", - "unitTestRunner": "jest", - "e2eTestRunner": "cypress" - }, - "@nx/angular:library": { - "linter": "eslint", - "unitTestRunner": "jest" - }, - "@nrwl/schematics:component": { - "styleext": "scss" - }, - "@schematics/angular:component": { - "styleext": "scss" - }, - "@nx/angular:component": { - "style": "scss" - }, - "@nx/angular": { - "application": { - "linter": "eslint" - }, - "library": { - "linter": "eslint" - }, - "storybook-configuration": { - "linter": "eslint" - } - } - }, - "defaultProject": "alfa", - "$schema": "./node_modules/nx/schemas/nx-schema.json", - "targetDefaults": { - "build": { - "dependsOn": ["^build"], - "inputs": ["production", "^production"], - "cache": true - }, - "e2e": { - "inputs": ["default", "^production"], - "cache": true - }, - "test": { - "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"], - "cache": true - }, - "lint": { - "inputs": ["default", "{workspaceRoot}/.eslintrc.json"], - "cache": true - }, - "build-storybook": { - "cache": true, - "inputs": ["default", "^production", "{projectRoot}/.storybook/**/*", "{projectRoot}/tsconfig.storybook.json"] - } - }, - "namedInputs": { - "default": ["{projectRoot}/**/*", "sharedGlobals"], - "sharedGlobals": [ - "{workspaceRoot}/angular.json", - "{workspaceRoot}/tsconfig.base.json", - "{workspaceRoot}/tslint.json", - "{workspaceRoot}/nx.json" - ], - "production": [ - "default", - "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", - "!{projectRoot}/tsconfig.spec.json", - "!{projectRoot}/jest.config.[jt]s", - "!{projectRoot}/.eslintrc.json", - "!{projectRoot}/src/test-setup.[jt]s", - "!{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)", - "!{projectRoot}/.storybook/**/*", - "!{projectRoot}/tsconfig.storybook.json" - ] - }, - "parallel": 1, - "tasksRunnerOptions": { - "default": { - "options": { - "cacheableOperations": ["build-storybook"] - } - } - } + "affected": { + "defaultBase": "master" + }, + "cli": { + "analytics": "96410a10-f846-4f96-b18f-6da7a28dea2d" + }, + "generators": { + "@nx/angular:application": { + "style": "scss", + "linter": "eslint", + "unitTestRunner": "jest", + "e2eTestRunner": "cypress" + }, + "@nx/angular:library": { + "linter": "eslint", + "unitTestRunner": "jest" + }, + "@nrwl/schematics:component": { + "styleext": "scss" + }, + "@schematics/angular:component": { + "styleext": "scss" + }, + "@nx/angular:component": { + "style": "scss" + }, + "@nx/angular": { + "application": { + "linter": "eslint" + }, + "library": { + "linter": "eslint" + }, + "storybook-configuration": { + "linter": "eslint" + } + } + }, + "defaultProject": "alfa", + "$schema": "./node_modules/nx/schemas/nx-schema.json", + "targetDefaults": { + "build": { + "dependsOn": ["^build"], + "inputs": ["production", "^production"], + "cache": true + }, + "e2e": { + "inputs": ["default", "^production"], + "cache": true + }, + "test": { + "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"], + "cache": true + }, + "lint": { + "inputs": ["default", "{workspaceRoot}/.eslintrc.json"], + "cache": true + }, + "build-storybook": { + "cache": true, + "inputs": [ + "default", + "^production", + "{projectRoot}/.storybook/**/*", + "{projectRoot}/tsconfig.storybook.json" + ] + } + }, + "namedInputs": { + "default": ["{projectRoot}/**/*", "sharedGlobals"], + "sharedGlobals": [ + "{workspaceRoot}/angular.json", + "{workspaceRoot}/tsconfig.base.json", + "{workspaceRoot}/tslint.json", + "{workspaceRoot}/nx.json" + ], + "production": [ + "default", + "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", + "!{projectRoot}/tsconfig.spec.json", + "!{projectRoot}/jest.config.[jt]s", + "!{projectRoot}/.eslintrc.json", + "!{projectRoot}/src/test-setup.[jt]s", + "!{projectRoot}/**/*.stories.@(js|jsx|ts|tsx|mdx)", + "!{projectRoot}/.storybook/**/*", + "!{projectRoot}/tsconfig.storybook.json" + ] + }, + "parallel": 1, + "tasksRunnerOptions": { + "default": { + "options": { + "cacheableOperations": ["build-storybook"] + } + } + } } diff --git a/alfa-client/package-lock.json b/alfa-client/package-lock.json index a4aaf8a1125f5d06a2582e2844c4eca54b79de67..f94cb80b1c16c854b7222c2b085d170473060f7b 100644 --- a/alfa-client/package-lock.json +++ b/alfa-client/package-lock.json @@ -34,8 +34,6 @@ "include-media": "^1.4.10", "js-base64": "^3.7.5", "lodash-es": "4.17.21", - "react": "^18.2.0", - "react-dom": "^18.2.0", "rxjs": "~7.8.1", "sanitize-filename-ts": "^1.0.2", "tslib": "^2.3.0", @@ -105,8 +103,10 @@ "postcss-import": "~14.1.0", "postcss-preset-env": "~7.5.0", "postcss-url": "~10.1.3", - "prettier": "^3.2.4", - "prettier-plugin-tailwindcss": "^0.5.7", + "prettier": "^3.2.5", + "prettier-plugin-tailwindcss": "^0.5.11", + "react": "^18.2.0", + "react-dom": "^18.2.0", "sonarqube-scanner": "3.1.0", "tailwindcss": "^3.0.2", "ts-jest": "^29.1.0", @@ -5110,13 +5110,12 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm/-/android-arm-0.19.5.tgz", - "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5127,13 +5126,12 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", - "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5144,13 +5142,12 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-x64/-/android-x64-0.19.5.tgz", - "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5161,13 +5158,12 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", - "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5195,13 +5191,12 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", - "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5212,13 +5207,12 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", - "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5229,13 +5223,12 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", - "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5246,13 +5239,12 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", - "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5263,13 +5255,12 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", - "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5280,13 +5271,12 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", - "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", "cpu": [ "loong64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5297,13 +5287,12 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", - "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", "cpu": [ "mips64el" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5314,13 +5303,12 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", - "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5331,13 +5319,12 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", - "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", "cpu": [ "riscv64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5348,13 +5335,12 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", - "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5365,13 +5351,12 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", - "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5382,13 +5367,12 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", - "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5399,13 +5383,12 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", - "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5416,13 +5399,12 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", - "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5433,13 +5415,12 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", - "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5450,13 +5431,12 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", - "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", "cpu": [ "ia32" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5467,13 +5447,12 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", - "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "version": "0.18.20", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -5647,24 +5626,24 @@ } }, "node_modules/@floating-ui/dom": { - "version": "1.6.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@floating-ui/dom/-/dom-1.6.0.tgz", - "integrity": "sha512-SZ0BEXzsaaS6THZfZJUcAobbZTD+MvfGM42bxgeg0Tnkp4/an/avqwAXiVLsFtIBZtfsx3Ymvwx0+KnnhdA/9g==", + "version": "1.6.3", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@floating-ui/dom/-/dom-1.6.3.tgz", + "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.1" + "@floating-ui/core": "^1.0.0", + "@floating-ui/utils": "^0.2.0" } }, "node_modules/@floating-ui/react-dom": { - "version": "2.0.7", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@floating-ui/react-dom/-/react-dom-2.0.7.tgz", - "integrity": "sha512-B5GJxKUyPcGsvE1vua+Abvw0t6zVMyTbtG+Jk7BoI4hfc5Ahv50dstRIAn0nS0274kR9gnKwxIXyGA8EzBZJrA==", + "version": "2.0.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@floating-ui/react-dom/-/react-dom-2.0.8.tgz", + "integrity": "sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.6.0" + "@floating-ui/dom": "^1.6.1" }, "peerDependencies": { "react": ">=16.8.0", @@ -7759,13 +7738,13 @@ } }, "node_modules/@nrwl/storybook": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nrwl/storybook/-/storybook-17.2.8.tgz", - "integrity": "sha512-YBedhVfpylP48lG7VqB7xdiPp5DsEY6aFeabiZC3DQWK+oaMAIOYUKFD6+LiviDoPGpIJCeoJRC0UcnAuaLO7g==", + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nrwl/storybook/-/storybook-17.3.2.tgz", + "integrity": "sha512-7oRD83FTa9c5fWWgdtIlmJ7Vt4ppfUNy9CPcWrZoxf+PWUXsxFclT4SyC+Wxo0Ccax/kBU2hJ5iP0X6UHV0vmQ==", "dev": true, "license": "MIT", "dependencies": { - "@nx/storybook": "17.2.8" + "@nx/storybook": "17.3.2" } }, "node_modules/@nrwl/tao": { @@ -9470,23 +9449,6 @@ "nx": ">= 16 <= 18" } }, - "node_modules/@nx/js/node_modules/@nx/nx-darwin-arm64": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-darwin-arm64/-/nx-darwin-arm64-17.2.8.tgz", - "integrity": "sha512-dMb0uxug4hM7tusISAU1TfkDK3ixYmzc1zhHSZwpR7yKJIyKLtUpBTbryt8nyso37AS1yH+dmfh2Fj2WxfBHTg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@nx/js/node_modules/@nx/nx-darwin-x64": { "version": "17.2.8", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-darwin-x64/-/nx-darwin-x64-17.2.8.tgz", @@ -9504,142 +9466,6 @@ "node": ">= 10" } }, - "node_modules/@nx/js/node_modules/@nx/nx-freebsd-x64": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-freebsd-x64/-/nx-freebsd-x64-17.2.8.tgz", - "integrity": "sha512-YFMgx5Qpp2btCgvaniDGdu7Ctj56bfFvbbaHQWmOeBPK1krNDp2mqp8HK6ZKOfEuDJGOYAp7HDtCLvdZKvJxzA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-17.2.8.tgz", - "integrity": "sha512-iN2my6MrhLRkVDtdivQHugK8YmR7URo1wU9UDuHQ55z3tEcny7LV3W9NSsY9UYPK/FrxdDfevj0r2hgSSdhnzA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-arm64-gnu": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-17.2.8.tgz", - "integrity": "sha512-Iy8BjoW6mOKrSMiTGujUcNdv+xSM1DALTH6y3iLvNDkGbjGK1Re6QNnJAzqcXyDpv32Q4Fc57PmuexyysZxIGg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-arm64-musl": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-17.2.8.tgz", - "integrity": "sha512-9wkAxWzknjpzdofL1xjtU6qPFF1PHlvKCZI3hgEYJDo4mQiatGI+7Ttko+lx/ZMP6v4+Umjtgq7+qWrApeKamQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-x64-gnu": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-17.2.8.tgz", - "integrity": "sha512-sjG1bwGsjLxToasZ3lShildFsF0eyeGu+pOQZIp9+gjFbeIkd19cTlCnHrOV9hoF364GuKSXQyUlwtFYFR4VTQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-linux-x64-musl": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-17.2.8.tgz", - "integrity": "sha512-QiakXZ1xBCIptmkGEouLHQbcM4klQkcr+kEaz2PlNwy/sW3gH1b/1c0Ed5J1AN9xgQxWspriAONpScYBRgxdhA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-win32-arm64-msvc": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-17.2.8.tgz", - "integrity": "sha512-XBWUY/F/GU3vKN9CAxeI15gM4kr3GOBqnzFZzoZC4qJt2hKSSUEWsMgeZtsMgeqEClbi4ZyCCkY7YJgU32WUGA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nx/js/node_modules/@nx/nx-win32-x64-msvc": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-17.2.8.tgz", - "integrity": "sha512-HTqDv+JThlLzbcEm/3f+LbS5/wYQWzb5YDXbP1wi7nlCTihNZOLNqGOkEmwlrR5tAdNHPRpHSmkYg4305W0CtA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@nx/js/node_modules/@nx/workspace": { "version": "17.2.8", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/workspace/-/workspace-17.2.8.tgz", @@ -10001,12 +9827,13 @@ } }, "node_modules/@nx/nx-darwin-arm64": { - "version": "17.0.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-darwin-arm64/-/nx-darwin-arm64-17.0.2.tgz", - "integrity": "sha512-OSZLRfV8VplYPEqMcIg3mbAsJXlXEHKrdlJ0KUTk8Hih2+wl7cxuSEwG7X7qfBUOz+ognxaqicL+hueNrgwjlQ==", + "version": "17.2.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-darwin-arm64/-/nx-darwin-arm64-17.2.8.tgz", + "integrity": "sha512-dMb0uxug4hM7tusISAU1TfkDK3ixYmzc1zhHSZwpR7yKJIyKLtUpBTbryt8nyso37AS1yH+dmfh2Fj2WxfBHTg==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10033,12 +9860,13 @@ } }, "node_modules/@nx/nx-freebsd-x64": { - "version": "17.0.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-freebsd-x64/-/nx-freebsd-x64-17.0.2.tgz", - "integrity": "sha512-+mta0J2G2byd+rfZ275oZs0aYXC/s92nI9ySBFQFQZnKJ6bsAagdZHe+uETsnE4xdhFXD8kvNMJU1WTGlyFyjg==", + "version": "17.2.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-freebsd-x64/-/nx-freebsd-x64-17.2.8.tgz", + "integrity": "sha512-YFMgx5Qpp2btCgvaniDGdu7Ctj56bfFvbbaHQWmOeBPK1krNDp2mqp8HK6ZKOfEuDJGOYAp7HDtCLvdZKvJxzA==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10049,12 +9877,13 @@ } }, "node_modules/@nx/nx-linux-arm-gnueabihf": { - "version": "17.0.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-17.0.2.tgz", - "integrity": "sha512-m80CmxHHyNAJ8j/0rkjc0hg/eGQlf6V2sLsV+gEJkz2sTEEdgSOK4DvnWcZRWO/SWBnqigxoHX4Kf5TH1nmoHA==", + "version": "17.2.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-17.2.8.tgz", + "integrity": "sha512-iN2my6MrhLRkVDtdivQHugK8YmR7URo1wU9UDuHQ55z3tEcny7LV3W9NSsY9UYPK/FrxdDfevj0r2hgSSdhnzA==", "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10065,12 +9894,13 @@ } }, "node_modules/@nx/nx-linux-arm64-gnu": { - "version": "17.0.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-17.0.2.tgz", - "integrity": "sha512-AsD1H6wt68MK1u6vkmtNaFaxDMcyuk6dpo5kq1YT9cfUd614ys3qMUjVp3P2CXxzXh+0UDZeGrc6qotNKOkpJw==", + "version": "17.2.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-17.2.8.tgz", + "integrity": "sha512-Iy8BjoW6mOKrSMiTGujUcNdv+xSM1DALTH6y3iLvNDkGbjGK1Re6QNnJAzqcXyDpv32Q4Fc57PmuexyysZxIGg==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10081,12 +9911,13 @@ } }, "node_modules/@nx/nx-linux-arm64-musl": { - "version": "17.0.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-17.0.2.tgz", - "integrity": "sha512-f8pUFoZHBFQtHnopHgTEuwIiu0Rzem0dD7iK8SyyBy/lRAADtHCAHxaPAG+iatHAJ9h4DFIB50k9ybYxDtH2mg==", + "version": "17.2.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-17.2.8.tgz", + "integrity": "sha512-9wkAxWzknjpzdofL1xjtU6qPFF1PHlvKCZI3hgEYJDo4mQiatGI+7Ttko+lx/ZMP6v4+Umjtgq7+qWrApeKamQ==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10097,12 +9928,13 @@ } }, "node_modules/@nx/nx-linux-x64-gnu": { - "version": "17.0.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-17.0.2.tgz", - "integrity": "sha512-PISrHjLTxv5w8bz50vPZH6puYos88xu28o4IbVyYWrUrhoFsAx9Zbn1D6gWDPMSaKJU32v1l+5bTciQjQJU8fQ==", + "version": "17.2.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-17.2.8.tgz", + "integrity": "sha512-sjG1bwGsjLxToasZ3lShildFsF0eyeGu+pOQZIp9+gjFbeIkd19cTlCnHrOV9hoF364GuKSXQyUlwtFYFR4VTQ==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10113,12 +9945,13 @@ } }, "node_modules/@nx/nx-linux-x64-musl": { - "version": "17.0.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-17.0.2.tgz", - "integrity": "sha512-2wsqyBRjsxmAjxW+0lnGFtJLTk+AxgW7gjMv8NgLK8P1bc/sJYQB+g0o5op2z+szXRG3Noi0RZ9C0fG39EPFZw==", + "version": "17.2.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-17.2.8.tgz", + "integrity": "sha512-QiakXZ1xBCIptmkGEouLHQbcM4klQkcr+kEaz2PlNwy/sW3gH1b/1c0Ed5J1AN9xgQxWspriAONpScYBRgxdhA==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10129,12 +9962,13 @@ } }, "node_modules/@nx/nx-win32-arm64-msvc": { - "version": "17.0.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-17.0.2.tgz", - "integrity": "sha512-Sc3sQUcS5xdk05PABe/knG6orG5rmHZdSUj6SMRpvYfN2tM3ziNn6/wCF/LJoW6n70OxrOEXXwLSRK/5WigXbA==", + "version": "17.2.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-17.2.8.tgz", + "integrity": "sha512-XBWUY/F/GU3vKN9CAxeI15gM4kr3GOBqnzFZzoZC4qJt2hKSSUEWsMgeZtsMgeqEClbi4ZyCCkY7YJgU32WUGA==", "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10145,12 +9979,13 @@ } }, "node_modules/@nx/nx-win32-x64-msvc": { - "version": "17.0.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-17.0.2.tgz", - "integrity": "sha512-XhET0BDk6fbvTBCs7m5gZii8+2WhLpiC1sZchJw4LAJN2VJBiy3I3xnvpQYGFOAWaCb/iUGpuN/qP/NlQ+LNgA==", + "version": "17.2.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-17.2.8.tgz", + "integrity": "sha512-HTqDv+JThlLzbcEm/3f+LbS5/wYQWzb5YDXbP1wi7nlCTihNZOLNqGOkEmwlrR5tAdNHPRpHSmkYg4305W0CtA==", "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10161,56 +9996,138 @@ } }, "node_modules/@nx/storybook": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/storybook/-/storybook-17.2.8.tgz", - "integrity": "sha512-8fQck3mP2i3XWCnq/p5l+Y11TQTr8Gv4L64Rggq6nPuZOk6RbinCPG+VMztqGgQET8q4XTTGt8yw5VOUG0cIyw==", + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/storybook/-/storybook-17.3.2.tgz", + "integrity": "sha512-nqfw8NKe3+D7B7iWT68cLxmjTkq8w1pgguuzbQPySlZl7qXwsrGl4lqtdjhXQ4xrOZiptg6QkiZWH6Sp5AYTzg==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/storybook": "17.2.8", - "@nx/cypress": "17.2.8", - "@nx/devkit": "17.2.8", - "@nx/eslint": "17.2.8", - "@nx/js": "17.2.8", + "@nrwl/storybook": "17.3.2", + "@nx/cypress": "17.3.2", + "@nx/devkit": "17.3.2", + "@nx/eslint": "17.3.2", + "@nx/js": "17.3.2", "@phenomnomnominal/tsquery": "~5.0.1", - "semver": "7.5.3", + "semver": "^7.5.3", "tslib": "^2.3.0" } }, + "node_modules/@nx/storybook/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@nx/storybook/node_modules/@babel/plugin-transform-runtime": { + "version": "7.23.9", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.9.tgz", + "integrity": "sha512-A7clW3a0aSjm3ONU9o2HAILSegJCYlEZmOhmBRReVtIpY/Z/p7yIZ+wR41Z+UipwdGuqwtID/V/dOdZXjwi9gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "babel-plugin-polyfill-corejs2": "^0.4.8", + "babel-plugin-polyfill-corejs3": "^0.9.0", + "babel-plugin-polyfill-regenerator": "^0.5.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@nx/storybook/node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/@nx/storybook/node_modules/@nrwl/cypress": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nrwl/cypress/-/cypress-17.2.8.tgz", - "integrity": "sha512-32owq2ybkkKOIeqQ/mkwBzFH4HPukmHEJyJ4v95sUgY8qrnj/Ca89vozdJ6WEvUiqcAb7ebrmp/nqFCz7PIWbg==", + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nrwl/cypress/-/cypress-17.3.2.tgz", + "integrity": "sha512-TdSDs6GwFbLB/3npKIMIathF2HoFj/n2ApkW6DWsw4tn4Vrw/VbI6bLVTxZuhCkUZUNc0PCHTmC5gQjc5/xnyQ==", "dev": true, "license": "MIT", "dependencies": { - "@nx/cypress": "17.2.8" + "@nx/cypress": "17.3.2" } }, "node_modules/@nx/storybook/node_modules/@nrwl/devkit": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nrwl/devkit/-/devkit-17.2.8.tgz", - "integrity": "sha512-l2dFy5LkWqSA45s6pee6CoqJeluH+sjRdVnAAQfjLHRNSx6mFAKblyzq5h1f4P0EUCVVVqLs+kVqmNx5zxYqvw==", + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nrwl/devkit/-/devkit-17.3.2.tgz", + "integrity": "sha512-31wh7dDZPM1YUCfhhk/ioHnUeoPIlKYLFLW0fGdw76Ow2nmTqrmxha2m0CSIR1/9En9GpYut2IdUdNh9CctNlA==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "17.2.8" + "@nx/devkit": "17.3.2" + } + }, + "node_modules/@nx/storybook/node_modules/@nrwl/js": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nrwl/js/-/js-17.3.2.tgz", + "integrity": "sha512-WuIeSErulJuMeSpeK41RfiWI3jLjDD0S+tLnYdOLaWdjaIPqjknClM2BAJKlq472NnkkNWvtwtOS8jm518OjOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/js": "17.3.2" + } + }, + "node_modules/@nx/storybook/node_modules/@nrwl/tao": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nrwl/tao/-/tao-17.3.2.tgz", + "integrity": "sha512-5uvpSmij0J9tteFV/0M/024K+H/o3XAlqtSdU8j03Auj1IleclSLF2yCTuIo7pYXhG3cgx1+nR+3nMs1QVAdUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "nx": "17.3.2", + "tslib": "^2.3.0" + }, + "bin": { + "tao": "index.js" + } + }, + "node_modules/@nx/storybook/node_modules/@nrwl/workspace": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nrwl/workspace/-/workspace-17.3.2.tgz", + "integrity": "sha512-7xE/dujPjOIxsCV6TB0C4768voQaQSxmEUAbVz0mywBGrVpjpvAIx1GvdB6wwgWqtpZTz34hKFkUSJFPweUvbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/workspace": "17.3.2" } }, "node_modules/@nx/storybook/node_modules/@nx/cypress": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/cypress/-/cypress-17.2.8.tgz", - "integrity": "sha512-RjDD2AjDg7D743/+hSgzllLlSi4RwP196Nm0C8ltG5udPK1W+3S0qcERgHgtTuYr6+WVZIMtcZF2Vq09zcbtyg==", + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/cypress/-/cypress-17.3.2.tgz", + "integrity": "sha512-uf4m5cWuSicHIAEZoeU4iQpSiOgnV15pdsoqCVIMYQ1JUGrInYx3kAe87GJAF31tsQHSyExcfj28i8cR8OXQ1A==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/cypress": "17.2.8", - "@nx/devkit": "17.2.8", - "@nx/eslint": "17.2.8", - "@nx/js": "17.2.8", + "@nrwl/cypress": "17.3.2", + "@nx/devkit": "17.3.2", + "@nx/eslint": "17.3.2", + "@nx/js": "17.3.2", "@phenomnomnominal/tsquery": "~5.0.1", "detect-port": "^1.5.1", - "semver": "7.5.3", + "semver": "^7.5.3", "tslib": "^2.3.0" }, "peerDependencies": { @@ -10223,58 +10140,305 @@ } }, "node_modules/@nx/storybook/node_modules/@nx/devkit": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/devkit/-/devkit-17.2.8.tgz", - "integrity": "sha512-6LtiQihtZwqz4hSrtT5cCG5XMCWppG6/B8c1kNksg97JuomELlWyUyVF+sxmeERkcLYFaKPTZytP0L3dmCFXaw==", + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/devkit/-/devkit-17.3.2.tgz", + "integrity": "sha512-gbOIhwrZKCSSFFbh6nE6LLCvAU7mhSdBSnRiS14YBwJJMu4CRJ0IcaFz58iXqGWZefMivKtkNFtx+zqwUC4ziw==", "dev": true, "license": "MIT", "dependencies": { - "@nrwl/devkit": "17.2.8", + "@nrwl/devkit": "17.3.2", "ejs": "^3.1.7", "enquirer": "~2.3.6", "ignore": "^5.0.4", - "semver": "7.5.3", + "semver": "^7.5.3", "tmp": "~0.2.1", - "tslib": "^2.3.0" + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" }, "peerDependencies": { "nx": ">= 16 <= 18" } }, "node_modules/@nx/storybook/node_modules/@nx/eslint": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/eslint/-/eslint-17.2.8.tgz", - "integrity": "sha512-P6s85cIK7LYHixCJFZ+tLCPDxeOt9m2bQQOLxBCLEy5mqaGmjMHzWkLaoQBueCSntE6PSao0MMA+1TeeZjOoDw==", + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/eslint/-/eslint-17.3.2.tgz", + "integrity": "sha512-KArvmi9Y4Qcf0bIRXGC1/FZsjL6XtT7wzhJ5uGsJIvXAJUiMMlw/KqIR31pY4nu2cBbphCa0/P1Jp2C/IFXG8w==", "dev": true, "license": "MIT", "dependencies": { - "@nx/devkit": "17.2.8", - "@nx/js": "17.2.8", - "@nx/linter": "17.2.8", + "@nx/devkit": "17.3.2", + "@nx/js": "17.3.2", + "@nx/linter": "17.3.2", + "eslint": "^8.0.0", "tslib": "^2.3.0", - "typescript": "~5.2.2" + "typescript": "~5.3.2" }, "peerDependencies": { - "eslint": "^8.0.0", "js-yaml": "4.1.0" }, "peerDependenciesMeta": { - "eslint": { - "optional": true - }, "js-yaml": { "optional": true } } }, + "node_modules/@nx/storybook/node_modules/@nx/js": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/js/-/js-17.3.2.tgz", + "integrity": "sha512-37E3OILyu/7rCj6Z7tvC6PktHYa51UQBU+wWPdVWSZ64xu1SUsg9B9dfiyD1LXR9/rhjg4+0+g4cou0aqDK1Wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.2", + "@babel/plugin-proposal-decorators": "^7.22.7", + "@babel/plugin-transform-class-properties": "^7.22.5", + "@babel/plugin-transform-runtime": "^7.23.2", + "@babel/preset-env": "^7.23.2", + "@babel/preset-typescript": "^7.22.5", + "@babel/runtime": "^7.22.6", + "@nrwl/js": "17.3.2", + "@nx/devkit": "17.3.2", + "@nx/workspace": "17.3.2", + "@phenomnomnominal/tsquery": "~5.0.1", + "babel-plugin-const-enum": "^1.0.1", + "babel-plugin-macros": "^2.8.0", + "babel-plugin-transform-typescript-metadata": "^0.3.1", + "chalk": "^4.1.0", + "columnify": "^1.6.0", + "detect-port": "^1.5.1", + "fast-glob": "3.2.7", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "js-tokens": "^4.0.0", + "minimatch": "9.0.3", + "npm-package-arg": "11.0.1", + "npm-run-path": "^4.0.1", + "ora": "5.3.0", + "semver": "^7.5.3", + "source-map-support": "0.5.19", + "ts-node": "10.9.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0" + }, + "peerDependencies": { + "verdaccio": "^5.0.4" + }, + "peerDependenciesMeta": { + "verdaccio": { + "optional": true + } + } + }, "node_modules/@nx/storybook/node_modules/@nx/linter": { - "version": "17.2.8", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/linter/-/linter-17.2.8.tgz", - "integrity": "sha512-dwqE742TIw1+/djzlikKakIfComq8nFnhupWjvl7KrU9r8ytcKyQbxHw7KGMUT9HAEG4xSNuwiaELr/8w4MM2Q==", + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/linter/-/linter-17.3.2.tgz", + "integrity": "sha512-ruB72ODekAlqGI65IeO37vqgJIY+ROcx2Gyf12H3tZGUYeC1IwpPltbU63vD5Qkgj2znrD6aNkpYPV7C0b0scQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nx/eslint": "17.3.2" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-darwin-arm64": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-darwin-arm64/-/nx-darwin-arm64-17.3.2.tgz", + "integrity": "sha512-hn12o/tt26Pf4wG+8rIBgNIEZq5BFlHLv3scNrgKbd5SancHlTbY4RveRGct737UQ/78GCMCgMDRgNdagbCr6w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-darwin-x64": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-darwin-x64/-/nx-darwin-x64-17.3.2.tgz", + "integrity": "sha512-5F28wrfE7yU60MzEXGjndy1sPJmNMIaV2W/g82kTXzxAbGHgSjwrGFmrJsrexzLp9oDlWkbc6YmInKV8gmmIaQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-freebsd-x64": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-freebsd-x64/-/nx-freebsd-x64-17.3.2.tgz", + "integrity": "sha512-07MMTfsJooONqL1Vrm5L6qk/gzmSrYLazjkiTmJz+9mrAM61RdfSYfO3mSyAoyfgWuQ5yEvfI56P036mK8aoPg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-17.3.2.tgz", + "integrity": "sha512-gQxMF6U/h18Rz+FZu50DZCtfOdk27hHghNh3d3YTeVsrJTd1SmUQbYublmwU/ia1HhFS8RVI8GvkaKt5ph0HoA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-17.3.2.tgz", + "integrity": "sha512-X20wiXtXmKlC01bpVEREsRls1uVOM22xDTpqILvVty6+P+ytEYFR3Vs5EjDtzBKF51wjrwf03rEoToZbmgM8MA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-linux-arm64-musl": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-17.3.2.tgz", + "integrity": "sha512-yko3Xsezkn4tjeudZYLjxFl07X/YB84K+DLK7EFyh9elRWV/8VjFcQmBAKUS2r9LfaEMNXq8/vhWMOWYyWBrIA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-linux-x64-gnu": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-17.3.2.tgz", + "integrity": "sha512-RiPvvQMmlZmDu9HdT6n6sV0+fEkyAqR5VocrD5ZAzEzFIlh4dyVLripFR3+MD+QhIhXyPt/hpri1kq9sgs4wnw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-linux-x64-musl": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-17.3.2.tgz", + "integrity": "sha512-PWfVGmFsFJi+N1Nljg/jTKLHdufpGuHlxyfHqhDso/o4Qc0exZKSeZ1C63WkD7eTcT5kInifTQ/PffLiIDE3MA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-17.3.2.tgz", + "integrity": "sha512-O+4FFPbQz1mqaIj+SVE02ppe7T9ELj7Z5soQct5TbRRhwjGaw5n5xaPPBW7jUuQe2L5htid1E82LJyq3JpVc8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/nx-win32-x64-msvc": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-17.3.2.tgz", + "integrity": "sha512-4hQm+7coy+hBqGY9J709hz/tUPijhf/WS7eML2r2xBmqBew3PMHfeZuaAAYWN690nIsu0WX3wyDsNjulR8HGPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nx/storybook/node_modules/@nx/workspace": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/workspace/-/workspace-17.3.2.tgz", + "integrity": "sha512-2y952OmJx+0Rj+LQIxat8SLADjIkgB6NvjtgYZt8uRQ94jRS/JsRvGTw0V8DsY9mvsNbYoIRdJP25T3pGnI3gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nrwl/workspace": "17.3.2", + "@nx/devkit": "17.3.2", + "chalk": "^4.1.0", + "enquirer": "~2.3.6", + "nx": "17.3.2", + "tslib": "^2.3.0", + "yargs-parser": "21.1.1" + } + }, + "node_modules/@nx/storybook/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { - "@nx/eslint": "17.2.8" + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/@nx/storybook/node_modules/argparse": { @@ -10282,9 +10446,68 @@ "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true, - "license": "Python-2.0", - "optional": true, - "peer": true + "license": "Python-2.0" + }, + "node_modules/@nx/storybook/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.9.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz", + "integrity": "sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.5.0", + "core-js-compat": "^3.34.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@nx/storybook/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/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/@nx/storybook/node_modules/chalk": { + "version": "4.1.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/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/@nx/storybook/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/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/@nx/storybook/node_modules/color-name": { + "version": "1.1.4", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" }, "node_modules/@nx/storybook/node_modules/enquirer": { "version": "2.3.6", @@ -10299,14 +10522,52 @@ "node": ">=8.6" } }, + "node_modules/@nx/storybook/node_modules/fast-glob": { + "version": "3.2.7", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/fast-glob/-/fast-glob-3.2.7.tgz", + "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/storybook/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@nx/storybook/node_modules/hosted-git-info": { + "version": "7.0.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/hosted-git-info/-/hosted-git-info-7.0.1.tgz", + "integrity": "sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^10.0.1" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, "node_modules/@nx/storybook/node_modules/js-yaml": { "version": "4.1.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "dependencies": { "argparse": "^2.0.1" }, @@ -10314,39 +10575,181 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@nx/storybook/node_modules/semver": { - "version": "7.5.3", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/semver/-/semver-7.5.3.tgz", - "integrity": "sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==", + "node_modules/@nx/storybook/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/@nx/storybook/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, "license": "ISC", "dependencies": { - "lru-cache": "^6.0.0" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@nx/storybook/node_modules/npm-package-arg": { + "version": "11.0.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/npm-package-arg/-/npm-package-arg-11.0.1.tgz", + "integrity": "sha512-M7s1BD4NxdAvBKUPqqRW957Xwcl/4Zvo8Aj+ANrzvIPzGJZElrH7Z//rSaec2ORcND6FHHLnZeY8qgTpXDMFQQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^7.0.0", + "proc-log": "^3.0.0", + "semver": "^7.3.5", + "validate-npm-package-name": "^5.0.0" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + } + }, + "node_modules/@nx/storybook/node_modules/nx": { + "version": "17.3.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/nx/-/nx-17.3.2.tgz", + "integrity": "sha512-QjF1gnwKebQISvATrSbW7dsmIcLbA0fcyDyxLo5wVHx/MIlcaIb/lLYaPTld73ZZ6svHEZ6n2gOkhMitmkIPQA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@nrwl/tao": "17.3.2", + "@yarnpkg/lockfile": "^1.1.0", + "@yarnpkg/parsers": "3.0.0-rc.46", + "@zkochan/js-yaml": "0.0.6", + "axios": "^1.6.0", + "chalk": "^4.1.0", + "cli-cursor": "3.1.0", + "cli-spinners": "2.6.1", + "cliui": "^8.0.1", + "dotenv": "~16.3.1", + "dotenv-expand": "~10.0.0", + "enquirer": "~2.3.6", + "figures": "3.2.0", + "flat": "^5.0.2", + "fs-extra": "^11.1.0", + "ignore": "^5.0.4", + "jest-diff": "^29.4.1", + "js-yaml": "4.1.0", + "jsonc-parser": "3.2.0", + "lines-and-columns": "~2.0.3", + "minimatch": "9.0.3", + "node-machine-id": "1.1.12", + "npm-run-path": "^4.0.1", + "open": "^8.4.0", + "ora": "5.3.0", + "semver": "^7.5.3", + "string-width": "^4.2.3", + "strong-log-transformer": "^2.1.0", + "tar-stream": "~2.2.0", + "tmp": "~0.2.1", + "tsconfig-paths": "^4.1.2", + "tslib": "^2.3.0", + "yargs": "^17.6.2", + "yargs-parser": "21.1.1" }, "bin": { - "semver": "bin/semver.js" + "nx": "bin/nx.js", + "nx-cloud": "bin/nx-cloud.js" + }, + "optionalDependencies": { + "@nx/nx-darwin-arm64": "17.3.2", + "@nx/nx-darwin-x64": "17.3.2", + "@nx/nx-freebsd-x64": "17.3.2", + "@nx/nx-linux-arm-gnueabihf": "17.3.2", + "@nx/nx-linux-arm64-gnu": "17.3.2", + "@nx/nx-linux-arm64-musl": "17.3.2", + "@nx/nx-linux-x64-gnu": "17.3.2", + "@nx/nx-linux-x64-musl": "17.3.2", + "@nx/nx-win32-arm64-msvc": "17.3.2", + "@nx/nx-win32-x64-msvc": "17.3.2" + }, + "peerDependencies": { + "@swc-node/register": "^1.6.7", + "@swc/core": "^1.3.85" + }, + "peerDependenciesMeta": { + "@swc-node/register": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nx/storybook/node_modules/ora": { + "version": "5.3.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ora/-/ora-5.3.0.tgz", + "integrity": "sha512-zAKMgGXUim0Jyd6CXK9lraBnD3H5yPGBPPOkC23a2BG6hsm4Zu6OQSjQuEtV0BHDf4aKHcUFvJiGRrFuW3MG8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "log-symbols": "^4.0.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@nx/storybook/node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/@nx/storybook/node_modules/source-map": { + "version": "0.6.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "license": "ISC", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@nx/storybook/node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@nx/storybook/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/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": ">=10" + "node": ">=8" } }, "node_modules/@nx/storybook/node_modules/typescript": { - "version": "5.2.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.3", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "license": "Apache-2.0", "bin": { @@ -10357,13 +10760,6 @@ "node": ">=14.17" } }, - "node_modules/@nx/storybook/node_modules/yallist": { - "version": "4.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, "node_modules/@nx/web": { "version": "17.0.2", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/web/-/web-17.0.2.tgz", @@ -12186,13 +12582,13 @@ } }, "node_modules/@storybook/addon-actions": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-actions/-/addon-actions-7.6.10.tgz", - "integrity": "sha512-pcKmf0H/caGzKDy8cz1adNSjv+KOBWLJ11RzGExrWm+Ad5ACifwlsQPykJ3TQ/21sTd9IXVrE9uuq4LldEnPbg==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-actions/-/addon-actions-7.6.14.tgz", + "integrity": "sha512-hFVB/ejxBdE6J3wOEPSx6aFB51PqDfQ/YR4ik5GCGJb3cmUX7d/FY8zH0TKJLXcG/Hw3XoxNiEo5AaMVxtGVGA==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/core-events": "7.6.10", + "@storybook/core-events": "7.6.14", "@storybook/global": "^5.0.0", "@types/uuid": "^9.0.1", "dequal": "^2.0.2", @@ -12219,9 +12615,9 @@ } }, "node_modules/@storybook/addon-backgrounds": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-backgrounds/-/addon-backgrounds-7.6.10.tgz", - "integrity": "sha512-kGzsN1QkfyI8Cz7TErEx9OCB3PMzpCFGLd/iy7FreXwbMbeAQ3/9fYgKUsNOYgOhuTz7S09koZUWjS/WJuZGFA==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-backgrounds/-/addon-backgrounds-7.6.14.tgz", + "integrity": "sha512-R6OblK71iKIwpxTZQhuOpbktIT5pNrfMNe4/lkIP2F6Dv9HgHwvg95Bpt0ebHKlRvD7KNwj1whKjJh1fO3yLgQ==", "dev": true, "license": "MIT", "dependencies": { @@ -12235,13 +12631,13 @@ } }, "node_modules/@storybook/addon-controls": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-controls/-/addon-controls-7.6.10.tgz", - "integrity": "sha512-LjwCQRMWq1apLtFwDi6U8MI6ITUr+KhxJucZ60tfc58RgB2v8ayozyDAonFEONsx9YSR1dNIJ2Z/e2rWTBJeYA==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-controls/-/addon-controls-7.6.14.tgz", + "integrity": "sha512-KJRPdzbXjitqCixMzMjkcRYJGIts9wrx2Qk7NCSXCbE0LDdT+U7//25luLp5DrRiPdqIVEQjNcLF10frljaA9g==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/blocks": "7.6.10", + "@storybook/blocks": "7.6.14", "lodash": "^4.17.21", "ts-dedent": "^2.0.0" }, @@ -12251,27 +12647,27 @@ } }, "node_modules/@storybook/addon-docs": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-docs/-/addon-docs-7.6.10.tgz", - "integrity": "sha512-GtyQ9bMx1AOOtl6ZS9vwK104HFRK+tqzxddRRxhXkpyeKu3olm9aMgXp35atE/3fJSqyyDm2vFtxxH8mzBA20A==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-docs/-/addon-docs-7.6.14.tgz", + "integrity": "sha512-fH3voEcHuJmMXNIT6Lxs5ve+dM6P74gwhdyMj21WIp8DnYM99RrmjvT1k/3+tGknL/7oGM+4Y2DLyy2KYFc6HQ==", "dev": true, "license": "MIT", "dependencies": { "@jest/transform": "^29.3.1", "@mdx-js/react": "^2.1.5", - "@storybook/blocks": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/components": "7.6.10", - "@storybook/csf-plugin": "7.6.10", - "@storybook/csf-tools": "7.6.10", + "@storybook/blocks": "7.6.14", + "@storybook/client-logger": "7.6.14", + "@storybook/components": "7.6.14", + "@storybook/csf-plugin": "7.6.14", + "@storybook/csf-tools": "7.6.14", "@storybook/global": "^5.0.0", "@storybook/mdx2-csf": "^1.0.0", - "@storybook/node-logger": "7.6.10", - "@storybook/postinstall": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/react-dom-shim": "7.6.10", - "@storybook/theming": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/node-logger": "7.6.14", + "@storybook/postinstall": "7.6.14", + "@storybook/preview-api": "7.6.14", + "@storybook/react-dom-shim": "7.6.14", + "@storybook/theming": "7.6.14", + "@storybook/types": "7.6.14", "fs-extra": "^11.1.0", "remark-external-links": "^8.0.0", "remark-slug": "^6.0.0", @@ -12287,25 +12683,25 @@ } }, "node_modules/@storybook/addon-essentials": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-essentials/-/addon-essentials-7.6.10.tgz", - "integrity": "sha512-cjbuCCK/3dtUity0Uqi5LwbkgfxqCCE5x5mXZIk9lTMeDz5vB9q6M5nzncVDy8F8przF3NbDLLgxKlt8wjiICg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@storybook/addon-actions": "7.6.10", - "@storybook/addon-backgrounds": "7.6.10", - "@storybook/addon-controls": "7.6.10", - "@storybook/addon-docs": "7.6.10", - "@storybook/addon-highlight": "7.6.10", - "@storybook/addon-measure": "7.6.10", - "@storybook/addon-outline": "7.6.10", - "@storybook/addon-toolbars": "7.6.10", - "@storybook/addon-viewport": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/manager-api": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/preview-api": "7.6.10", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-essentials/-/addon-essentials-7.6.14.tgz", + "integrity": "sha512-1CcpLvzmvXyRhxbc2FgVbchpu7EMEeAjNY2lQ8ejn4cwLuIeWvYI61Cq4swiEmcEOEzi9Uvrq9q1bua9N1fPqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/addon-actions": "7.6.14", + "@storybook/addon-backgrounds": "7.6.14", + "@storybook/addon-controls": "7.6.14", + "@storybook/addon-docs": "7.6.14", + "@storybook/addon-highlight": "7.6.14", + "@storybook/addon-measure": "7.6.14", + "@storybook/addon-outline": "7.6.14", + "@storybook/addon-toolbars": "7.6.14", + "@storybook/addon-viewport": "7.6.14", + "@storybook/core-common": "7.6.14", + "@storybook/manager-api": "7.6.14", + "@storybook/node-logger": "7.6.14", + "@storybook/preview-api": "7.6.14", "ts-dedent": "^2.0.0" }, "funding": { @@ -12318,9 +12714,9 @@ } }, "node_modules/@storybook/addon-highlight": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-highlight/-/addon-highlight-7.6.10.tgz", - "integrity": "sha512-dIuS5QmoT1R+gFOcf6CoBa6D9UR5/wHCfPqPRH8dNNcCLtIGSHWQ4v964mS5OCq1Huj7CghmR15lOUk7SaYwUA==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-highlight/-/addon-highlight-7.6.14.tgz", + "integrity": "sha512-VQTgLm6jPKN7DOhrx0mY5yrhQxOiidQt4yoazJTgzn+aV7zBFKn+GtF1W38QrnFtq5Mr8VJsEByEdtVCqMcmyw==", "dev": true, "license": "MIT", "dependencies": { @@ -12332,9 +12728,9 @@ } }, "node_modules/@storybook/addon-measure": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-measure/-/addon-measure-7.6.10.tgz", - "integrity": "sha512-OVfTI56+kc4hLWfZ/YPV3WKj/aA9e4iKXYxZyPdhfX4Z8TgZdD1wv9Z6e8DKS0H5kuybYrHKHaID5ki6t7qz3w==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-measure/-/addon-measure-7.6.14.tgz", + "integrity": "sha512-bRy3SEv4uf1csDe5H8Lg3wUDg1uMZo6/j2FwNjvUmW+vcasj3VsqPKQjT6KO+LjCXsQ1pIAHu1HcUh2v/Qoitw==", "dev": true, "license": "MIT", "dependencies": { @@ -12347,9 +12743,9 @@ } }, "node_modules/@storybook/addon-outline": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-outline/-/addon-outline-7.6.10.tgz", - "integrity": "sha512-RVJrEoPArhI6zAIMNl1Gz0zrj84BTfEWYYz0yDWOTVgvN411ugsoIk1hw0671MOneXJ2RcQ9MFIeV/v6AVDQYg==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-outline/-/addon-outline-7.6.14.tgz", + "integrity": "sha512-RH3arZYMBBxoqif4pnKN8m8Vt8setpeh0kz6oA+Ilhf/Z8Wz5jWiYDvTL5WW3+E+XGLrIFwH87wmJLN0egKqtA==", "dev": true, "license": "MIT", "dependencies": { @@ -12362,9 +12758,9 @@ } }, "node_modules/@storybook/addon-toolbars": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-toolbars/-/addon-toolbars-7.6.10.tgz", - "integrity": "sha512-PaXY/oj9yxF7/H0CNdQKcioincyCkfeHpISZriZbZqhyqsjn3vca7RFEmsB88Q+ou6rMeqyA9st+6e2cx/Ct6A==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-toolbars/-/addon-toolbars-7.6.14.tgz", + "integrity": "sha512-/Zea9XgmxJp/5pQ+PKw+FGj2s2POIur/9uCUmLBWPDAMIW+kugOYZ/i8krrcHDPJ7nG2rtUJbeSliod9h2tpfw==", "dev": true, "license": "MIT", "funding": { @@ -12373,9 +12769,9 @@ } }, "node_modules/@storybook/addon-viewport": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-viewport/-/addon-viewport-7.6.10.tgz", - "integrity": "sha512-+bA6juC/lH4vEhk+w0rXakaG8JgLG4MOYrIudk5vJKQaC6X58LIM9N4kzIS2KSExRhkExXBPrWsnMfCo7uxmKg==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/addon-viewport/-/addon-viewport-7.6.14.tgz", + "integrity": "sha512-7GbJyXFP3QCZezUQ+75VdjBpyXWutdFY0YMM/3JTjU+Khutbph3RurMTi4dRiBndAIPXlReNm1AnnYX5w+jd9w==", "dev": true, "license": "MIT", "dependencies": { @@ -12387,25 +12783,25 @@ } }, "node_modules/@storybook/angular": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/angular/-/angular-7.6.10.tgz", - "integrity": "sha512-oaSYV3j5hutC0YwSI4M/iIQ7BikfMGjyXW10DAm+Acs9uo99op5GQ4LKSP7CVQAaCBg/DkcUst0Z6uPTfwLfoQ==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/angular/-/angular-7.6.14.tgz", + "integrity": "sha512-bNp7KJVCwLGtNpxT+6yFFbznxuoSu/bvJVNOCH2Su6toHSg5qL7p0QlQYqLY/hMihwZrkHbbPIfrOcaML/5i4A==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/builder-webpack5": "7.6.10", - "@storybook/cli": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/core-server": "7.6.10", - "@storybook/core-webpack": "7.6.10", - "@storybook/docs-tools": "7.6.10", + "@storybook/builder-webpack5": "7.6.14", + "@storybook/cli": "7.6.14", + "@storybook/client-logger": "7.6.14", + "@storybook/core-common": "7.6.14", + "@storybook/core-events": "7.6.14", + "@storybook/core-server": "7.6.14", + "@storybook/core-webpack": "7.6.14", + "@storybook/docs-tools": "7.6.14", "@storybook/global": "^5.0.0", - "@storybook/node-logger": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/telemetry": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/node-logger": "7.6.14", + "@storybook/preview-api": "7.6.14", + "@storybook/telemetry": "7.6.14", + "@storybook/types": "7.6.14", "@types/node": "^18.0.0", "@types/react": "^16.14.34", "@types/react-dom": "^16.9.14", @@ -12617,23 +13013,23 @@ } }, "node_modules/@storybook/blocks": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/blocks/-/blocks-7.6.10.tgz", - "integrity": "sha512-oSIukGC3yuF8pojABC/HLu5tv2axZvf60TaUs8eDg7+NiiKhzYSPoMQxs5uMrKngl+EJDB92ESgWT9vvsfvIPg==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/blocks/-/blocks-7.6.14.tgz", + "integrity": "sha512-DZOSEWSNptAhaeNiOG0BqidJxqi/KaAZ2ZnlygpswDDT9vOCGoc7edZEgrq/i83M55KZFD4IXVLYFdfpjRcirQ==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/components": "7.6.10", - "@storybook/core-events": "7.6.10", + "@storybook/channels": "7.6.14", + "@storybook/client-logger": "7.6.14", + "@storybook/components": "7.6.14", + "@storybook/core-events": "7.6.14", "@storybook/csf": "^0.1.2", - "@storybook/docs-tools": "7.6.10", + "@storybook/docs-tools": "7.6.14", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/theming": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/manager-api": "7.6.14", + "@storybook/preview-api": "7.6.14", + "@storybook/theming": "7.6.14", + "@storybook/types": "7.6.14", "@types/lodash": "^4.14.167", "color-convert": "^2.0.1", "dequal": "^2.0.2", @@ -12677,16 +13073,16 @@ "license": "MIT" }, "node_modules/@storybook/builder-manager": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/builder-manager/-/builder-manager-7.6.10.tgz", - "integrity": "sha512-f+YrjZwohGzvfDtH8BHzqM3xW0p4vjjg9u7uzRorqUiNIAAKHpfNrZ/WvwPlPYmrpAHt4xX/nXRJae4rFSygPw==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/builder-manager/-/builder-manager-7.6.14.tgz", + "integrity": "sha512-pID/g2Bnr3tjmkh8c+O6TZei3f1TWHW/UWi/skNQ3wGJ+9dqJIK2vQY5SwnXBWkmJdUqGVXaW5BvzR8jjfpTxQ==", "dev": true, "license": "MIT", "dependencies": { "@fal-works/esbuild-plugin-global-externals": "^2.1.2", - "@storybook/core-common": "7.6.10", - "@storybook/manager": "7.6.10", - "@storybook/node-logger": "7.6.10", + "@storybook/core-common": "7.6.14", + "@storybook/manager": "7.6.14", + "@storybook/node-logger": "7.6.14", "@types/ejs": "^3.1.1", "@types/find-cache-dir": "^3.2.1", "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", @@ -12705,74 +13101,6 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@storybook/builder-manager/node_modules/@esbuild/darwin-x64": { "version": "0.18.20", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", @@ -12790,295 +13118,6 @@ "node": ">=12" } }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/builder-manager/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@storybook/builder-manager/node_modules/esbuild": { "version": "0.18.20", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/esbuild/-/esbuild-0.18.20.tgz", @@ -13132,21 +13171,21 @@ } }, "node_modules/@storybook/builder-webpack5": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/builder-webpack5/-/builder-webpack5-7.6.10.tgz", - "integrity": "sha512-ja47rdy75tAs37T+JLSqgUGJiba+74zM/8IpEZAzgJmGxLetnHuCWEDskZWh3NXemxYS2uCvsg5rNc+dL9z4RA==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/builder-webpack5/-/builder-webpack5-7.6.14.tgz", + "integrity": "sha512-J5kwNDB/osGiv40hDXKrFNasu8GpXp1tGZa2RLFEeHncrbf+wDpWyr188+bviS2gnw9OtxWI7krFGoUoNdjWDg==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.23.2", - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/core-webpack": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/preview": "7.6.10", - "@storybook/preview-api": "7.6.10", + "@storybook/channels": "7.6.14", + "@storybook/client-logger": "7.6.14", + "@storybook/core-common": "7.6.14", + "@storybook/core-events": "7.6.14", + "@storybook/core-webpack": "7.6.14", + "@storybook/node-logger": "7.6.14", + "@storybook/preview": "7.6.14", + "@storybook/preview-api": "7.6.14", "@swc/core": "^1.3.82", "@types/node": "^18.0.0", "@types/semver": "^7.3.4", @@ -13346,9 +13385,9 @@ "license": "MIT" }, "node_modules/@storybook/builder-webpack5/node_modules/magic-string": { - "version": "0.30.5", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "version": "0.30.7", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/magic-string/-/magic-string-0.30.7.tgz", + "integrity": "sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==", "dev": true, "license": "MIT", "dependencies": { @@ -13412,14 +13451,14 @@ } }, "node_modules/@storybook/channels": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/channels/-/channels-7.6.10.tgz", - "integrity": "sha512-ITCLhFuDBKgxetuKnWwYqMUWlU7zsfH3gEKZltTb+9/2OAWR7ez0iqU7H6bXP1ridm0DCKkt2UMWj2mmr9iQqg==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/channels/-/channels-7.6.14.tgz", + "integrity": "sha512-tyrnnXTh7Ca6HbtzYtZGZmbUkC+eYPdot41+YDERMxXCnejd18BnsH/pyGW66GwgY079Q7uhdDFyM63ynZrt/A==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", + "@storybook/client-logger": "7.6.14", + "@storybook/core-events": "7.6.14", "@storybook/global": "^5.0.0", "qs": "^6.10.0", "telejson": "^7.2.0", @@ -13431,9 +13470,9 @@ } }, "node_modules/@storybook/cli": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/cli/-/cli-7.6.10.tgz", - "integrity": "sha512-pK1MEseMm73OMO2OVoSz79QWX8ymxgIGM8IeZTCo9gImiVRChMNDFYcv8yPWkjuyesY8c15CoO48aR7pdA1OjQ==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/cli/-/cli-7.6.14.tgz", + "integrity": "sha512-2xqcGRPtj/OE+9ro92C5MFCT8VHdMCDDuZZRnmgPi83iqSZtYbO8xHZwz78j4TvmouHstOV1SedeWv0IsFIxLw==", "dev": true, "license": "MIT", "dependencies": { @@ -13441,14 +13480,14 @@ "@babel/preset-env": "^7.23.2", "@babel/types": "^7.23.0", "@ndelangen/get-tarball": "^3.0.7", - "@storybook/codemod": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/core-events": "7.6.10", - "@storybook/core-server": "7.6.10", - "@storybook/csf-tools": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/telemetry": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/codemod": "7.6.14", + "@storybook/core-common": "7.6.14", + "@storybook/core-events": "7.6.14", + "@storybook/core-server": "7.6.14", + "@storybook/csf-tools": "7.6.14", + "@storybook/node-logger": "7.6.14", + "@storybook/telemetry": "7.6.14", + "@storybook/types": "7.6.14", "@types/semver": "^7.3.4", "@yarnpkg/fslib": "2.10.3", "@yarnpkg/libzip": "2.3.0", @@ -13676,9 +13715,9 @@ } }, "node_modules/@storybook/client-logger": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/client-logger/-/client-logger-7.6.10.tgz", - "integrity": "sha512-U7bbpu21ntgePMz/mKM18qvCSWCUGCUlYru8mgVlXLCKqFqfTeP887+CsPEQf29aoE3cLgDrxqbRJ1wxX9kL9A==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/client-logger/-/client-logger-7.6.14.tgz", + "integrity": "sha512-rHa2hLU+80BN5E58Shf1g09YS6QEEOk5hwMuJ4WJfAypMDYPjnIsOYUboHClkCA9TDCH/iVhyRSPy83NWN2MZg==", "dev": true, "license": "MIT", "dependencies": { @@ -13690,9 +13729,9 @@ } }, "node_modules/@storybook/codemod": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/codemod/-/codemod-7.6.10.tgz", - "integrity": "sha512-pzFR0nocBb94vN9QCJLC3C3dP734ZigqyPmd0ZCDj9Xce2ytfHK3v1lKB6TZWzKAZT8zztauECYxrbo4LVuagw==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/codemod/-/codemod-7.6.14.tgz", + "integrity": "sha512-Sq/Q12KmvzaSUtmbtD26cEEGVmZLUA+iiNHbl0n65MMka6QBGG/VgSPvSgu+GEpKowbVoqfMpH4Ic16A6XsNFg==", "dev": true, "license": "MIT", "dependencies": { @@ -13700,9 +13739,9 @@ "@babel/preset-env": "^7.23.2", "@babel/types": "^7.23.0", "@storybook/csf": "^0.1.2", - "@storybook/csf-tools": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/csf-tools": "7.6.14", + "@storybook/node-logger": "7.6.14", + "@storybook/types": "7.6.14", "@types/cross-spawn": "^6.0.2", "cross-spawn": "^7.0.3", "globby": "^11.0.2", @@ -13733,19 +13772,19 @@ } }, "node_modules/@storybook/components": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/components/-/components-7.6.10.tgz", - "integrity": "sha512-H5hF8pxwtbt0LxV24KMMsPlbYG9Oiui3ObvAQkvGu6q62EYxRPeNSrq3GBI5XEbI33OJY9bT24cVaZx18dXqwQ==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/components/-/components-7.6.14.tgz", + "integrity": "sha512-kukLj6B2xaIbKAq8E2WUcU0KZ+keuvIo0VcfrtSNHFbNvrNzHshajPC1dTO4NbgI3ey2SmD0rp71eh06TUQ9ng==", "dev": true, "license": "MIT", "dependencies": { "@radix-ui/react-select": "^1.2.2", "@radix-ui/react-toolbar": "^1.0.4", - "@storybook/client-logger": "7.6.10", + "@storybook/client-logger": "7.6.14", "@storybook/csf": "^0.1.2", "@storybook/global": "^5.0.0", - "@storybook/theming": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/theming": "7.6.14", + "@storybook/types": "7.6.14", "memoizerific": "^1.11.3", "use-resize-observer": "^9.1.0", "util-deprecate": "^1.0.2" @@ -13760,15 +13799,15 @@ } }, "node_modules/@storybook/core-common": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/core-common/-/core-common-7.6.10.tgz", - "integrity": "sha512-K3YWqjCKMnpvYsWNjOciwTH6zWbuuZzmOiipziZaVJ+sB1XYmH52Y3WGEm07TZI8AYK9DRgwA13dR/7W0nw72Q==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/core-common/-/core-common-7.6.14.tgz", + "integrity": "sha512-0CIfwdjY5+OO6B+WxeCx3fZou1wk50RU9hFOMGwJ2yj/5ilV06xVHt0HNrA2x37zaK7r370PjOuny0Xudba03g==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/core-events": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/core-events": "7.6.14", + "@storybook/node-logger": "7.6.14", + "@storybook/types": "7.6.14", "@types/find-cache-dir": "^3.2.1", "@types/node": "^18.0.0", "@types/node-fetch": "^2.6.4", @@ -13795,74 +13834,6 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/core-common/node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@storybook/core-common/node_modules/@esbuild/darwin-x64": { "version": "0.18.20", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", @@ -13880,295 +13851,6 @@ "node": ">=12" } }, - "node_modules/@storybook/core-common/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@storybook/core-common/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@storybook/core-common/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -14395,9 +14077,9 @@ } }, "node_modules/@storybook/core-events": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/core-events/-/core-events-7.6.10.tgz", - "integrity": "sha512-yccDH67KoROrdZbRKwxgTswFMAco5nlCyxszCDASCLygGSV2Q2e+YuywrhchQl3U6joiWi3Ps1qWu56NeNafag==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/core-events/-/core-events-7.6.14.tgz", + "integrity": "sha512-zuSMjOgju7WLFL+okTXVvOKKNzwqVGRVp5UhXeSikT4aXuVdpfepCfikkjntn12G1ybL7mfFCsBU2DV1lwwp6Q==", "dev": true, "license": "MIT", "dependencies": { @@ -14409,27 +14091,27 @@ } }, "node_modules/@storybook/core-server": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/core-server/-/core-server-7.6.10.tgz", - "integrity": "sha512-2icnqJkn3vwq0eJPP0rNaHd7IOvxYf5q4lSVl2AWTxo/Ae19KhokI6j/2vvS2XQJMGQszwshlIwrZUNsj5p0yw==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/core-server/-/core-server-7.6.14.tgz", + "integrity": "sha512-OSUunvjXyUiyfGet8ZBz7/Lka6dSgbbVMH7lU6wELIYCd2ZUxU5HQMl9JPesl61wWB4L3JaWFAoMRaCVI7q0xQ==", "dev": true, "license": "MIT", "dependencies": { "@aw-web-design/x-default-browser": "1.4.126", "@discoveryjs/json-ext": "^0.5.3", - "@storybook/builder-manager": "7.6.10", - "@storybook/channels": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/core-events": "7.6.10", + "@storybook/builder-manager": "7.6.14", + "@storybook/channels": "7.6.14", + "@storybook/core-common": "7.6.14", + "@storybook/core-events": "7.6.14", "@storybook/csf": "^0.1.2", - "@storybook/csf-tools": "7.6.10", + "@storybook/csf-tools": "7.6.14", "@storybook/docs-mdx": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/manager": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/telemetry": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/manager": "7.6.14", + "@storybook/node-logger": "7.6.14", + "@storybook/preview-api": "7.6.14", + "@storybook/telemetry": "7.6.14", + "@storybook/types": "7.6.14", "@types/detect-port": "^1.3.0", "@types/node": "^18.0.0", "@types/pretty-hrtime": "^1.0.0", @@ -14575,15 +14257,15 @@ } }, "node_modules/@storybook/core-webpack": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/core-webpack/-/core-webpack-7.6.10.tgz", - "integrity": "sha512-+GiCRp+2Hw0NO3NYRKamG/U5SyOQ8tOfRUxuAqWI7nduXwB3WWdjji3/ofjqOm/ryKesuQFtfhozaczvBJBvng==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/core-webpack/-/core-webpack-7.6.14.tgz", + "integrity": "sha512-aKykzFPHai9Tq9625PTftmg0sgdqU5VcY0ezBiT/MSrNr9aLORIXwIh7q4Xrx0ItwtnLBxvO9UZLy55CXeQkfg==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/core-common": "7.6.10", - "@storybook/node-logger": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/core-common": "7.6.14", + "@storybook/node-logger": "7.6.14", + "@storybook/types": "7.6.14", "@types/node": "^18.0.0", "ts-dedent": "^2.0.0" }, @@ -14603,13 +14285,13 @@ } }, "node_modules/@storybook/csf-plugin": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/csf-plugin/-/csf-plugin-7.6.10.tgz", - "integrity": "sha512-Sc+zZg/BnPH2X28tthNaQBnDiFfO0QmfjVoOx0fGYM9SvY3P5ehzWwp5hMRBim6a/twOTzePADtqYL+t6GMqqg==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/csf-plugin/-/csf-plugin-7.6.14.tgz", + "integrity": "sha512-TYmtuLCzdWGy4/T6KYUBGdzRy/4cJzDQrDzWRWD7a+xcy1Z7wlKkXw+zWfxbNheEnxb146q5lIkRpvhevKgpGA==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/csf-tools": "7.6.10", + "@storybook/csf-tools": "7.6.14", "unplugin": "^1.3.1" }, "funding": { @@ -14618,9 +14300,9 @@ } }, "node_modules/@storybook/csf-tools": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/csf-tools/-/csf-tools-7.6.10.tgz", - "integrity": "sha512-TnDNAwIALcN6SA4l00Cb67G02XMOrYU38bIpFJk5VMDX2dvgPjUtJNBuLmEbybGcOt7nPyyFIHzKcY5FCVGoWA==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/csf-tools/-/csf-tools-7.6.14.tgz", + "integrity": "sha512-s7XFIi823HhcKxTqHY/uU1QZCujLBjFt6OJa5y3XvwIMoLJWZtuT1PF/QPR0K7iYb9gQnGHwO9lZBfMraUywrQ==", "dev": true, "license": "MIT", "dependencies": { @@ -14629,7 +14311,7 @@ "@babel/traverse": "^7.23.2", "@babel/types": "^7.23.0", "@storybook/csf": "^0.1.2", - "@storybook/types": "7.6.10", + "@storybook/types": "7.6.14", "fs-extra": "^11.1.0", "recast": "^0.23.1", "ts-dedent": "^2.0.0" @@ -14676,15 +14358,15 @@ "license": "MIT" }, "node_modules/@storybook/docs-tools": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/docs-tools/-/docs-tools-7.6.10.tgz", - "integrity": "sha512-UgbikducoXzqQHf2TozO0f2rshaeBNnShVbL5Ai4oW7pDymBmrfzdjGbF/milO7yxNKcoIByeoNmu384eBamgQ==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/docs-tools/-/docs-tools-7.6.14.tgz", + "integrity": "sha512-8FCuVnty2d74cgF+qjhI/LTbGlf3mvu1OkKpLMp9xqouPy3X+yo9N8mpe2tIhgpRMTDzDScIeIBUpLrIpjHaXA==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/core-common": "7.6.10", - "@storybook/preview-api": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/core-common": "7.6.14", + "@storybook/preview-api": "7.6.14", + "@storybook/types": "7.6.14", "@types/doctrine": "^0.0.3", "assert": "^2.1.0", "doctrine": "^3.0.0", @@ -14731,9 +14413,9 @@ "license": "MIT" }, "node_modules/@storybook/manager": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/manager/-/manager-7.6.10.tgz", - "integrity": "sha512-Co3sLCbNYY6O4iH2ggmRDLCPWLj03JE5s/DOG8OVoXc6vBwTc/Qgiyrsxxp6BHQnPpM0mxL6aKAxE3UjsW/Nog==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/manager/-/manager-7.6.14.tgz", + "integrity": "sha512-lgowunC/pm2y6d+3j7UJ/CkHpWC0o+nZ9b7mDbkJ6PmezW5Hpy83kbeCxbwRGosYoPQ0izBzVB5ZqGgKrNNDjA==", "dev": true, "license": "MIT", "funding": { @@ -14742,20 +14424,20 @@ } }, "node_modules/@storybook/manager-api": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/manager-api/-/manager-api-7.6.10.tgz", - "integrity": "sha512-8eGVpRlpunuFScDtc7nxpPJf/4kJBAAZlNdlhmX09j8M3voX6GpcxabBamSEX5pXZqhwxQCshD4IbqBmjvadlw==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/manager-api/-/manager-api-7.6.14.tgz", + "integrity": "sha512-kZbcudrpQaYgUCrnBumDBPOvaEcvFBrZjM5v3AvMenVMXTjwlAHF8mZswE/ptpDsico2iSN96nMhd97OyaAuqA==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", + "@storybook/channels": "7.6.14", + "@storybook/client-logger": "7.6.14", + "@storybook/core-events": "7.6.14", "@storybook/csf": "^0.1.2", "@storybook/global": "^5.0.0", - "@storybook/router": "7.6.10", - "@storybook/theming": "7.6.10", - "@storybook/types": "7.6.10", + "@storybook/router": "7.6.14", + "@storybook/theming": "7.6.14", + "@storybook/types": "7.6.14", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", @@ -14776,9 +14458,9 @@ "license": "MIT" }, "node_modules/@storybook/node-logger": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/node-logger/-/node-logger-7.6.10.tgz", - "integrity": "sha512-ZBuqrv4bjJzKXyfRGFkVIi+z6ekn6rOPoQao4KmsfLNQAUUsEdR8Baw/zMnnU417zw5dSEaZdpuwx75SCQAeOA==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/node-logger/-/node-logger-7.6.14.tgz", + "integrity": "sha512-prKUMGxGzeX3epdlin1UU6M1//CoAJM1GrffrFeNntnPr3h6GMTgxNzl85flUhWd4ky/wjC/36dGOI8QRYVtoA==", "dev": true, "license": "MIT", "funding": { @@ -14787,9 +14469,9 @@ } }, "node_modules/@storybook/postinstall": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/postinstall/-/postinstall-7.6.10.tgz", - "integrity": "sha512-SMdXtednPCy3+SRJ7oN1OPN1oVFhj3ih+ChOEX8/kZ5J3nfmV3wLPtsZvFGUCf0KWQEP1xL+1Urv48mzMKcV/w==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/postinstall/-/postinstall-7.6.14.tgz", + "integrity": "sha512-ya3e5jvW1eSw4l3lhiGH2g+Gk8py2Tr3PW5ecnH/x1rD8Tt43OHXRQqiFfl7QzOudHxQGKQsO3lhWe8FJXvdbA==", "dev": true, "license": "MIT", "funding": { @@ -14798,9 +14480,9 @@ } }, "node_modules/@storybook/preview": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/preview/-/preview-7.6.10.tgz", - "integrity": "sha512-F07BzVXTD3byq+KTWtvsw3pUu3fQbyiBNLFr2CnfU4XSdLKja5lDt8VqDQq70TayVQOf5qfUTzRd4M6pQkjw1w==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/preview/-/preview-7.6.14.tgz", + "integrity": "sha512-6Y873pNsJBQuCeR3YDMlRgRW+4Tf+Rj4VdujjvRw/H7ES1+pO8qgcI3VJCcoxqDY9ZNPT/riLh8YOddpLNCgNg==", "dev": true, "license": "MIT", "funding": { @@ -14809,18 +14491,18 @@ } }, "node_modules/@storybook/preview-api": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/preview-api/-/preview-api-7.6.10.tgz", - "integrity": "sha512-5A3etoIwZCx05yuv3KSTv1wynN4SR4rrzaIs/CTBp3BC4q1RBL+Or/tClk0IJPXQMlx/4Y134GtNIBbkiDofpw==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/preview-api/-/preview-api-7.6.14.tgz", + "integrity": "sha512-CnUEkTUK3ei3vw4Ypa9EOxEO9lCKc3HvVHxXu4z6Caoe/hRUc10Q6Nj1A7brqok1QLZ304qc715XdYFMahDhyA==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/channels": "7.6.10", - "@storybook/client-logger": "7.6.10", - "@storybook/core-events": "7.6.10", + "@storybook/channels": "7.6.14", + "@storybook/client-logger": "7.6.14", + "@storybook/core-events": "7.6.14", "@storybook/csf": "^0.1.2", "@storybook/global": "^5.0.0", - "@storybook/types": "7.6.10", + "@storybook/types": "7.6.14", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", @@ -14836,9 +14518,9 @@ } }, "node_modules/@storybook/react-dom-shim": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/react-dom-shim/-/react-dom-shim-7.6.10.tgz", - "integrity": "sha512-M+N/h6ximacaFdIDjMN2waNoWwApeVYTpFeoDppiFTvdBTXChyIuiPgYX9QSg7gDz92OaA52myGOot4wGvXVzg==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/react-dom-shim/-/react-dom-shim-7.6.14.tgz", + "integrity": "sha512-Ldmc2tKj1N3vNYZpI791xgTbk0XdqJDm1a09fSRM4CeBu4BI7M9IjnNS4cHNdTeqtK9MbCSzCr1nxfxNCtrtiA==", "dev": true, "license": "MIT", "funding": { @@ -14851,13 +14533,13 @@ } }, "node_modules/@storybook/router": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/router/-/router-7.6.10.tgz", - "integrity": "sha512-G/H4Jn2+y8PDe8Zbq4DVxF/TPn0/goSItdILts39JENucHiuGBCjKjSWGBe1rkwKi1tUbB3yhxJVrLagxFEPpQ==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/router/-/router-7.6.14.tgz", + "integrity": "sha512-eVD7jVZeM8mppEtHsvkKIEN92stsdbiXDHG49iNVnw+ojOSjJ1HR8+Pm8wy5Cc2pcyoZEHeU356kaP9gXOhuOQ==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/client-logger": "7.6.10", + "@storybook/client-logger": "7.6.14", "memoizerific": "^1.11.3", "qs": "^6.10.0" }, @@ -14867,15 +14549,15 @@ } }, "node_modules/@storybook/telemetry": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/telemetry/-/telemetry-7.6.10.tgz", - "integrity": "sha512-p3mOSUtIyy2tF1z6pQXxNh1JzYFcAm97nUgkwLzF07GfEdVAPM+ftRSLFbD93zVvLEkmLTlsTiiKaDvOY/lQWg==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/telemetry/-/telemetry-7.6.14.tgz", + "integrity": "sha512-F+a9Q4dHCpuBLQmB05DOLosU8p1Otj3Vd+/5EF9QUFSn4C64z1gmMc3jzF3iUgktY53HdoUqR871w3GoOJ7g9A==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/client-logger": "7.6.10", - "@storybook/core-common": "7.6.10", - "@storybook/csf-tools": "7.6.10", + "@storybook/client-logger": "7.6.14", + "@storybook/core-common": "7.6.14", + "@storybook/csf-tools": "7.6.14", "chalk": "^4.1.0", "detect-package-manager": "^2.0.1", "fetch-retry": "^5.0.2", @@ -14964,14 +14646,14 @@ } }, "node_modules/@storybook/theming": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/theming/-/theming-7.6.10.tgz", - "integrity": "sha512-f5tuy7yV3TOP3fIboSqpgLHy0wKayAw/M8HxX0jVET4Z4fWlFK0BiHJabQ+XEdAfQM97XhPFHB2IPbwsqhCEcQ==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/theming/-/theming-7.6.14.tgz", + "integrity": "sha512-jpryYjBAGLkFauSyNEoflSfYqO3srn98llNxhgxpc1P1ocmOzeDwdg7PUWDI9DCuJC+OWaXa1zzLO6uRLyEJAQ==", "dev": true, "license": "MIT", "dependencies": { "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@storybook/client-logger": "7.6.10", + "@storybook/client-logger": "7.6.14", "@storybook/global": "^5.0.0", "memoizerific": "^1.11.3" }, @@ -14985,13 +14667,13 @@ } }, "node_modules/@storybook/types": { - "version": "7.6.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/types/-/types-7.6.10.tgz", - "integrity": "sha512-hcS2HloJblaMpCAj2axgGV+53kgSRYPT0a1PG1IHsZaYQILfHSMmBqM8XzXXYTsgf9250kz3dqFX1l0n3EqMlQ==", + "version": "7.6.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@storybook/types/-/types-7.6.14.tgz", + "integrity": "sha512-sJ3qn45M2XLXlOi+wkhXK5xsXbSVzi8YGrusux//DttI3s8wCP3BQSnEgZkBiEktloxPferINHT1er8/9UK7Xw==", "dev": true, "license": "MIT", "dependencies": { - "@storybook/channels": "7.6.10", + "@storybook/channels": "7.6.14", "@types/babel__core": "^7.0.0", "@types/express": "^4.7.0", "file-system-cache": "2.3.0" @@ -15002,9 +14684,9 @@ } }, "node_modules/@swc-node/core": { - "version": "1.10.6", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc-node/core/-/core-1.10.6.tgz", - "integrity": "sha512-lDIi/rPosmKIknWzvs2/Fi9zWRtbkx8OJ9pQaevhsoGzJSal8Pd315k1W5AIrnknfdAB4HqRN12fk6AhqnrEEw==", + "version": "1.12.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc-node/core/-/core-1.12.0.tgz", + "integrity": "sha512-AYrEmPL2BT46wbikHwSMR5IK98SelBEYH+ycjalUxJ5xYjEupjF8Fd+NkadKoZAzf5zDtysFKd5R1PY4QBHIiw==", "devOptional": true, "license": "MIT", "engines": { @@ -15015,7 +14697,8 @@ "url": "https://github.com/sponsors/Brooooooklyn" }, "peerDependencies": { - "@swc/core": ">= 1.3" + "@swc/core": ">= 1.3", + "@swc/types": ">= 0.1" } }, "node_modules/@swc-node/register": { @@ -15053,9 +14736,9 @@ } }, "node_modules/@swc/core": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core/-/core-1.3.106.tgz", - "integrity": "sha512-++QPSPkFq2qELYVScxNHJC42hKQChjiTWS2P0QQ5JWT4NHb9lmNSfrc1ylFIyImwRnxsW2MTBALLYLf95EFAsg==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core/-/core-1.3.107.tgz", + "integrity": "sha512-zKhqDyFcTsyLIYK1iEmavljZnf4CCor5pF52UzLAz4B6Nu/4GLU+2LQVAf+oRHjusG39PTPjd2AlRT3f3QWfsQ==", "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -15071,16 +14754,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.3.106", - "@swc/core-darwin-x64": "1.3.106", - "@swc/core-linux-arm-gnueabihf": "1.3.106", - "@swc/core-linux-arm64-gnu": "1.3.106", - "@swc/core-linux-arm64-musl": "1.3.106", - "@swc/core-linux-x64-gnu": "1.3.106", - "@swc/core-linux-x64-musl": "1.3.106", - "@swc/core-win32-arm64-msvc": "1.3.106", - "@swc/core-win32-ia32-msvc": "1.3.106", - "@swc/core-win32-x64-msvc": "1.3.106" + "@swc/core-darwin-arm64": "1.3.107", + "@swc/core-darwin-x64": "1.3.107", + "@swc/core-linux-arm-gnueabihf": "1.3.107", + "@swc/core-linux-arm64-gnu": "1.3.107", + "@swc/core-linux-arm64-musl": "1.3.107", + "@swc/core-linux-x64-gnu": "1.3.107", + "@swc/core-linux-x64-musl": "1.3.107", + "@swc/core-win32-arm64-msvc": "1.3.107", + "@swc/core-win32-ia32-msvc": "1.3.107", + "@swc/core-win32-x64-msvc": "1.3.107" }, "peerDependencies": { "@swc/helpers": "^0.5.0" @@ -15092,9 +14775,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.106.tgz", - "integrity": "sha512-XYcbViNyHnnm7RWOAO1YipMmthM7m2aXF32b0y+JMLYFBEyFpjVX9btLkzeL7wRx/5B3I35yJNhE+xyx0Q1Gkw==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.107.tgz", + "integrity": "sha512-47tD/5vSXWxPd0j/ZllyQUg4bqalbQTsmqSw0J4dDdS82MWqCAwUErUrAZPRjBkjNQ6Kmrf5rpCWaGTtPw+ngw==", "cpu": [ "arm64" ], @@ -15108,9 +14791,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-darwin-x64/-/core-darwin-x64-1.3.106.tgz", - "integrity": "sha512-YKDPhUdfuwhmOUS9+CaIwl/0Tp+f1b73BH2EIESuxSNsogZf18a8HQ8O0fQEwdiwmA5LEqw47cj+kfOWV/0+kw==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-darwin-x64/-/core-darwin-x64-1.3.107.tgz", + "integrity": "sha512-hwiLJ2ulNkBGAh1m1eTfeY1417OAYbRGcb/iGsJ+LuVLvKAhU/itzsl535CvcwAlt2LayeCFfcI8gdeOLeZa9A==", "cpu": [ "x64" ], @@ -15124,9 +14807,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.106.tgz", - "integrity": "sha512-bHxxJXogvFfocLL5inZxxtx/x/WgKozigp80Vbx0viac1fPDJrqKBw2X4MzpMiuTRAGVQ03jJI6pDwbSBf+yDw==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.107.tgz", + "integrity": "sha512-I2wzcC0KXqh0OwymCmYwNRgZ9nxX7DWnOOStJXV3pS0uB83TXAkmqd7wvMBuIl9qu4Hfomi9aDM7IlEEn9tumQ==", "cpu": [ "arm" ], @@ -15140,9 +14823,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.106.tgz", - "integrity": "sha512-c7jue++CHLgtpeaakEukoCLT9eNrImizbleE9Y7Is8CHqLq/7DG4s+7ma9DFKXIzW2MpTg9byIEQfpqSphVW6A==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.107.tgz", + "integrity": "sha512-HWgnn7JORYlOYnGsdunpSF8A+BCZKPLzLtEUA27/M/ZuANcMZabKL9Zurt7XQXq888uJFAt98Gy+59PU90aHKg==", "cpu": [ "arm64" ], @@ -15156,9 +14839,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.106.tgz", - "integrity": "sha512-51EaC3Q8qAhLtWVnAVqoYX/gk3tK31cCBzUpwCcmhianhEBM2/WtKRAS4MqPhE8VVZuN3WjO2c2JaF2mX0yuoA==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.107.tgz", + "integrity": "sha512-vfPF74cWfAm8hyhS8yvYI94ucMHIo8xIYU+oFOW9uvDlGQRgnUf/6DEVbLyt/3yfX5723Ln57U8uiMALbX5Pyw==", "cpu": [ "arm64" ], @@ -15172,9 +14855,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.106.tgz", - "integrity": "sha512-tOUi8BB6jAeCXgx7ESLNnX7nrbMVKQ/XajK77v7Ad4SXf9HYArnimBJpXUUyVFJTXLSv4e6c7s6XHHqXb5Lwcg==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.107.tgz", + "integrity": "sha512-uBVNhIg0ip8rH9OnOsCARUFZ3Mq3tbPHxtmWk9uAa5u8jQwGWeBx5+nTHpDOVd3YxKb6+5xDEI/edeeLpha/9g==", "cpu": [ "x64" ], @@ -15188,9 +14871,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.106.tgz", - "integrity": "sha512-binLw4Lbd83NPy4/m/teH2nbaifxveSD+sKDvpxywRbvYW2I0w/iCBpUBcbnl16TQF4TPOGpq5YwG9lVxPVw5g==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.107.tgz", + "integrity": "sha512-mvACkUvzSIB12q1H5JtabWATbk3AG+pQgXEN95AmEX2ZA5gbP9+B+mijsg7Sd/3tboHr7ZHLz/q3SHTvdFJrEw==", "cpu": [ "x64" ], @@ -15204,9 +14887,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.106.tgz", - "integrity": "sha512-n4ttBWr8tM7DPzwcEOIBTyTMHZTzCmbic/HTtxEsPyMAf/Daen+yrTKzjPP6k2usfSrjkxA780RSJJxI1N8r2w==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.107.tgz", + "integrity": "sha512-J3P14Ngy/1qtapzbguEH41kY109t6DFxfbK4Ntz9dOWNuVY3o9/RTB841ctnJk0ZHEG+BjfCJjsD2n8H5HcaOA==", "cpu": [ "arm64" ], @@ -15220,9 +14903,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.106.tgz", - "integrity": "sha512-GhDNIwxE5FhkujESI6h/4ysT3wxwmrzTUlZYaR8rRui6a6SdX9feIPUHPEE5o5hpyp+xqlmvRxKkRxOnwsq8iA==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.107.tgz", + "integrity": "sha512-ZBUtgyjTHlz8TPJh7kfwwwFma+ktr6OccB1oXC8fMSopD0AxVnQasgun3l3099wIsAB9eEsJDQ/3lDkOLs1gBA==", "cpu": [ "ia32" ], @@ -15236,9 +14919,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.3.106", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.106.tgz", - "integrity": "sha512-2M6yWChuMS1+/MPo3Dor0SOMkvmiugonWlzsZBAu/oZboH2xKrHSRv7brsBujb2Oe47r+NsbV+vq9tnnP9Vl1Q==", + "version": "1.3.107", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.107.tgz", + "integrity": "sha512-Eyzo2XRqWOxqhE1gk9h7LWmUf4Bp4Xn2Ttb0ayAXFp6YSTxQIThXcT9kipXZqcpxcmDwoq8iWbbf2P8XL743EA==", "cpu": [ "x64" ], @@ -15252,9 +14935,9 @@ } }, "node_modules/@swc/counter": { - "version": "0.1.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/counter/-/counter-0.1.2.tgz", - "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", + "version": "0.1.3", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", "devOptional": true, "license": "Apache-2.0" }, @@ -15743,9 +15426,9 @@ } }, "node_modules/@types/mdx": { - "version": "2.0.10", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@types/mdx/-/mdx-2.0.10.tgz", - "integrity": "sha512-Rllzc5KHk0Al5/WANwgSPl1/CwjqCy+AZrGd78zuK+jO9aDM6ffblZ+zIjgPNAaEBmlO0RYDvLNh7wD0zKVgEg==", + "version": "2.0.11", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@types/mdx/-/mdx-2.0.11.tgz", + "integrity": "sha512-HM5bwOaIQJIQbAYfax35HCKxx7a3KrK3nBtIqJgSOitivTD1y3oW9P3rxY9RkXYPUk7y/AjAohfHKmFpGE79zw==", "dev": true, "license": "MIT" }, @@ -15837,9 +15520,9 @@ "license": "MIT" }, "node_modules/@types/react": { - "version": "18.2.48", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@types/react/-/react-18.2.48.tgz", - "integrity": "sha512-qboRCl6Ie70DQQG9hhNREz81jqC1cs9EVNcjQ1AU+jH6NFfSAhVVbrrY/+nSF+Bsk4AOwm9Qa61InvMCyV+H3w==", + "version": "18.2.55", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@types/react/-/react-18.2.55.tgz", + "integrity": "sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==", "dev": true, "license": "MIT", "dependencies": { @@ -18033,19 +17716,35 @@ } }, "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.6", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.6.tgz", - "integrity": "sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==", + "version": "0.4.8", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz", + "integrity": "sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==", "license": "MIT", "dependencies": { "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.4.3", + "@babel/helper-define-polyfill-provider": "^0.5.0", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { "version": "6.3.1", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/semver/-/semver-6.3.1.tgz", @@ -18069,12 +17768,28 @@ } }, "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.5.3", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.3.tgz", - "integrity": "sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==", + "version": "0.5.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz", + "integrity": "sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==", "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.4.3" + "@babel/helper-define-polyfill-provider": "^0.5.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.5.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz", + "integrity": "sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" }, "peerDependencies": { "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" @@ -18527,9 +18242,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.22.3", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/browserslist/-/browserslist-4.22.3.tgz", + "integrity": "sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A==", "funding": [ { "type": "opencollective", @@ -18546,9 +18261,9 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001580", + "electron-to-chromium": "^1.4.648", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -18868,9 +18583,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001559", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/caniuse-lite/-/caniuse-lite-1.0.30001559.tgz", - "integrity": "sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==", + "version": "1.0.30001587", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/caniuse-lite/-/caniuse-lite-1.0.30001587.tgz", + "integrity": "sha512-HMFNotUmLXn71BQxg8cijvqxnIAofforZOwGsxyXJ0qugTdspUF4sPSJ2vhgprHCB996tIDzEq1ubumPDV8ULA==", "funding": [ { "type": "opencollective", @@ -19798,12 +19513,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.33.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/core-js-compat/-/core-js-compat-3.33.1.tgz", - "integrity": "sha512-6pYKNOgD/j/bkC5xS5IIg6bncid3rfrI42oBH1SQJbsmYPKF7rhzcFzYCcxYMmNQQ0rCEB8WqpW7QHndOggaeQ==", + "version": "3.35.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/core-js-compat/-/core-js-compat-3.35.1.tgz", + "integrity": "sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==", "license": "MIT", "dependencies": { - "browserslist": "^4.22.1" + "browserslist": "^4.22.2" }, "funding": { "type": "opencollective", @@ -21604,9 +21319,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.574", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/electron-to-chromium/-/electron-to-chromium-1.4.574.tgz", - "integrity": "sha512-bg1m8L0n02xRzx4LsTTMbBPiUd9yIR+74iPtS/Ao65CuXvhVZHP0ym1kSdDG3yHFDXqHQQBKujlN1AQ8qZnyFg==", + "version": "1.4.665", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/electron-to-chromium/-/electron-to-chromium-1.4.665.tgz", + "integrity": "sha512-UpyCWObBoD+nSZgOC2ToaIdZB0r9GhqT2WahPKiSki6ckkSuKhQNso8V2PrFcHBMleI/eqbKgVQgVC4Wni4ilw==", "license": "ISC" }, "node_modules/elliptic": { @@ -21762,9 +21477,9 @@ } }, "node_modules/envinfo": { - "version": "7.11.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/envinfo/-/envinfo-7.11.0.tgz", - "integrity": "sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==", + "version": "7.11.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/envinfo/-/envinfo-7.11.1.tgz", + "integrity": "sha512-8PiZgZNIB4q/Lw4AhOvAfB/ityHAd2bli3lESSWmWSzSsl5dKpy5N1d1Rfkd2teq/g9xN90lc6o98DOjMeYHpg==", "dev": true, "license": "MIT", "bin": { @@ -21900,6 +21615,363 @@ "node": ">=12" } }, + "node_modules/esbuild/node_modules/@esbuild/android-arm": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm/-/android-arm-0.19.5.tgz", + "integrity": "sha512-bhvbzWFF3CwMs5tbjf3ObfGqbl/17ict2/uwOSfr3wmxDE6VdS2GqY/FuzIPe0q0bdhj65zQsvqfArI9MY6+AA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-arm64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm64/-/android-arm64-0.19.5.tgz", + "integrity": "sha512-5d1OkoJxnYQfmC+Zd8NBFjkhyCNYwM4n9ODrycTFY6Jk1IGiZ+tjVJDDSwDt77nK+tfpGP4T50iMtVi4dEGzhQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/android-x64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-x64/-/android-x64-0.19.5.tgz", + "integrity": "sha512-9t+28jHGL7uBdkBjL90QFxe7DVA+KGqWlHCF8ChTKyaKO//VLuoBricQCgwhOjA1/qOczsw843Fy4cbs4H3DVA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/darwin-arm64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/darwin-arm64/-/darwin-arm64-0.19.5.tgz", + "integrity": "sha512-mvXGcKqqIqyKoxq26qEDPHJuBYUA5KizJncKOAf9eJQez+L9O+KfvNFu6nl7SCZ/gFb2QPaRqqmG0doSWlgkqw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/freebsd-arm64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.5.tgz", + "integrity": "sha512-GGDNnPWTmWE+DMchq1W8Sd0mUkL+APvJg3b11klSGUDvRXh70JqLAO56tubmq1s2cgpVCSKYywEiKBfju8JztQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/freebsd-x64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-x64/-/freebsd-x64-0.19.5.tgz", + "integrity": "sha512-1CCwDHnSSoA0HNwdfoNY0jLfJpd7ygaLAp5EHFos3VWJCRX9DMwWODf96s9TSse39Br7oOTLryRVmBoFwXbuuQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-arm": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm/-/linux-arm-0.19.5.tgz", + "integrity": "sha512-lrWXLY/vJBzCPC51QN0HM71uWgIEpGSjSZZADQhq7DKhPcI6NH1IdzjfHkDQws2oNpJKpR13kv7/pFHBbDQDwQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-arm64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm64/-/linux-arm64-0.19.5.tgz", + "integrity": "sha512-o3vYippBmSrjjQUCEEiTZ2l+4yC0pVJD/Dl57WfPwwlvFkrxoSO7rmBZFii6kQB3Wrn/6GwJUPLU5t52eq2meA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-ia32": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ia32/-/linux-ia32-0.19.5.tgz", + "integrity": "sha512-MkjHXS03AXAkNp1KKkhSKPOCYztRtK+KXDNkBa6P78F8Bw0ynknCSClO/ztGszILZtyO/lVKpa7MolbBZ6oJtQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-loong64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-loong64/-/linux-loong64-0.19.5.tgz", + "integrity": "sha512-42GwZMm5oYOD/JHqHska3Jg0r+XFb/fdZRX+WjADm3nLWLcIsN27YKtqxzQmGNJgu0AyXg4HtcSK9HuOk3v1Dw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-mips64el": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-mips64el/-/linux-mips64el-0.19.5.tgz", + "integrity": "sha512-kcjndCSMitUuPJobWCnwQ9lLjiLZUR3QLQmlgaBfMX23UEa7ZOrtufnRds+6WZtIS9HdTXqND4yH8NLoVVIkcg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-ppc64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ppc64/-/linux-ppc64-0.19.5.tgz", + "integrity": "sha512-yJAxJfHVm0ZbsiljbtFFP1BQKLc8kUF6+17tjQ78QjqjAQDnhULWiTA6u0FCDmYT1oOKS9PzZ2z0aBI+Mcyj7Q==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-riscv64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-riscv64/-/linux-riscv64-0.19.5.tgz", + "integrity": "sha512-5u8cIR/t3gaD6ad3wNt1MNRstAZO+aNyBxu2We8X31bA8XUNyamTVQwLDA1SLoPCUehNCymhBhK3Qim1433Zag==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-s390x": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-s390x/-/linux-s390x-0.19.5.tgz", + "integrity": "sha512-Z6JrMyEw/EmZBD/OFEFpb+gao9xJ59ATsoTNlj39jVBbXqoZm4Xntu6wVmGPB/OATi1uk/DB+yeDPv2E8PqZGw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/linux-x64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-x64/-/linux-x64-0.19.5.tgz", + "integrity": "sha512-psagl+2RlK1z8zWZOmVdImisMtrUxvwereIdyJTmtmHahJTKb64pAcqoPlx6CewPdvGvUKe2Jw+0Z/0qhSbG1A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/netbsd-x64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/netbsd-x64/-/netbsd-x64-0.19.5.tgz", + "integrity": "sha512-kL2l+xScnAy/E/3119OggX8SrWyBEcqAh8aOY1gr4gPvw76la2GlD4Ymf832UCVbmuWeTf2adkZDK+h0Z/fB4g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/openbsd-x64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/openbsd-x64/-/openbsd-x64-0.19.5.tgz", + "integrity": "sha512-sPOfhtzFufQfTBgRnE1DIJjzsXukKSvZxloZbkJDG383q0awVAq600pc1nfqBcl0ice/WN9p4qLc39WhBShRTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/sunos-x64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/sunos-x64/-/sunos-x64-0.19.5.tgz", + "integrity": "sha512-dGZkBXaafuKLpDSjKcB0ax0FL36YXCvJNnztjKV+6CO82tTYVDSH2lifitJ29jxRMoUhgkg9a+VA/B03WK5lcg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/win32-arm64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-arm64/-/win32-arm64-0.19.5.tgz", + "integrity": "sha512-dWVjD9y03ilhdRQ6Xig1NWNgfLtf2o/STKTS+eZuF90fI2BhbwD6WlaiCGKptlqXlURVB5AUOxUj09LuwKGDTg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/win32-ia32": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-ia32/-/win32-ia32-0.19.5.tgz", + "integrity": "sha512-4liggWIA4oDgUxqpZwrDhmEfAH4d0iljanDOK7AnVU89T6CzHon/ony8C5LeOdfgx60x5cnQJFZwEydVlYx4iw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild/node_modules/@esbuild/win32-x64": { + "version": "0.19.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-x64/-/win32-x64-0.19.5.tgz", + "integrity": "sha512-czTrygUsB/jlM8qEW5MD8bgYU2Xg14lo6kBDXW6HdxKjh8M5PzETGiSHaz9MtbXBYDloHNUAUW2tMiKW4KM9Mw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/escalade/-/escalade-3.1.1.tgz", @@ -23155,9 +23227,9 @@ "license": "ISC" }, "node_modules/flow-parser": { - "version": "0.227.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/flow-parser/-/flow-parser-0.227.0.tgz", - "integrity": "sha512-nOygtGKcX/siZK/lFzpfdHEfOkfGcTW7rNroR1Zsz6T/JxSahPALXVt5qVHq/fgvMJuv096BTKbgxN3PzVBaDA==", + "version": "0.228.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/flow-parser/-/flow-parser-0.228.0.tgz", + "integrity": "sha512-xPWkzCO07AnS8X+fQFpWm+tJ+C7aeaiVzJ+rSepbkCXUvUJ6l6squEl63axoMcixyH4wLjmypOzq/+zTD0O93w==", "dev": true, "license": "MIT", "engines": { @@ -29100,6 +29172,7 @@ "version": "1.4.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" @@ -29271,9 +29344,9 @@ } }, "node_modules/markdown-to-jsx": { - "version": "7.4.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/markdown-to-jsx/-/markdown-to-jsx-7.4.0.tgz", - "integrity": "sha512-zilc+MIkVVXPyTb4iIUTIz9yyqfcWjszGXnwF9K/aiBWcHXFcmdEMTkG01/oQhwSCH7SY1BnG6+ev5BzWmbPrg==", + "version": "7.4.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/markdown-to-jsx/-/markdown-to-jsx-7.4.1.tgz", + "integrity": "sha512-GbrbkTnHp9u6+HqbPRFJbObi369AgJNXi/sGqq5HRsoZW063xR1XDCaConqq+whfEIAlzB1YPnOgsPc7B7bc/A==", "dev": true, "license": "MIT", "engines": { @@ -31122,9 +31195,9 @@ } }, "node_modules/node-fetch-native": { - "version": "1.6.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/node-fetch-native/-/node-fetch-native-1.6.1.tgz", - "integrity": "sha512-bW9T/uJDPAJB2YNYEpWzE54U5O3MQidXsOyTfnbKYtTtFexRvGzb1waphBN4ZwP6EcIvYYEOwW0b72BpAqydTw==", + "version": "1.6.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/node-fetch-native/-/node-fetch-native-1.6.2.tgz", + "integrity": "sha512-69mtXOFZ6hSkYiXAVB5SqaRvrbITC/NPyqv7yuu/qw0nmgPyYbIMYYNIDhNtwPrzk0ptrimrLz/hhjvm4w5Z+w==", "dev": true, "license": "MIT" }, @@ -31304,9 +31377,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "license": "MIT" }, "node_modules/nopt": { @@ -31577,6 +31650,150 @@ } } }, + "node_modules/nx/node_modules/@nx/nx-darwin-arm64": { + "version": "17.0.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-darwin-arm64/-/nx-darwin-arm64-17.0.2.tgz", + "integrity": "sha512-OSZLRfV8VplYPEqMcIg3mbAsJXlXEHKrdlJ0KUTk8Hih2+wl7cxuSEwG7X7qfBUOz+ognxaqicL+hueNrgwjlQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-freebsd-x64": { + "version": "17.0.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-freebsd-x64/-/nx-freebsd-x64-17.0.2.tgz", + "integrity": "sha512-+mta0J2G2byd+rfZ275oZs0aYXC/s92nI9ySBFQFQZnKJ6bsAagdZHe+uETsnE4xdhFXD8kvNMJU1WTGlyFyjg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-linux-arm-gnueabihf": { + "version": "17.0.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm-gnueabihf/-/nx-linux-arm-gnueabihf-17.0.2.tgz", + "integrity": "sha512-m80CmxHHyNAJ8j/0rkjc0hg/eGQlf6V2sLsV+gEJkz2sTEEdgSOK4DvnWcZRWO/SWBnqigxoHX4Kf5TH1nmoHA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-linux-arm64-gnu": { + "version": "17.0.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm64-gnu/-/nx-linux-arm64-gnu-17.0.2.tgz", + "integrity": "sha512-AsD1H6wt68MK1u6vkmtNaFaxDMcyuk6dpo5kq1YT9cfUd614ys3qMUjVp3P2CXxzXh+0UDZeGrc6qotNKOkpJw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-linux-arm64-musl": { + "version": "17.0.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-arm64-musl/-/nx-linux-arm64-musl-17.0.2.tgz", + "integrity": "sha512-f8pUFoZHBFQtHnopHgTEuwIiu0Rzem0dD7iK8SyyBy/lRAADtHCAHxaPAG+iatHAJ9h4DFIB50k9ybYxDtH2mg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-linux-x64-gnu": { + "version": "17.0.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-x64-gnu/-/nx-linux-x64-gnu-17.0.2.tgz", + "integrity": "sha512-PISrHjLTxv5w8bz50vPZH6puYos88xu28o4IbVyYWrUrhoFsAx9Zbn1D6gWDPMSaKJU32v1l+5bTciQjQJU8fQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-linux-x64-musl": { + "version": "17.0.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-linux-x64-musl/-/nx-linux-x64-musl-17.0.2.tgz", + "integrity": "sha512-2wsqyBRjsxmAjxW+0lnGFtJLTk+AxgW7gjMv8NgLK8P1bc/sJYQB+g0o5op2z+szXRG3Noi0RZ9C0fG39EPFZw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-win32-arm64-msvc": { + "version": "17.0.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-win32-arm64-msvc/-/nx-win32-arm64-msvc-17.0.2.tgz", + "integrity": "sha512-Sc3sQUcS5xdk05PABe/knG6orG5rmHZdSUj6SMRpvYfN2tM3ziNn6/wCF/LJoW6n70OxrOEXXwLSRK/5WigXbA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/nx/node_modules/@nx/nx-win32-x64-msvc": { + "version": "17.0.2", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@nx/nx-win32-x64-msvc/-/nx-win32-x64-msvc-17.0.2.tgz", + "integrity": "sha512-XhET0BDk6fbvTBCs7m5gZii8+2WhLpiC1sZchJw4LAJN2VJBiy3I3xnvpQYGFOAWaCb/iUGpuN/qP/NlQ+LNgA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/nx/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -34211,9 +34428,9 @@ } }, "node_modules/prettier": { - "version": "3.2.4", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/prettier/-/prettier-3.2.4.tgz", - "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "version": "3.2.5", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", "dev": true, "license": "MIT", "bin": { @@ -34226,29 +34443,6 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/prettier-plugin-organize-imports": { - "version": "3.2.4", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.2.4.tgz", - "integrity": "sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "peerDependencies": { - "@volar/vue-language-plugin-pug": "^1.0.4", - "@volar/vue-typescript": "^1.0.4", - "prettier": ">=2.0", - "typescript": ">=2.9" - }, - "peerDependenciesMeta": { - "@volar/vue-language-plugin-pug": { - "optional": true - }, - "@volar/vue-typescript": { - "optional": true - } - } - }, "node_modules/prettier-plugin-tailwindcss": { "version": "0.5.11", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.11.tgz", @@ -34855,6 +35049,7 @@ "version": "18.2.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/react/-/react-18.2.0.tgz", "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" @@ -34878,6 +35073,7 @@ "version": "18.2.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/react-dom/-/react-dom-18.2.0.tgz", "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", @@ -35974,6 +36170,7 @@ "version": "0.23.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/scheduler/-/scheduler-0.23.0.tgz", "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, "license": "MIT", "dependencies": { "loose-envify": "^1.1.0" @@ -39080,9 +39277,9 @@ } }, "node_modules/ufo": { - "version": "1.3.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ufo/-/ufo-1.3.2.tgz", - "integrity": "sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==", + "version": "1.4.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ufo/-/ufo-1.4.0.tgz", + "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", "dev": true, "license": "MIT" }, @@ -39283,13 +39480,13 @@ } }, "node_modules/unplugin": { - "version": "1.6.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/unplugin/-/unplugin-1.6.0.tgz", - "integrity": "sha512-BfJEpWBu3aE/AyHx8VaNE/WgouoQxgH9baAiH82JjX8cqVyi3uJQstqwD5J+SZxIK326SZIhsSZlALXVBCknTQ==", + "version": "1.7.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/unplugin/-/unplugin-1.7.1.tgz", + "integrity": "sha512-JqzORDAPxxs8ErLV4x+LL7bk5pk3YlcWqpSNsIkAZj972KzFZLClc/ekppahKkOczGkwIG6ElFgdOgOlK4tXZw==", "dev": true, "license": "MIT", "dependencies": { - "acorn": "^8.11.2", + "acorn": "^8.11.3", "chokidar": "^3.5.3", "webpack-sources": "^3.2.3", "webpack-virtual-modules": "^0.6.1" @@ -39747,70 +39944,6 @@ } } }, - "node_modules/vite/node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/vite/node_modules/@esbuild/darwin-x64": { "version": "0.18.20", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", @@ -39827,278 +39960,6 @@ "node": ">=12" } }, - "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/vite/node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/vite/node_modules/esbuild": { "version": "0.18.20", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/esbuild/-/esbuild-0.18.20.tgz", @@ -40734,9 +40595,9 @@ } }, "node_modules/webpack-hot-middleware": { - "version": "2.26.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/webpack-hot-middleware/-/webpack-hot-middleware-2.26.0.tgz", - "integrity": "sha512-okzjec5sAEy4t+7rzdT8eRyxsk0FDSmBPN2KwX4Qd+6+oQCfe5Ve07+u7cJvofgB+B4w5/4dO4Pz0jhhHyyPLQ==", + "version": "2.26.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/webpack-hot-middleware/-/webpack-hot-middleware-2.26.1.tgz", + "integrity": "sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==", "dev": true, "license": "MIT", "dependencies": { diff --git a/alfa-client/package.json b/alfa-client/package.json index b1dbd1d07e3adc8b1db21e5a5c31f73ab182ef76..8a0a6b88cafb734b0f270f1a3c2dcc5ab6992ad0 100644 --- a/alfa-client/package.json +++ b/alfa-client/package.json @@ -67,8 +67,6 @@ "include-media": "^1.4.10", "js-base64": "^3.7.5", "lodash-es": "4.17.21", - "react": "^18.2.0", - "react-dom": "^18.2.0", "rxjs": "~7.8.1", "sanitize-filename-ts": "^1.0.2", "tslib": "^2.3.0", @@ -138,8 +136,10 @@ "postcss-import": "~14.1.0", "postcss-preset-env": "~7.5.0", "postcss-url": "~10.1.3", - "prettier": "^3.2.4", - "prettier-plugin-tailwindcss": "^0.5.7", + "prettier": "^3.2.5", + "prettier-plugin-tailwindcss": "^0.5.11", + "react": "^18.2.0", + "react-dom": "^18.2.0", "sonarqube-scanner": "3.1.0", "tailwindcss": "^3.0.2", "ts-jest": "^29.1.0", diff --git a/alfa-client/pom.xml b/alfa-client/pom.xml index 4b5df1b2180fb9c74feec5e675386f3f76634731..155340560e7db527d6e0d0de3b99f320f13bbfc8 100644 --- a/alfa-client/pom.xml +++ b/alfa-client/pom.xml @@ -24,13 +24,12 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>de.ozgcloud.alfa</groupId> <artifactId>alfa</artifactId> - <version>2.2.0-SNAPSHOT</version> + <version>2.3.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> diff --git a/alfa-client/proxy.conf.mjs b/alfa-client/proxy.conf.mjs index 7b763c96c6604c3b6eedec61f569331fa0daba3b..cdc878a3be72dd91616310639946483c8275ddf4 100644 --- a/alfa-client/proxy.conf.mjs +++ b/alfa-client/proxy.conf.mjs @@ -1,14 +1,12 @@ export default [ - { - "context": [ - "/api" - ], - "target": { - "host": "localhost", - "port": 8080, - "protocol": "http:" - }, - "secure": false, - "logLevel": "debug" - } -]; \ No newline at end of file + { + context: ['/api'], + target: { + host: 'localhost', + port: 8080, + protocol: 'http:', + }, + secure: false, + logLevel: 'debug', + }, +]; diff --git a/alfa-client/proxy.dev.conf.json b/alfa-client/proxy.dev.conf.json index cd5807bbb588e06ec11e67f520b1e2b4237c4454..2f1499aed01bbfe6ac78d1edde31d6bba718868c 100644 --- a/alfa-client/proxy.dev.conf.json +++ b/alfa-client/proxy.dev.conf.json @@ -1,12 +1,11 @@ { - "/api": { - "target": { - "host": "kiel.dev.by.ozg-cloud.de", + "/api": { + "target": { + "host": "kiel.dev.by.ozg-cloud.de", - "protocol": "https:" - }, - "secure": false, - "logLevel": "debug" - } + "protocol": "https:" + }, + "secure": false, + "logLevel": "debug" } - \ No newline at end of file +} diff --git a/alfa-server/pom.xml b/alfa-server/pom.xml index 8765c271edfae79d7486590f9e66386ead0c7802..cd18f5ebb3a482794fb46b30ed44cec42fa44b6d 100644 --- a/alfa-server/pom.xml +++ b/alfa-server/pom.xml @@ -1,11 +1,11 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<?xml version="1.0"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>de.ozgcloud.alfa</groupId> <artifactId>alfa</artifactId> - <version>2.2.0-SNAPSHOT</version> + <version>2.3.0-SNAPSHOT</version> </parent> <artifactId>alfa-server</artifactId> diff --git a/alfa-service/pom.xml b/alfa-service/pom.xml index 1fe37647502d07000c758a66bc39ab127f87c434..380cea0dadb30e4e4978d8ba87606a467fcfb083 100644 --- a/alfa-service/pom.xml +++ b/alfa-service/pom.xml @@ -1,3 +1,4 @@ +<?xml version="1.0"?> <!-- Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den @@ -23,15 +24,14 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>de.ozgcloud.alfa</groupId> <artifactId>alfa</artifactId> - <version>2.2.0-SNAPSHOT</version> + <version>2.3.0-SNAPSHOT</version> </parent> <artifactId>alfa-service</artifactId> diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachConfig.java b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachConfig.java new file mode 100644 index 0000000000000000000000000000000000000000..1b3696ea0b688f1bce416613029836442effcd23 --- /dev/null +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachConfig.java @@ -0,0 +1,14 @@ +package de.ozgcloud.alfa.postfach; + +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +@Getter +@Builder +@ToString +public class PostfachConfig { + + private final String type; + private final boolean replyAllowed; +} diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachConfigGroup.java b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachConfigGroup.java new file mode 100644 index 0000000000000000000000000000000000000000..7cb0ba862108f93e6a32cee1741896c78b6a1f43 --- /dev/null +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachConfigGroup.java @@ -0,0 +1,16 @@ +package de.ozgcloud.alfa.postfach; + +import java.util.List; + +import lombok.Builder; +import lombok.Getter; +import lombok.ToString; + +@Getter +@Builder +@ToString +public class PostfachConfigGroup { + + private final boolean configured; + private final List<PostfachConfig> postfachConfigs; +} diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachConfigMapper.java b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachConfigMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..1e4c6ea99850c620307f452e8546dfe5919d9ab9 --- /dev/null +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachConfigMapper.java @@ -0,0 +1,17 @@ +package de.ozgcloud.alfa.postfach; + +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.NullValueCheckStrategy; + +import de.ozgcloud.nachrichten.postfach.GrpcGetPostfachConfigResponse; +import de.ozgcloud.nachrichten.postfach.GrpcPostfach; + +@Mapper(nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) +interface PostfachConfigMapper { + + @Mapping(target = "postfachConfigs", source = "postfachList") + PostfachConfigGroup toPostfachConfigGroup(GrpcGetPostfachConfigResponse grpcPostfachCollection); + + PostfachConfig toPostfachConfig(GrpcPostfach grpcPostfach); +} diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailRemoteService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailRemoteService.java index dc0314670de3ec3f6490d16f5ca9fcb3562d76c2..6a6dc382a92b6bef49161198140425a9b3e1b3f5 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailRemoteService.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailRemoteService.java @@ -33,7 +33,7 @@ import de.ozgcloud.alfa.common.GrpcUtil; import de.ozgcloud.alfa.common.callcontext.ContextService; import de.ozgcloud.nachrichten.postfach.GrpcFindPostfachMailRequest; import de.ozgcloud.nachrichten.postfach.GrpcFindPostfachMailsRequest; -import de.ozgcloud.nachrichten.postfach.GrpcIsPostfachConfiguredRequest; +import de.ozgcloud.nachrichten.postfach.GrpcGetPostfachConfigRequest; import de.ozgcloud.nachrichten.postfach.GrpcResendPostfachMailRequest; import de.ozgcloud.nachrichten.postfach.PostfachServiceGrpc.PostfachServiceBlockingStub; import net.devh.boot.grpc.client.inject.GrpcClient; @@ -47,6 +47,8 @@ class PostfachMailRemoteService { private ContextService contextService; @Autowired private PostfachMailMapper postfachNachrichtMapper; + @Autowired + private PostfachConfigMapper postfachConfigMapper; public Stream<PostfachMail> findPostfachMails(String vorgangId) { var response = serviceStub.findPostfachMails(buildFindPostfachMailsRequest(vorgangId)); @@ -86,11 +88,12 @@ class PostfachMailRemoteService { .build(); } - public boolean isPostfachConfigured() { - return serviceStub.isPostfachConfigured(buildIsPostfachConfiguredRequest()).getIsConfigured(); + public PostfachConfigGroup getPostfachConfig() { + var response = serviceStub.getPostfachConfig(buildGetPostfachConfigRequest()); + return postfachConfigMapper.toPostfachConfigGroup(response); } - private GrpcIsPostfachConfiguredRequest buildIsPostfachConfiguredRequest() { - return GrpcIsPostfachConfiguredRequest.newBuilder().setContext(contextService.createCallContext()).build(); + private GrpcGetPostfachConfigRequest buildGetPostfachConfigRequest() { + return GrpcGetPostfachConfigRequest.newBuilder().build(); } } \ No newline at end of file diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailService.java b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailService.java index 85996eb590e7782cbeaded537622670c9b663d63..a94151852adef541a174920e40dc35081e801d4b 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailService.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachMailService.java @@ -53,9 +53,7 @@ import lombok.extern.log4j.Log4j2; @Service class PostfachMailService { - private static final String OSI_SERVICE_KONTO_TYPE = "OSI"; - - private Boolean postfachConfigured = null; + private PostfachConfigGroup postfachConfigGroup; @Autowired private PostfachMailRemoteService remoteService; @@ -84,17 +82,15 @@ class PostfachMailService { remoteService.resendPostfachMail(commandId, postfachMailId); } catch (RuntimeException e) { LOG.error("Error sending PostfachNachricht: " + e.getMessage(), e); -// FIXME mark command as in error + // FIXME mark command as in error } } public boolean isPostfachConfigured() { - if (Objects.isNull(postfachConfigured)) { - LOG.info("isPostfachConfigured is null"); - postfachConfigured = remoteService.isPostfachConfigured(); - LOG.info("isPostfachConfigured set to " + postfachConfigured); + if (Objects.isNull(postfachConfigGroup)) { + postfachConfigGroup = remoteService.getPostfachConfig(); } - return postfachConfigured; + return postfachConfigGroup.isConfigured(); } public OutputStream getAllAsPdf(VorgangWithEingang vorgang, OutputStream out) { @@ -149,7 +145,18 @@ class PostfachMailService { public boolean isReplyToMessageAllowed(VorgangWithEingang vorgang) { return Optional.ofNullable(vorgang.getHeader().getServiceKonto()) .map(ServiceKonto::getType) - .map(OSI_SERVICE_KONTO_TYPE::equals) + .map(this::isReplyAllowed) + .orElse(false); + } + + boolean isReplyAllowed(String serviceKontoType) { + if (!isPostfachConfigured()) { + return false; + } + return postfachConfigGroup.getPostfachConfigs().stream() + .filter(postfachConfig -> postfachConfig.getType().equals(serviceKontoType)) + .map(PostfachConfig::isReplyAllowed) + .findFirst() .orElse(false); } } \ No newline at end of file diff --git a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachNachrichtHelper.java b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachNachrichtHelper.java index 87c08bd5a1b825159e969a90dced7f7de0a6ef6e..df580d4aec2b1bfb268391827d91aac17998e993 100644 --- a/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachNachrichtHelper.java +++ b/alfa-service/src/main/java/de/ozgcloud/alfa/postfach/PostfachNachrichtHelper.java @@ -1,5 +1,9 @@ package de.ozgcloud.alfa.postfach; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -9,18 +13,31 @@ import de.ozgcloud.alfa.vorgang.VorgangWithEingang; @Component class PostfachNachrichtHelper { + static final String SERVICEKONTO_TYPE_FIELD = "serviceKontoType"; + @Autowired private PostfachMailMapper mapper; public CommandBody addPostfachAddressToBody(PostfachMail nachricht, VorgangWithEingang vorgang) { - return addPostfachAddress(nachricht, getPostfachAddress(vorgang)); + return addPostfachAddress(nachricht, createPostfachAddressForPostfachMail(vorgang)); + } + + private PostfachMail addPostfachAddress(PostfachMail nachricht, Map<String, Object> postfachAddress) { + return nachricht.toBuilder().postfachAddress(postfachAddress).build(); + } + + private Map<String, Object> createPostfachAddressForPostfachMail(VorgangWithEingang vorgang) { + Map<String, Object> postfachAddressForPostfachMail = new HashMap<>(mapper.mapPostfachAddressToMap(getPostfachAddress(vorgang))); + postfachAddressForPostfachMail.put(SERVICEKONTO_TYPE_FIELD, getServiceKontoType(vorgang)); + return Collections.unmodifiableMap(postfachAddressForPostfachMail); } private PostfachAddress getPostfachAddress(VorgangWithEingang vorgang) { return vorgang.getHeader().getServiceKonto().getPostfachAddresses().get(0); } - private PostfachMail addPostfachAddress(PostfachMail nachricht, PostfachAddress postfachAddress) { - return nachricht.toBuilder().postfachAddress(mapper.mapPostfachAddressToMap(postfachAddress)).build(); + private String getServiceKontoType(VorgangWithEingang vorgang) { + return vorgang.getHeader().getServiceKonto().getType(); } + } \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/GrpcGetPostfachConfigResponseTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/GrpcGetPostfachConfigResponseTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..9751b72211ce6cbc454e36ebba6f09c153adb814 --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/GrpcGetPostfachConfigResponseTestFactory.java @@ -0,0 +1,18 @@ +package de.ozgcloud.alfa.postfach; + +import de.ozgcloud.nachrichten.postfach.GrpcGetPostfachConfigResponse; + +public class GrpcGetPostfachConfigResponseTestFactory { + + public static final boolean CONFIGURED = true; + + public static GrpcGetPostfachConfigResponse create() { + return createBuilder().build(); + } + + public static GrpcGetPostfachConfigResponse.Builder createBuilder() { + return GrpcGetPostfachConfigResponse.newBuilder() + .setConfigured(CONFIGURED) + .addPostfach(GrpcPostfachTestFactory.create()); + } +} diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/GrpcPostfachTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/GrpcPostfachTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..10f25a858eaa4f364fbbcc83b89a73df51784bad --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/GrpcPostfachTestFactory.java @@ -0,0 +1,19 @@ +package de.ozgcloud.alfa.postfach; + +import de.ozgcloud.nachrichten.postfach.GrpcPostfach; + +public class GrpcPostfachTestFactory { + + public static final String TYPE = "OSI"; + public static final boolean REPLY_ALLOWED = true; + + public static GrpcPostfach create() { + return createBuilder().build(); + } + + public static GrpcPostfach.Builder createBuilder() { + return GrpcPostfach.newBuilder() + .setType(TYPE) + .setReplyAllowed(REPLY_ALLOWED); + } +} diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachAddressTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachAddressTestFactory.java index 10fb0c75997a5c00c14f713e7fa4c1e48409b190..c3259ffc1377bbdd771464084718131c919e81f1 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachAddressTestFactory.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachAddressTestFactory.java @@ -3,6 +3,8 @@ package de.ozgcloud.alfa.postfach; import java.util.Map; import java.util.UUID; +import de.ozgcloud.alfa.vorgang.ServiceKontoTestFactory; + public class PostfachAddressTestFactory { public final static int TYPE = 1; @@ -26,7 +28,8 @@ public class PostfachAddressTestFactory { public static Map<String, Object> createAsMap() { return Map.of(PostfachAddress.TYPE_FIELD, TYPE, PostfachAddress.VERSION_FIELD, VERSION, - PostfachAddress.IDENTIFIER_FIELD, createIdentifierMap()); + PostfachAddress.IDENTIFIER_FIELD, createIdentifierMap(), + PostfachNachrichtHelper.SERVICEKONTO_TYPE_FIELD, ServiceKontoTestFactory.TYPE); } private static Map<String, Object> createIdentifierMap() { diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachConfigGroupTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachConfigGroupTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..c87b363c75277df2fcc89b54d5162c98462b8a56 --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachConfigGroupTestFactory.java @@ -0,0 +1,16 @@ +package de.ozgcloud.alfa.postfach; + +import java.util.List; + +public class PostfachConfigGroupTestFactory { + + public static PostfachConfigGroup create() { + return createBuilder().build(); + } + + public static PostfachConfigGroup.PostfachConfigGroupBuilder createBuilder() { + return PostfachConfigGroup.builder() + .configured(true) + .postfachConfigs(List.of(PostfachConfigTestFactory.create())); + } +} diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachConfigMapperTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachConfigMapperTest.java new file mode 100644 index 0000000000000000000000000000000000000000..348719c1c667cb04202403b07f5620af4d0beaed --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachConfigMapperTest.java @@ -0,0 +1,54 @@ +package de.ozgcloud.alfa.postfach; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mapstruct.factory.Mappers; +import org.mockito.Spy; + +public class PostfachConfigMapperTest { + + @Spy + private final PostfachConfigMapper mapper = Mappers.getMapper(PostfachConfigMapper.class); + + @Nested + class TestToPostfachConfig { + + @Test + void shouldMapReplyAllowed() { + var postfachConfig = mapper.toPostfachConfig(GrpcPostfachTestFactory.create()); + + assertThat(postfachConfig.isReplyAllowed()).isEqualTo(GrpcPostfachTestFactory.REPLY_ALLOWED); + } + + @Test + void shouldMapType() { + var postfachConfig = mapper.toPostfachConfig(GrpcPostfachTestFactory.create()); + + assertThat(postfachConfig.getType()).isEqualTo(GrpcPostfachTestFactory.TYPE); + } + } + + @Nested + class TestToPostfachConfigGroup { + + @Test + void shouldMapConfigured() { + var postfachConfigGroup = mapper.toPostfachConfigGroup(GrpcGetPostfachConfigResponseTestFactory.create()); + + assertThat(postfachConfigGroup.isConfigured()).isEqualTo(GrpcGetPostfachConfigResponseTestFactory.CONFIGURED); + } + + @Test + void shouldMapPostfachConfigs() { + var expectedPostfachConfig = PostfachConfigTestFactory.create(); + doReturn(expectedPostfachConfig).when(mapper).toPostfachConfig(GrpcPostfachTestFactory.create()); + + var postfachConfigGroup = mapper.toPostfachConfigGroup(GrpcGetPostfachConfigResponseTestFactory.create()); + + assertThat(postfachConfigGroup.getPostfachConfigs()).containsOnly(expectedPostfachConfig); + } + } +} diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachConfigTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachConfigTestFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..5d77699ee786d942c53cf4102a405561ce0c9d7b --- /dev/null +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachConfigTestFactory.java @@ -0,0 +1,16 @@ +package de.ozgcloud.alfa.postfach; + +public class PostfachConfigTestFactory { + + public static final String TYPE = "OSI"; + + public static PostfachConfig create() { + return createBuilder().build(); + } + + public static PostfachConfig.PostfachConfigBuilder createBuilder() { + return PostfachConfig.builder() + .replyAllowed(true) + .type(TYPE); + } +} diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailITCase.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailITCase.java index 1af57b84b77211fd3125c17fcad36261b8c4c1cf..8e0fcaa743a0c7f8b9c786359eff40e28a2a1e2f 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailITCase.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailITCase.java @@ -79,6 +79,7 @@ public class PostfachMailITCase { @BeforeEach void mock() { when(serviceStub.findPostfachMails(any())).thenReturn(GrpcPostfachMailTestFactory.createFindPostfachMailsResponse()); + when(serviceStub.getPostfachConfig(any())).thenReturn(GrpcGetPostfachConfigResponseTestFactory.create()); when(vorgangController.getVorgang(anyString())).thenReturn( VorgangWithEingangTestFactory.createBuilder().eingang(EingangTestFactory.createBuilder().antragsteller(null).build()).build()); diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailRemoteServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailRemoteServiceTest.java index b754ce2a13a5c9c5d91c91eded5dba835e409e8b..b2befc98785ddcad00b93cbf77947f58cbaed8ed 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailRemoteServiceTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailRemoteServiceTest.java @@ -43,8 +43,8 @@ import de.ozgcloud.alfa.common.command.CommandTestFactory; import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; import de.ozgcloud.nachrichten.postfach.GrpcFindPostfachMailRequest; import de.ozgcloud.nachrichten.postfach.GrpcFindPostfachMailsRequest; -import de.ozgcloud.nachrichten.postfach.GrpcIsPostfachConfiguredRequest; -import de.ozgcloud.nachrichten.postfach.GrpcIsPostfachConfiguredResponse; +import de.ozgcloud.nachrichten.postfach.GrpcGetPostfachConfigRequest; +import de.ozgcloud.nachrichten.postfach.GrpcGetPostfachConfigResponse; import de.ozgcloud.nachrichten.postfach.GrpcPostfachMail; import de.ozgcloud.nachrichten.postfach.GrpcResendPostfachMailRequest; import de.ozgcloud.nachrichten.postfach.PostfachServiceGrpc.PostfachServiceBlockingStub; @@ -59,15 +59,12 @@ class PostfachMailRemoteServiceTest { @Mock private PostfachMailMapper postfachNachrichtMapper; @Mock + private PostfachConfigMapper postfachConfigMapper; + @Mock private ContextService contextService; private GrpcCallContext callContext = GrpcCallContext.newBuilder().build(); - @BeforeEach - void initMocks() { - when(contextService.createCallContext()).thenReturn(callContext); - } - @Nested class TestFindPostfachMail { @@ -76,6 +73,7 @@ class PostfachMailRemoteServiceTest { @BeforeEach void init() { + when(contextService.createCallContext()).thenReturn(callContext); when(serviceStub.findPostfachMail(any())).thenReturn(GrpcPostfachMailTestFactory.createFindPostfachMailResponse()); } @@ -114,7 +112,8 @@ class PostfachMailRemoteServiceTest { class TestFindPostfachMails { @BeforeEach - void mockServiceStub() { + void init() { + when(contextService.createCallContext()).thenReturn(callContext); when(serviceStub.findPostfachMails(any())).thenReturn(GrpcPostfachMailTestFactory.createFindPostfachMailsResponse()); } @@ -148,6 +147,11 @@ class PostfachMailRemoteServiceTest { @Nested class TestResendPostfachMail { + @BeforeEach + void init() { + when(contextService.createCallContext()).thenReturn(callContext); + } + @Test void shouldCallStub() { service.resendPostfachMail(CommandTestFactory.ID, PostfachMailTestFactory.ID); @@ -164,26 +168,36 @@ class PostfachMailRemoteServiceTest { } @Nested - class TestIsPostfachConfigured { + class TestGetPostfachConfig { + + private final GrpcGetPostfachConfigResponse grpcResponse = GrpcGetPostfachConfigResponseTestFactory.create(); + private final PostfachConfigGroup postfachConfigGroup = PostfachConfigGroupTestFactory.create(); @BeforeEach void mockStub() { - when(serviceStub.isPostfachConfigured(any(GrpcIsPostfachConfiguredRequest.class))) - .thenReturn(GrpcIsPostfachConfiguredResponse.newBuilder().setIsConfigured(true).build()); + when(serviceStub.getPostfachConfig(any(GrpcGetPostfachConfigRequest.class))).thenReturn(grpcResponse); + when(postfachConfigMapper.toPostfachConfigGroup(any(GrpcGetPostfachConfigResponse.class))).thenReturn(postfachConfigGroup); } @Test void shouldCallServiceStub() { - service.isPostfachConfigured(); + service.getPostfachConfig(); - verify(serviceStub).isPostfachConfigured(any(GrpcIsPostfachConfiguredRequest.class)); + verify(serviceStub).getPostfachConfig(any(GrpcGetPostfachConfigRequest.class)); } @Test - void shouldCallContextService() { - service.isPostfachConfigured(); + void shouldCallMapper() { + service.getPostfachConfig(); - verify(contextService).createCallContext(); + verify(postfachConfigMapper).toPostfachConfigGroup(grpcResponse); + } + + @Test + void shouldReturnPostfachConfigs() { + var result = service.getPostfachConfig(); + + assertThat(result).isEqualTo(postfachConfigGroup); } } } \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailServiceTest.java b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailServiceTest.java index cef6356871feaa40d6b878e6e7d663f0317d85d8..aa07067a624b2dbc8d8a38d77f521da35b6ed36b 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailServiceTest.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/postfach/PostfachMailServiceTest.java @@ -38,11 +38,15 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; import org.springframework.test.util.ReflectionTestUtils; +import com.thedeanda.lorem.LoremIpsum; + import de.ozgcloud.alfa.common.binaryfile.BinaryFileService; import de.ozgcloud.alfa.common.binaryfile.BinaryFileTestFactory; import de.ozgcloud.alfa.common.command.CommandService; @@ -93,7 +97,7 @@ class PostfachMailServiceTest { @Nested class TestFindById { - private PostfachMail mail = PostfachMailTestFactory.create(); + private final PostfachMail mail = PostfachMailTestFactory.create(); @BeforeEach void init() { @@ -154,20 +158,52 @@ class PostfachMailServiceTest { @Test void shouldCallRemoteServiceOnMissingProperty() { + when(remoteService.getPostfachConfig()).thenReturn(PostfachConfigGroupTestFactory.create()); + service.isPostfachConfigured(); - verify(remoteService).isPostfachConfigured(); + verify(remoteService).getPostfachConfig(); } @Test - void shouldNotCallRemoteServiceOnExistingProperty() throws Exception { - ReflectionTestUtils.setField(service, "postfachConfigured", true); + void shouldNotCallRemoteServiceOnExistingProperty() { + setPostfachConfigGroup(PostfachConfigGroupTestFactory.create()); service.isPostfachConfigured(); verifyNoInteractions(remoteService); } + @Test + void shoulCallRemoteServiceOnlyOnce() { + when(remoteService.getPostfachConfig()).thenReturn(PostfachConfigGroupTestFactory.create()); + + service.isPostfachConfigured(); + service.isPostfachConfigured(); + + verify(remoteService, times(1)).getPostfachConfig(); + } + + @ParameterizedTest + @ValueSource(booleans = { false, true }) + void shouldReturnValueFromRemoteService(boolean expectedConfigured) { + var serviceResponse = PostfachConfigGroupTestFactory.createBuilder().configured(expectedConfigured).build(); + when(remoteService.getPostfachConfig()).thenReturn(serviceResponse); + + var configured = service.isPostfachConfigured(); + + assertThat(configured).isEqualTo(expectedConfigured); + } + + @ParameterizedTest + @ValueSource(booleans = { false, true }) + void shouldReturnCachedValue(boolean expectedConfigured) { + setPostfachConfigGroup(PostfachConfigGroupTestFactory.createBuilder().configured(expectedConfigured).build()); + + var configured = service.isPostfachConfigured(); + + assertThat(configured).isEqualTo(expectedConfigured); + } } @DisplayName("Get all as pdf") @@ -439,30 +475,22 @@ class PostfachMailServiceTest { class TestIsReplyToMessageAllowed { @Test - void shouldReturnTrueForOSIPostfach() { - var vorgang = VorgangWithEingangTestFactory.create(); - - var replyToMessageAllowed = service.isReplyToMessageAllowed(vorgang); - - assertThat(replyToMessageAllowed).isTrue(); - } + void shouldCallIsReplyAllowed() { + doReturn(true).when(service).isReplyAllowed(any()); - @Test - void shouldReturnFalseForBayernIDPostfach() { - var vorgangWithEingang = createVorgangWithServiceKonto("BayernID"); - - var replyToMessageAllowed = service.isReplyToMessageAllowed(vorgangWithEingang); + service.isReplyToMessageAllowed(VorgangWithEingangTestFactory.create()); - assertThat(replyToMessageAllowed).isFalse(); + verify(service).isReplyAllowed(ServiceKontoTestFactory.TYPE); } - @Test - void shouldReturnFalseForUnknownPostfach() { - var vorgangWithEingang = createVorgangWithServiceKonto(null); + @ParameterizedTest + @ValueSource(booleans = { false, true }) + void shouldReturnResultOfIsReplyAllowed(boolean expectedReplyAllowed) { + doReturn(expectedReplyAllowed).when(service).isReplyAllowed(any()); - var replyToMessageAllowed = service.isReplyToMessageAllowed(vorgangWithEingang); + var replyAllowed = service.isReplyToMessageAllowed(VorgangWithEingangTestFactory.create()); - assertThat(replyToMessageAllowed).isFalse(); + assertThat(replyAllowed).isEqualTo(expectedReplyAllowed); } @Test @@ -477,15 +505,72 @@ class PostfachMailServiceTest { assertThat(replyToMessageAllowed).isFalse(); } + } - private VorgangWithEingang createVorgangWithServiceKonto(String serviceKontoType) { - return VorgangWithEingangTestFactory.createBuilder() - .header(VorgangHeadTestFactory.createBuilder() - .serviceKonto(ServiceKontoTestFactory.createBuilder() - .type(serviceKontoType) - .build()) - .build()) - .build(); + @Nested + class TestIsReplyAllowed { + + private static final String DUMMY_SERVICE_KONTO_TYPE = LoremIpsum.getInstance().getWords(1); + + @Test + @DisplayName("reply not allowed for given ServiceKonto-type") + void shouldReturnFalseIfPostfachNotConfigured() { + setPostfachConfigGroup(PostfachConfigGroupTestFactory.createBuilder().postfachConfigs(List.of()).build()); + doReturn(false).when(service).isPostfachConfigured(); + + var replyAllowed = service.isReplyAllowed(PostfachConfigTestFactory.TYPE); + + assertThat(replyAllowed).isFalse(); } + + @Test + @DisplayName("given ServiceKonto-type is not configured") + void shouldReturnFalseForNotConfiguredType() { + setPostfachConfigGroup(PostfachConfigGroupTestFactory.createBuilder().postfachConfigs(List.of()).build()); + doReturn(true).when(service).isPostfachConfigured(); + + var replyAllowed = service.isReplyAllowed(DUMMY_SERVICE_KONTO_TYPE); + + assertThat(replyAllowed).isFalse(); + } + + @Test + @DisplayName("given ServiceKonto-type is null") + void shouldReturnFalseForUnknownType() { + setPostfachConfigGroup(PostfachConfigGroupTestFactory.create()); + doReturn(true).when(service).isPostfachConfigured(); + + var replyAllowed = service.isReplyAllowed(null); + + assertThat(replyAllowed).isFalse(); + } + + @Test + @DisplayName("reply not allowed for given ServiceKonto-type") + void shouldReturnFalseIfReplyNotAllowed() { + setPostfachConfigGroup(PostfachConfigGroupTestFactory.createBuilder() + .postfachConfigs(List.of(PostfachConfigTestFactory.createBuilder().replyAllowed(false).build())) + .build()); + doReturn(true).when(service).isPostfachConfigured(); + + var replyAllowed = service.isReplyAllowed(PostfachConfigTestFactory.TYPE); + + assertThat(replyAllowed).isFalse(); + } + + @Test + @DisplayName("reply allowed for given ServiceKonto-type") + void shouldReturnTrueIfReplyIsAllowed() { + setPostfachConfigGroup(PostfachConfigGroupTestFactory.create()); + doReturn(true).when(service).isPostfachConfigured(); + + var replyAllowed = service.isReplyAllowed(PostfachConfigTestFactory.TYPE); + + assertThat(replyAllowed).isTrue(); + } + } + + private void setPostfachConfigGroup(PostfachConfigGroup postfachConfigGroup) { + ReflectionTestUtils.setField(service, "postfachConfigGroup", postfachConfigGroup); } } \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangTestFactory.java index 5923df23e81ce24fdcffa108627b5d94558f2747..5c50fc0b3fb528b426573e4fb44a63593de2fc74 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangTestFactory.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/EingangTestFactory.java @@ -40,7 +40,7 @@ public class EingangTestFactory { public static final String SUBFORM_NAME = "kontakt"; public static final Map<String, Object> SUBFORM = Map.of(SUBFORM_FIELD_NAME, SUBFORM_FIELD_VALUE); - public static final Map<String, Object> AS_MAP = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, SUBFORM_NAME, SUBFORM); + public static final Map<String, Object> AS_MAP = Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, NUMERIC_FIELD_NAME, NUMERIC_FIELD_VALUE, SUBFORM_NAME, SUBFORM); public static Eingang create() { return createBuilder().build(); @@ -52,8 +52,6 @@ public class EingangTestFactory { .antragsteller(AntragstellerTestFactory.create()) .header(EingangHeaderTestFactory.create()) .zustaendigeStelle(ZustaendigeStelleTestFactory.create()) - .formData(Map.of(SINGLE_FIELD_NAME, SINGLE_FIELD_VALUE, - NUMERIC_FIELD_NAME, NUMERIC_FIELD_VALUE, - SUBFORM_NAME, SUBFORM)); + .formData(AS_MAP); } } \ No newline at end of file diff --git a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangTestFactory.java b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangTestFactory.java index f12e5395d16484c5be7abb8146552a5649280842..706f7dc3643035274f9b9470fc721b74d7bb3e61 100644 --- a/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangTestFactory.java +++ b/alfa-service/src/test/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangTestFactory.java @@ -41,6 +41,7 @@ public class VorgangWithEingangTestFactory { .name(NAME) .status(STATUS) .nummer(NUMMER) + .aktenzeichen(AKTENZEICHEN) .createdAt(CREATED_AT) .hasNewPostfachNachricht(true) .header(VorgangHeadTestFactory.create()) diff --git a/alfa-xdomea/pom.xml b/alfa-xdomea/pom.xml index 8ded4007610e3532651eb004f02c86276263f343..4a877ce614d7f3b270517a089f8a80037ecc7f7f 100644 --- a/alfa-xdomea/pom.xml +++ b/alfa-xdomea/pom.xml @@ -1,3 +1,4 @@ +<?xml version="1.0"?> <!-- Copyright (C) 2023 Das Land Schleswig-Holstein vertreten durch den @@ -23,21 +24,19 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>de.ozgcloud.alfa</groupId> <artifactId>alfa</artifactId> - <version>2.2.0-SNAPSHOT</version> + <version>2.3.0-SNAPSHOT</version> </parent> <artifactId>alfa-xdomea</artifactId> - <name>Alfa XDomea</name> - <description>Alfa XDomea implementation</description> + <name>Alfa xdomea</name> + <description>Alfa xdomea implementation</description> <packaging>jar</packaging> <properties> diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AbgabeCreator.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AbgabeCreator.java index 94914c9bb45b167dd4d4577b0522566f62495c1f..3f7b8db4492f288ad2b9bceb2c7dc0ab496294f2 100644 --- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AbgabeCreator.java +++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/AbgabeCreator.java @@ -3,6 +3,7 @@ package de.ozgcloud.alfa.export; import java.util.stream.Stream; import de.xoev.xdomea.AbgabeAbgabe0401; +import de.xoev.xdomea.AkteType; import de.xoev.xdomea.DokumentType; import de.xoev.xdomea.NkAbgabeType; import de.xoev.xdomea.VorgangType; @@ -34,6 +35,11 @@ class AbgabeCreator { return this; } + public AbgabeCreator withAkteType(AkteType akteType) { + getSchriftgutobjekt().setAkte(akteType); + return this; + } + public AbgabeAbgabe0401 create() { return abgabeType; } diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportService.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportService.java index 3f5690be1f58840a358a13f484043a279d3ed3ff..7f63a5a48685328ddd6f41ca86d2f1bd52df6e2b 100644 --- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportService.java +++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/export/ExportService.java @@ -51,6 +51,7 @@ class ExportService { var abgabe = AbgabeCreator.createAbgabeCreator() .withKopf(exportVorgangService.createKopf(vorgangWithEingang)) .withVorgang(exportVorgangService.createVorgangType(vorgangWithEingang)) + .withAkteType(exportVorgangService.createAkteType(vorgangWithEingang)) .withDokumentTypes( exportFileService.createDokumentTypes(ozgFiles.stream(), vorgangWithEingang.getEingang().getHeader().getFormEngineName())) .create(); diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/ExportVorgangService.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/ExportVorgangService.java index e9065991f2beabac2478595cdfb3dafab372f6fd..086a3097893f17956ec76a0e291a2bf5ad99d207 100644 --- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/ExportVorgangService.java +++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/ExportVorgangService.java @@ -1,8 +1,15 @@ package de.ozgcloud.alfa.vorgang; +import java.util.Optional; +import java.util.UUID; + +import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import de.xoev.xdomea.AkteType; +import de.xoev.xdomea.AllgemeineMetadatenType; +import de.xoev.xdomea.IdentifikationObjektType; import de.xoev.xdomea.NkAbgabeType; import de.xoev.xdomea.VorgangType; @@ -29,4 +36,23 @@ public class ExportVorgangService { public NkAbgabeType createKopf(VorgangWithEingang vorgangWithEingang) { return kopfCreator.createKopf(vorgangWithEingang); } + + public AkteType createAkteType(VorgangWithEingang vorgangWithEingang) { + var akteType = new AkteType(); + akteType.setIdentifikation(createIdentifikationObjektType()); + akteType.setAllgemeineMetadaten(createAllgemeineMetadatenType(vorgangWithEingang)); + return akteType; + } + + IdentifikationObjektType createIdentifikationObjektType() { + var identifikationObjektType = new IdentifikationObjektType(); + identifikationObjektType.setID(UUID.randomUUID().toString()); + return identifikationObjektType; + } + + AllgemeineMetadatenType createAllgemeineMetadatenType(VorgangWithEingang vorgangWithEingang) { + var allgemeineMetadatenType = new AllgemeineMetadatenType(); + allgemeineMetadatenType.setKennzeichen(Optional.ofNullable(vorgangWithEingang.getAktenzeichen()).orElse(StringUtils.EMPTY)); + return allgemeineMetadatenType; + } } diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java index f1d47e4de25f507e3897f69927c117a8edd90fd3..04e32a6a67bb855d1d29a621748a4698df013cdd 100644 --- a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java +++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/FormDataMapper.java @@ -30,18 +30,25 @@ class FormDataMapper { private DateConverter dateConverter; public Antragsdaten toAntragsdaten(@NotNull VorgangWithEingang vorgang) { - return Optional.ofNullable(vorgang.getEingang()) - .map(Eingang::getFormData) - .map(this::buildAntragsdaten) - .orElseGet(Antragsdaten::new); - } - - Antragsdaten buildAntragsdaten(Map<?, ?> formData) { var antragsdaten = new Antragsdaten(); - antragsdaten.getItem().addAll(buildItems(formData)); + antragsdaten.getItem().addAll(mapFormData(vorgang)); + antragsdaten.getItem().addAll(mapOtherData(vorgang)); return antragsdaten; } + List<AntragsdatenItemType> mapFormData(VorgangWithEingang vorgang) { + return Optional.ofNullable(vorgang.getEingang()).map(Eingang::getFormData).map(this::mapData).orElse(List.of()); + } + + List<AntragsdatenItemType> mapOtherData(VorgangWithEingang vorgang) { + return Optional.ofNullable(vorgang.getEingang()).map(Eingang::getAntragsteller).map(Antragsteller::getOtherData).map(this::mapData) + .orElse(List.of()); + } + + List<AntragsdatenItemType> mapData(Map<String, Object> data) { + return buildItems(WrappedValueExtractor.extractWrappedValues(data)); + } + List<AntragsdatenItemType> buildItems(Map<?, ?> formData) { var items = new ArrayList<AntragsdatenItemType>(); for (var formDataEntry : formData.entrySet()) { diff --git a/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractor.java b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractor.java new file mode 100644 index 0000000000000000000000000000000000000000..12a2d36bc271932aa84defc5e7d43a0bfa2bafd9 --- /dev/null +++ b/alfa-xdomea/src/main/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractor.java @@ -0,0 +1,36 @@ +package de.ozgcloud.alfa.vorgang; + +import java.util.HashMap; +import java.util.Map; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +class WrappedValueExtractor { + + static final String WRAPPER_KEY = "value"; + + public static Map<String, Object> extractWrappedValues(Map<String, Object> formData) { + Map<String, Object> result = new HashMap<>(); + for (var entry : formData.entrySet()) { + result.put(entry.getKey(), replaceWrappedValueWithDirectValue(entry.getValue())); + } + return result; + } + + @SuppressWarnings("unchecked") + static Object replaceWrappedValueWithDirectValue(Object value) { + if (!(value instanceof Map)) { + return value; + } + Map<String, Object> formData = (Map<String, Object>) value; + return isWrappedValue(formData) ? + replaceWrappedValueWithDirectValue(formData.get(WRAPPER_KEY)) : + extractWrappedValues(formData); + } + + static boolean isWrappedValue(Map<String, Object> formData) { + return formData.containsKey(WRAPPER_KEY) && formData.size() == 1; + } +} diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AbgabeCreatorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AbgabeCreatorTest.java index 9e1524d0fd79e5b379471b53e09b436307a0ef7b..7efbe6cbcca7da55609df8d49d136d518d106134 100644 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AbgabeCreatorTest.java +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AbgabeCreatorTest.java @@ -6,6 +6,7 @@ import java.util.List; import org.junit.jupiter.api.Test; +import de.xoev.xdomea.AkteType; import de.xoev.xdomea.DokumentType; import de.xoev.xdomea.NkAbgabeType; import de.xoev.xdomea.VorgangType; @@ -56,4 +57,13 @@ public class AbgabeCreatorTest { void shouldThrowExceptionIfVorgangNotSet() { assertThatThrownBy(() -> abgabeCreator.withDokumentTypes(dokumentTypes.stream())).isExactlyInstanceOf(IllegalStateException.class); } + + @Test + void shouldSetAkteType() { + var akteType = new AkteType(); + + var abgabeType = abgabeCreator.withAkteType(akteType).create(); + + assertThat(abgabeType.getSchriftgutobjekt().get(0).getAkte()).isEqualTo(akteType); + } } diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AllgemeineMetadatenTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AllgemeineMetadatenTypeTestFactory.java index 380ee3058d81429d22396a87b9d0f5948623419a..fc7dd301486edbb9fc0ba13bef92329bdf208872 100644 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AllgemeineMetadatenTypeTestFactory.java +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/AllgemeineMetadatenTypeTestFactory.java @@ -1,10 +1,16 @@ package de.ozgcloud.alfa.export; +import com.thedeanda.lorem.LoremIpsum; + import de.xoev.xdomea.AllgemeineMetadatenType; public class AllgemeineMetadatenTypeTestFactory { + public static final String KENNZEICHEN = LoremIpsum.getInstance().getWords(1); + public static AllgemeineMetadatenType create() { - return new AllgemeineMetadatenType(); + var allgemeineMetadatenType = new AllgemeineMetadatenType(); + allgemeineMetadatenType.setKennzeichen(KENNZEICHEN); + return allgemeineMetadatenType; } } diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java index 342b1d2e6d5166a7062787664826cfb032e5bd86..5cb5123e7fb35b8ec94ae9a8a4c42a634e4e80c8 100644 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/ExportServiceTest.java @@ -40,6 +40,7 @@ import de.ozgcloud.alfa.vorgang.VorgangWithEingang; import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory; import de.ozgcloud.common.errorhandling.TechnicalException; import de.xoev.xdomea.AbgabeAbgabe0401; +import de.xoev.xdomea.AkteType; import de.xoev.xdomea.DokumentType; import de.xoev.xdomea.NkAbgabeType; import de.xoev.xdomea.VorgangType; @@ -186,6 +187,13 @@ class ExportServiceTest { verify(exportFileService).createDokumentTypes(ozgFiles, EingangHeaderTestFactory.FORM_ENGINE_NAME); } + @Test + void shouldCreateAkteType() { + callService(); + + verify(exportVorgangService).createAkteType(vorgang); + } + @Test void shouldSetKopf() { callService(); @@ -207,6 +215,16 @@ class ExportServiceTest { verify(abgabeCreator).withDokumentTypes(dokumentTypes); } + @Test + void shouldSetAkteType() { + var akteType = new AkteType(); + when(exportVorgangService.createAkteType(vorgang)).thenReturn(akteType); + + callService(); + + verify(abgabeCreator).withAkteType(akteType); + } + @Test void shouldCreateAbgabe() { callService(); diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/IdentifikationObjektTypeTestFactory.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/IdentifikationObjektTypeTestFactory.java index 84353f13e976b9de5d5bf24aed2483a0ff4142e6..9946765cf3e8bb56674da6ed13f4d089b7f3c084 100644 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/IdentifikationObjektTypeTestFactory.java +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/export/IdentifikationObjektTypeTestFactory.java @@ -1,10 +1,16 @@ package de.ozgcloud.alfa.export; +import java.util.UUID; + import de.xoev.xdomea.IdentifikationObjektType; public class IdentifikationObjektTypeTestFactory { + public static final String ID = UUID.randomUUID().toString(); + public static IdentifikationObjektType create() { - return new IdentifikationObjektType(); + var identifikationObjektType = new IdentifikationObjektType(); + identifikationObjektType.setID(ID); + return identifikationObjektType; } } diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java index 94cb0a3ac45e052dd9fb1551e55cefbe0826d062..8116403db510a3af998bb644a0f56f2e5e810f7b 100644 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceITCase.java @@ -29,10 +29,21 @@ class ExportVorgangServiceITCase { class TestMapAntragsdaten { private static final Map<String, Object> FORM_DATA = Map.of( - KEY_STRING, VALUE_STRING, + KEY_STRING, VALUE_STRING + + ); + + private static final Map<String, Object> OTHER_DATA = Map.of( KEY_MAP, Map.of(KEY_COLLECTION, List.of(VALUE_INTEGER)) ); + @Test + void shouldContainSingleAntragsdatenElement() { + var vorgangType = exportVorgangService.createVorgangType(VorgangWithEingangTestFactory.create()); + + assertThat(vorgangType.getAnwendungsspezifischeErweiterungXML().getAny()).hasSize(1).first().isInstanceOf(Antragsdaten.class); + } + @Test void shouldMapSingleField() { var antragsdaten = mapToAntragsdaten(); @@ -77,17 +88,13 @@ class ExportVorgangServiceITCase { } private Antragsdaten mapToAntragsdaten() { - var erweiterungType = exportVorgangService.createVorgangType(buildVorgang()).getAnwendungsspezifischeErweiterungXML(); - - assertThat(erweiterungType.getAny()).hasSize(1).first().isInstanceOf(Antragsdaten.class); - return (Antragsdaten) erweiterungType.getAny().get(0); + var eingang = EingangTestFactory.createBuilder().formData(FORM_DATA) + .antragsteller(AntragstellerTestFactory.createBuilder().otherData(OTHER_DATA).build()) + .build(); + var vorgangWithEingang = VorgangWithEingangTestFactory.createBuilder().eingang(eingang).build(); + var vorgangType = exportVorgangService.createVorgangType(vorgangWithEingang); + return (Antragsdaten) vorgangType.getAnwendungsspezifischeErweiterungXML().getAny().get(0); } - - private VorgangWithEingang buildVorgang() { - var eingang = EingangTestFactory.createBuilder().formData(FORM_DATA).build(); - return VorgangWithEingangTestFactory.createBuilder().eingang(eingang).build(); - } - } } } \ No newline at end of file diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceTest.java index 9601946a7a579c05ada5c2f21dc6dc73f0b3537d..4bf5f5eaf384761f16046c10c23662a344ecabf8 100644 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceTest.java +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/ExportVorgangServiceTest.java @@ -4,11 +4,15 @@ import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; +import de.ozgcloud.alfa.export.AllgemeineMetadatenTypeTestFactory; +import de.ozgcloud.alfa.export.IdentifikationObjektTypeTestFactory; + public class ExportVorgangServiceTest { private final static String VORGANG_ID = "DUMMY_ID"; @@ -21,20 +25,91 @@ public class ExportVorgangServiceTest { @Mock private VorgangService vorgangService; - @BeforeEach - void init() { - when(vorgangService.findVorgangWithEingang(anyString())).thenReturn(vorgang); + @Nested + class TestGetVorgang { + + @BeforeEach + void init() { + when(vorgangService.findVorgangWithEingang(VORGANG_ID)).thenReturn(vorgang); + } + + @Test + void shouldCallVorgangService() { + exportVorgangService.getVorgang(VORGANG_ID); + + verify(vorgangService).findVorgangWithEingang(VORGANG_ID); + } + + @Test + void shouldReturnVorgangWithEingang() { + assertThat(exportVorgangService.getVorgang(VORGANG_ID)).isEqualTo(vorgang); + } + } + + @Nested + class TestCreateAkteType { + + @Test + void shouldCallCreateIdentifikationObjektType() { + exportVorgangService.createAkteType(vorgang); + + verify(exportVorgangService).createIdentifikationObjektType(); + } + + @Test + void shouldSetIdentifikationObjektType() { + var identifikationObjektType = IdentifikationObjektTypeTestFactory.create(); + doReturn(identifikationObjektType).when(exportVorgangService).createIdentifikationObjektType(); + + var akteType = exportVorgangService.createAkteType(vorgang); + + assertThat(akteType.getIdentifikation()).isEqualTo(identifikationObjektType); + } + + @Test + void shouldCallCreateAllgemeineMetadatenType() { + exportVorgangService.createAkteType(vorgang); + + verify(exportVorgangService).createAllgemeineMetadatenType(vorgang); + } + + @Test + void shouldSetAllgemeineMetadatenType() { + var allgemeineMetadatenType = AllgemeineMetadatenTypeTestFactory.create(); + doReturn(allgemeineMetadatenType).when(exportVorgangService).createAllgemeineMetadatenType(vorgang); + + var akteType = exportVorgangService.createAkteType(vorgang); + + assertThat(akteType.getAllgemeineMetadaten()).isEqualTo(allgemeineMetadatenType); + } } - @Test - void shouldCallVorgangService() { - exportVorgangService.getVorgang(VORGANG_ID); + @Nested + class TestCreateIdentifikationObjektType { - verify(vorgangService).findVorgangWithEingang(VORGANG_ID); + @Test + void shouldSetID() { + var identifikationObjektType = exportVorgangService.createIdentifikationObjektType(); + + assertThat(identifikationObjektType.getID()).isNotBlank(); + } } - @Test - void shouldReturnVorgangWithEingang() { - assertThat(exportVorgangService.getVorgang(VORGANG_ID)).isEqualTo(vorgang); + @Nested + class TestCreateAllgemeineMetadatenType { + + @Test + void shouldSetKennzeichen() { + var allgemeineMetadatenType = exportVorgangService.createAllgemeineMetadatenType(vorgang); + + assertThat(allgemeineMetadatenType.getKennzeichen()).isEqualTo(VorgangHeaderTestFactory.AKTENZEICHEN); + } + + @Test + void shouldSetEmptyKennzeichen() { + var akteType = exportVorgangService.createAkteType(VorgangWithEingangTestFactory.createBuilder().aktenzeichen(null).build()); + + assertThat(akteType.getAllgemeineMetadaten().getKennzeichen()).isEmpty(); + } } } diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java index fd5111ad3b4d71b1b3dcdc92de8c5e5bae08ddd0..76557218cfb705d40f2f8a8eeccfef4f0c68d275 100644 --- a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/FormDataMapperTest.java @@ -1,7 +1,6 @@ package de.ozgcloud.alfa.vorgang; import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.time.ZonedDateTime; @@ -9,13 +8,19 @@ import java.util.Collections; import java.util.List; import java.util.Map; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullAndEmptySource; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.MockedStatic; import org.mockito.Spy; +import com.thedeanda.lorem.LoremIpsum; + import de.ozgcloud.alfa.common.DateConverter; import de.xoev.xdomea.AntragsdatenFieldType; import de.xoev.xdomea.AntragsdatenGroupType; @@ -38,66 +43,232 @@ class FormDataMapperTest { @Nested class TestToAntragsdaten { - @Mock - private VorgangWithEingang vorgang; + private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + private final List<AntragsdatenFieldType> formDataItems = List.of(AntragsdatenItemTypeTestFactory.createSingleValueField(), + AntragsdatenItemTypeTestFactory.createSingleValueField()); + private final List<AntragsdatenFieldType> otherDataItems = List.of(AntragsdatenItemTypeTestFactory.createMultiValueField()); @Test - void shouldCallBuildItemType() { - doReturn(new Object()).when(formDataMapper).formatValue(any(), any()); - var vorgang = VorgangWithEingangTestFactory.create(); + void shouldMapFormData() { + mockMapDataMethodsToReturnNotEmptyResults(); formDataMapper.toAntragsdaten(vorgang); - verify(formDataMapper).buildAntragsdaten(vorgang.getEingang().getFormData()); + verify(formDataMapper).mapFormData(vorgang); + } + + @Test + void shouldMapOtherData() { + mockMapDataMethodsToReturnNotEmptyResults(); + + formDataMapper.toAntragsdaten(vorgang); + + verify(formDataMapper).mapOtherData(vorgang); + } + + @Test + void shouldSetItemToEmptyListIfNoDataWasMapped() { + mockMapDataMethodsToReturnEmptyResults(); + + var antragsdaten = formDataMapper.toAntragsdaten(vorgang); + + assertThat(antragsdaten.getItem()).isEmpty(); } @Test - void shouldMapEingangNull() { - var Antragsdaten = formDataMapper.toAntragsdaten(vorgang); + void shouldAddMappedFormDataToAntragsdaten() { + mockMapDataMethodsToReturnNotEmptyResults(); + + var antragsdaten = formDataMapper.toAntragsdaten(vorgang); - assertThat(Antragsdaten.getItem()).isEmpty(); + assertThat(antragsdaten.getItem()).containsAll(formDataItems); } @Test - void shouldMapFormDataNull() { - var eingang = mock(Eingang.class); - when(vorgang.getEingang()).thenReturn(eingang); + void shouldAddMappedOtherDataToAntragsdaten() { + mockMapDataMethodsToReturnNotEmptyResults(); - var Antragsdaten = formDataMapper.toAntragsdaten(vorgang); + var antragsdaten = formDataMapper.toAntragsdaten(vorgang); - assertThat(Antragsdaten.getItem()).isEmpty(); + assertThat(antragsdaten.getItem()).containsAll(otherDataItems); } + private void mockMapDataMethodsToReturnNotEmptyResults() { + doReturn(formDataItems).when(formDataMapper).mapFormData(vorgang); + doReturn(otherDataItems).when(formDataMapper).mapOtherData(vorgang); + } + + private void mockMapDataMethodsToReturnEmptyResults() { + doReturn(List.of()).when(formDataMapper).mapFormData(vorgang); + doReturn(List.of()).when(formDataMapper).mapOtherData(vorgang); + } } @Nested - class TestBuildAntragsdaten { + class TestMapFormData { - private final Map<?,?> formData = EingangTestFactory.create().getFormData(); - private final List<AntragsdatenItemType> items = AntragsdatenItemTypeTestFactory.createAntragsdatenItemTypes(); + private VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + private final List<AntragsdatenFieldType> mapDataResult = List.of(AntragsdatenItemTypeTestFactory.createSingleValueField(), + AntragsdatenItemTypeTestFactory.createSingleValueField()); + + @Test + void shouldReturnEmptyOnNullEingang() { + vorgang = VorgangWithEingangTestFactory.createBuilder().eingang(null).build(); + + var antragsdatenItemTypes = formDataMapper.mapFormData(vorgang); + + assertThat(antragsdatenItemTypes).isEmpty(); + } + + @ParameterizedTest + @NullAndEmptySource + void shouldReturnEmptyOnMissingFormData(Map<String, Object> formData) { + vorgang = VorgangWithEingangTestFactory.createBuilder() + .eingang(EingangTestFactory.createBuilder().formData(formData).build()) + .build(); + + var antragsdatenItemTypes = formDataMapper.mapFormData(vorgang); + + assertThat(antragsdatenItemTypes).isEmpty(); + } + + @Test + void shouldMapData() { + doReturn(List.of()).when(formDataMapper).mapData(EingangTestFactory.AS_MAP); + + formDataMapper.mapFormData(vorgang); + + verify(formDataMapper).mapData(EingangTestFactory.AS_MAP); + } + + @Test + void shouldReturnMappedData() { + doReturn(mapDataResult).when(formDataMapper).mapData(vorgang.getEingang().getFormData()); + + var antragsdatenItemTypes = formDataMapper.mapFormData(vorgang); + + assertThat(antragsdatenItemTypes).containsExactlyElementsOf(mapDataResult); + } + } + + @Nested + class TestMapOtherData { + + private VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + private final List<AntragsdatenFieldType> mapDataResult = List.of(AntragsdatenItemTypeTestFactory.createSingleValueField(), + AntragsdatenItemTypeTestFactory.createSingleValueField()); + + @Test + void shouldReturnEmptyOnNullEingang() { + vorgang = VorgangWithEingangTestFactory.createBuilder().eingang(null).build(); + + var antragsdatenItemTypes = formDataMapper.mapOtherData(vorgang); + + assertThat(antragsdatenItemTypes).isEmpty(); + } + + @Test + void shouldReturnEmptyOnNullAntragsteller() { + vorgang = VorgangWithEingangTestFactory.createBuilder() + .eingang(EingangTestFactory.createBuilder().antragsteller(null).build()) + .build(); + + var antragsdatenItemTypes = formDataMapper.mapOtherData(vorgang); + + assertThat(antragsdatenItemTypes).isEmpty(); + } + + @ParameterizedTest + @NullAndEmptySource + void shouldReturnEmptyOnMissingOtherData(Map<String, Object> otherData) { + vorgang = VorgangWithEingangTestFactory.createBuilder() + .eingang(EingangTestFactory.createBuilder() + .antragsteller(AntragstellerTestFactory.createBuilder() + .otherData(otherData) + .build()) + .build()) + .build(); + + var antragsdatenItemTypes = formDataMapper.mapOtherData(vorgang); + + assertThat(antragsdatenItemTypes).isEmpty(); + } + + @Test + void shouldMapData() { + doReturn(List.of()).when(formDataMapper).mapData(AntragstellerTestFactory.OTHER_DATA); + + formDataMapper.mapOtherData(vorgang); + + verify(formDataMapper).mapData(AntragstellerTestFactory.OTHER_DATA); + } + + @Test + void shouldReturnMappedData() { + doReturn(mapDataResult).when(formDataMapper).mapData(AntragstellerTestFactory.OTHER_DATA); + + var antragsdatenItemTypes = formDataMapper.mapOtherData(vorgang); + + assertThat(antragsdatenItemTypes).containsExactlyElementsOf(mapDataResult); + } + } + + @Nested + class TestMapData { + + private final Map<String, Object> originalData = randomFormData(); + private final Map<String, Object> extractedData = randomFormData(); + private final List<AntragsdatenFieldType> mapDataResult = List.of(AntragsdatenItemTypeTestFactory.createSingleValueField(), + AntragsdatenItemTypeTestFactory.createSingleValueField()); + private MockedStatic<WrappedValueExtractor> wrappedValueExtractor; @BeforeEach void init() { - doReturn(items).when(formDataMapper).buildItems(any()); + wrappedValueExtractor = mockStatic(WrappedValueExtractor.class); + wrappedValueExtractor.when(() -> WrappedValueExtractor.extractWrappedValues(originalData)).thenReturn(extractedData); + doReturn(mapDataResult).when(formDataMapper).buildItems(extractedData); + } + + @AfterEach + void cleanup() { + wrappedValueExtractor.close(); } @Test - void shouldCallBuildItems() { - formDataMapper.buildAntragsdaten(formData); + void shouldCallWrappedValueExtractor() { + formDataMapper.mapData(originalData); + + wrappedValueExtractor.verify(() -> WrappedValueExtractor.extractWrappedValues(originalData)); + } + + @Test + void shouldCallBuildItemsWithExtractedData() { + formDataMapper.mapData(originalData); - verify(formDataMapper).buildItems(formData); + verify(formDataMapper).buildItems(extractedData); } @Test - void shouldFillItems() { - var antragsdaten = formDataMapper.buildAntragsdaten(formData); + void shouldReturnBuildItemsResult() { + var mappedData = formDataMapper.mapData(originalData); - assertThat(antragsdaten.getItem()).containsExactlyElementsOf(items); + assertThat(mappedData).isEqualTo(mapDataResult); + } + + private static Map<String, Object> randomFormData() { + return Map.of(LoremIpsum.getInstance().getWords(1), LoremIpsum.getInstance().getWords(1), + LoremIpsum.getInstance().getWords(1), LoremIpsum.getInstance().getWords(1)); } } @Nested class TestBuildItems { + + private static final String FORMDATA_KEY = "key1"; + private static final String SINGLE_VALUE = "value"; + private static final List<Object> COLLECTION_OF_VALUES = List.of("value"); + private static final Map<String, Object> FORMDATA_SUBMAP = Map.of("key2", "value"); + @Mock private AntragsdatenItemType expectedAntragsdatenItem; @@ -110,27 +281,27 @@ class FormDataMapperTest { @Test void shoulAddSubmap() { - doReturn(expectedAntragsdatenItem).when(formDataMapper).buildAntragsdatenGroup(any(), any()); + doReturn(expectedAntragsdatenItem).when(formDataMapper).buildAntragsdatenGroup(FORMDATA_KEY, FORMDATA_SUBMAP); - var items = formDataMapper.buildItems(Map.of("key", Map.of("key", "value"))); + var items = formDataMapper.buildItems(Map.of(FORMDATA_KEY, FORMDATA_SUBMAP)); assertThat(items).hasSize(1).first().isEqualTo(expectedAntragsdatenItem); } @Test void shouldAddCollection() { - doReturn(expectedAntragsdatenItem).when(formDataMapper).buildMultiValueField(any(), any()); + doReturn(expectedAntragsdatenItem).when(formDataMapper).buildMultiValueField(FORMDATA_KEY, COLLECTION_OF_VALUES); - var items = formDataMapper.buildItems(Map.of("key", List.of("value"))); + var items = formDataMapper.buildItems(Map.of(FORMDATA_KEY, COLLECTION_OF_VALUES)); assertThat(items).hasSize(1).first().isEqualTo(expectedAntragsdatenItem); } @Test void shouldAddSingleValue() { - doReturn(expectedAntragsdatenItem).when(formDataMapper).buildSingleValueField(any(), any()); + doReturn(expectedAntragsdatenItem).when(formDataMapper).buildSingleValueField(FORMDATA_KEY, SINGLE_VALUE); - var items = formDataMapper.buildItems(Map.of("key", "value")); + var items = formDataMapper.buildItems(Map.of(FORMDATA_KEY, SINGLE_VALUE)); assertThat(items).hasSize(1).first().isEqualTo(expectedAntragsdatenItem); } @@ -140,12 +311,13 @@ class FormDataMapperTest { class TestBuildAntragsdatenGroup { private static final String NAME = "name"; - private static final Map<String, Object> FORMDATA_SUBMAP = Map.of("key", "value"); + private static final String FORMDATA_SUBMAP_VALUE = "value"; + private static final Map<String, Object> FORMDATA_SUBMAP = Map.of("key", FORMDATA_SUBMAP_VALUE); private final List<AntragsdatenItemType> items = AntragsdatenItemTypeTestFactory.createAntragsdatenItemTypes(); @Test void shouldSetName() { - doReturn(new Object()).when(formDataMapper).formatValue(any(), any()); + mockFormatValue(); var antragsdatenGroup = formDataMapper.buildAntragsdatenGroup(NAME, FORMDATA_SUBMAP); @@ -154,7 +326,7 @@ class FormDataMapperTest { @Test void shouldSetItems() { - doReturn(items).when(formDataMapper).buildItems(any()); + doReturn(items).when(formDataMapper).buildItems(FORMDATA_SUBMAP); var antragsdatenGroup = (AntragsdatenGroupType) formDataMapper.buildAntragsdatenGroup(NAME, FORMDATA_SUBMAP); @@ -163,12 +335,17 @@ class FormDataMapperTest { @Test void shouldCallBuildItems() { - doReturn(new Object()).when(formDataMapper).formatValue(any(), any()); + mockFormatValue(); formDataMapper.buildAntragsdatenGroup(NAME, FORMDATA_SUBMAP); verify(formDataMapper).buildItems(FORMDATA_SUBMAP); } + + private void mockFormatValue() { + when(datatypeMapper.from(FORMDATA_SUBMAP_VALUE)).thenReturn(DatatypeType.STRING); + doReturn(new Object()).when(formDataMapper).formatValue(DatatypeType.STRING, FORMDATA_SUBMAP_VALUE); + } } @Nested @@ -179,7 +356,7 @@ class FormDataMapperTest { @Test void shouldSetName() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING); + when(datatypeMapper.from(FORMDATA_COLLECTION)).thenReturn(DatatypeType.STRING); var antragsdatenMultiValueFieldType = formDataMapper.buildMultiValueField(NAME, FORMDATA_COLLECTION); @@ -188,7 +365,7 @@ class FormDataMapperTest { @Test void shouldSetType() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING); + when(datatypeMapper.from(FORMDATA_COLLECTION)).thenReturn(DatatypeType.STRING); var antragsdatenMultiValueFieldType = (AntragsdatenFieldType) formDataMapper.buildMultiValueField(NAME, FORMDATA_COLLECTION); @@ -197,8 +374,8 @@ class FormDataMapperTest { @Test void shouldSetValue() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.INTEGER); var formData = List.of(1, 2); + when(datatypeMapper.from(formData)).thenReturn(DatatypeType.INTEGER); var antragsdatenMultiValueFieldType = (AntragsdatenMultiValueFieldType) formDataMapper.buildMultiValueField(NAME, formData); @@ -207,7 +384,7 @@ class FormDataMapperTest { @Test void shouldCallFormatValue() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING); + when(datatypeMapper.from(FORMDATA_COLLECTION)).thenReturn(DatatypeType.STRING); formDataMapper.buildMultiValueField(NAME, FORMDATA_COLLECTION); @@ -223,8 +400,7 @@ class FormDataMapperTest { @Test void shouldSetName() { - doReturn(new Object()).when(formDataMapper).formatValue(any(), any()); - + mockFormatValue(); var antragsdatenSingleValueFieldType = formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE); assertThat(antragsdatenSingleValueFieldType.getName()).isEqualTo(NAME); @@ -232,7 +408,7 @@ class FormDataMapperTest { @Test void shouldSetType() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING); + when(datatypeMapper.from(FORMDATA_VALUE)).thenReturn(DatatypeType.STRING); var antragsdatenSingleValueFieldType = (AntragsdatenFieldType) formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE); @@ -241,7 +417,7 @@ class FormDataMapperTest { @Test void shouldSetValue() { - doReturn(FORMDATA_VALUE).when(formDataMapper).formatValue(any(), any()); + mockFormatValue(); var antragsdatenSingleValueFieldType = (AntragsdatenSingleValueFieldType) formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE); @@ -255,15 +431,19 @@ class FormDataMapperTest { verify(formDataMapper, never()).formatValue(DatatypeType.STRING, null); } - @Test void shouldCallFormatValue() { - when(datatypeMapper.from(any())).thenReturn(DatatypeType.STRING); + when(datatypeMapper.from(FORMDATA_VALUE)).thenReturn(DatatypeType.STRING); formDataMapper.buildSingleValueField(NAME, FORMDATA_VALUE); verify(formDataMapper).formatValue(DatatypeType.STRING, FORMDATA_VALUE); } + + private void mockFormatValue() { + when(datatypeMapper.from(FORMDATA_VALUE)).thenReturn(DatatypeType.STRING); + doReturn(FORMDATA_VALUE).when(formDataMapper).formatValue(DatatypeType.STRING, FORMDATA_VALUE); + } } @Nested diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorITCase.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorITCase.java new file mode 100644 index 0000000000000000000000000000000000000000..2235bb23d85ac3e6a812a49aa88b2ec107a32ea7 --- /dev/null +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorITCase.java @@ -0,0 +1,55 @@ +package de.ozgcloud.alfa.vorgang; + +import static de.ozgcloud.alfa.vorgang.WrappedValueExtractor.*; +import static org.assertj.core.api.Assertions.*; + +import java.util.Map; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +public class WrappedValueExtractorITCase { + + @Nested + class TestExtractWrappedValues { + + @Test + void shouldPreserveWrapperKeyWithoutParent() { + Map<String, Object> formData = Map.of(WRAPPER_KEY, "Kiel"); + + var formDataWithoutValueKeys = WrappedValueExtractor.extractWrappedValues(formData); + + assertThat(formDataWithoutValueKeys).isEqualTo(formData); + } + + @Test + void shouldEliminateWrapperKeyWithoutSiblings() { + Map<String, Object> formData = Map.of("ort", Map.of(WRAPPER_KEY, "Kiel")); + Map<String, Object> expected = Map.of("ort", "Kiel"); + + var formDataWithoutValueKeys = WrappedValueExtractor.extractWrappedValues(formData); + + assertThat(formDataWithoutValueKeys).isEqualTo(expected); + } + + @Test + void shouldPreserveWrapperKeyIfHasSiblings() { + Map<String, Object> formData = Map.of("ort", Map.of(WRAPPER_KEY, "Kiel", "value2", "Kiel")); + + var formDataWithoutValueKeys = WrappedValueExtractor.extractWrappedValues(formData); + + assertThat(formDataWithoutValueKeys).isEqualTo(formData); + } + + @Test + void shouldPreserveNonWrapperKeys() { + Map<String, Object> formData = Map.of("empfangendestelle", + Map.of(WRAPPER_KEY, Map.of("OrganisationseinheitenAuswahl", Map.of(WRAPPER_KEY, "123456")))); + Map<String, Object> expected = Map.of("empfangendestelle", Map.of("OrganisationseinheitenAuswahl", "123456")); + + var formDataWithoutValueKeys = WrappedValueExtractor.extractWrappedValues(formData); + + assertThat(formDataWithoutValueKeys).isEqualTo(expected); + } + } +} diff --git a/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorTest.java b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..419c371d6aaf4f8a75904ec986814ffa4187881b --- /dev/null +++ b/alfa-xdomea/src/test/java/de/ozgcloud/alfa/vorgang/WrappedValueExtractorTest.java @@ -0,0 +1,176 @@ +package de.ozgcloud.alfa.vorgang; + +import static de.ozgcloud.alfa.vorgang.WrappedValueExtractor.*; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +import java.util.Map; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.MockedStatic; + +public class WrappedValueExtractorTest { + + @Nested + class TestExtractWrappedValues { + + private static final String KEY1 = "key1"; + private static final String KEY2 = "key2"; + private static final String KEY3 = "key3"; + + @Captor + private ArgumentCaptor<Object> valueCaptor; + private final Map<String, Object> originalData = Map.of(KEY1, "value1", KEY2, true, KEY3, 100); + private final Map<String, Object> extractedData = Map.of(KEY1, "extracted1", KEY2, "extracted2", KEY3, "extracted3"); + + @Test + void shouldCallReplaceWrappedValueWithDirectValue() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + + WrappedValueExtractor.extractWrappedValues(originalData); + + wrappedValueExtractor.verify(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(valueCaptor.capture()), times( + originalData.size())); + assertThat(valueCaptor.getAllValues()).containsExactlyElementsOf(originalData.values()); + } + } + + @Test + void shouldReturnMapWithReplacedValues() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + wrappedValueExtractor.when(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(originalData.get(KEY1))).thenReturn(extractedData.get(KEY1)); + wrappedValueExtractor.when(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(originalData.get(KEY2))).thenReturn(extractedData.get(KEY2)); + wrappedValueExtractor.when(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(originalData.get(KEY3))).thenReturn(extractedData.get(KEY3)); + + var result = WrappedValueExtractor.extractWrappedValues(originalData); + + assertThat(result).isEqualTo(extractedData); + } + } + + private void unmockMethodUnderTest(MockedStatic<WrappedValueExtractor> wrappedValueExtractor) { + wrappedValueExtractor.when(() -> WrappedValueExtractor.extractWrappedValues(any())).thenCallRealMethod(); + } + } + + @Nested + class TestReplaceWrappedValueWithDirectValue { + + private final String simpleValue = "simple value"; + private final Map<String, Object> mapValue = Map.of("key1", "value1", "key2", "value2"); + private final Map<String, Object> wrappedValue = Map.of(WRAPPER_KEY, "value1"); + + @Test + void shouldReturnValue() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + + var result = WrappedValueExtractor.replaceWrappedValueWithDirectValue(simpleValue); + + assertThat(result).isEqualTo(simpleValue); + } + } + + @Test + void shouldCallIsWrappedValue() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + + WrappedValueExtractor.replaceWrappedValueWithDirectValue(mapValue); + + wrappedValueExtractor.verify(() -> WrappedValueExtractor.isWrappedValue(mapValue)); + } + } + + @Test + void shouldCallItself() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + wrappedValueExtractor.when(() -> WrappedValueExtractor.isWrappedValue(wrappedValue)).thenReturn(true); + + WrappedValueExtractor.replaceWrappedValueWithDirectValue(wrappedValue); + + wrappedValueExtractor.verify(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(wrappedValue.get(WRAPPER_KEY))); + } + } + + @Test + void shouldReturnResultOfCallingItself() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + wrappedValueExtractor.when(() -> WrappedValueExtractor.isWrappedValue(wrappedValue)).thenReturn(true); + + var result = WrappedValueExtractor.replaceWrappedValueWithDirectValue(wrappedValue); + + assertThat(result).isEqualTo(wrappedValue.get(WRAPPER_KEY)); + } + } + + @Test + void shouldCallExtractWrappedValues() { + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + wrappedValueExtractor.when(() -> WrappedValueExtractor.isWrappedValue(mapValue)).thenReturn(false); + + WrappedValueExtractor.replaceWrappedValueWithDirectValue(mapValue); + + wrappedValueExtractor.verify(() -> WrappedValueExtractor.extractWrappedValues(mapValue)); + } + } + + @Test + void shouldReturnResultOfExtractWrappedValues() { + final Map<String, Object> extractVrappedValuesResult = Map.of("resultKey", "resultValue"); + try (MockedStatic<WrappedValueExtractor> wrappedValueExtractor = mockStatic(WrappedValueExtractor.class)) { + unmockMethodUnderTest(wrappedValueExtractor); + wrappedValueExtractor.when(() -> WrappedValueExtractor.isWrappedValue(mapValue)).thenReturn(false); + wrappedValueExtractor.when(() -> WrappedValueExtractor.extractWrappedValues(any())).thenReturn(extractVrappedValuesResult); + + var result = WrappedValueExtractor.replaceWrappedValueWithDirectValue(mapValue); + + assertThat(result).isEqualTo(extractVrappedValuesResult); + } + } + + private void unmockMethodUnderTest(MockedStatic<WrappedValueExtractor> wrappedValueExtractor) { + wrappedValueExtractor.when(() -> WrappedValueExtractor.replaceWrappedValueWithDirectValue(any())).thenCallRealMethod(); + } + } + + @Nested + class TestIsWrappedValue { + + @Test + void shouldReturnTrueIfWrapped() { + var result = WrappedValueExtractor.isWrappedValue(Map.of(WRAPPER_KEY, "value1")); + + assertThat(result).isTrue(); + } + + @Test + void shouldReturnFalseIfHasMultipleEntries() { + var result = WrappedValueExtractor.isWrappedValue(Map.of(WRAPPER_KEY, "value1", "key2", "value2")); + + assertThat(result).isFalse(); + } + + @Test + void shouldReturnFalseIfNotWrapped() { + var result = WrappedValueExtractor.isWrappedValue(Map.of("key1", "value1")); + + assertThat(result).isFalse(); + } + + @Test + void shouldReturnFalseIfEmpty() { + var result = WrappedValueExtractor.isWrappedValue(Map.of()); + + assertThat(result).isFalse(); + } + } +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..1d53587185233e7fb873cd4a72e76b6bab291f1b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6 @@ +{ + "name": "goofy", + "lockfileVersion": 2, + "requires": true, + "packages": {} +} diff --git a/pom.xml b/pom.xml index 6ca4246a58b4fa5a7b9687f98d4de4c1ba6f5fa8..2a72ba53e8e76705ce7785e948bb9fb9711156ae 100644 --- a/pom.xml +++ b/pom.xml @@ -1,3 +1,4 @@ +<?xml version="1.0"?> <!-- Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den @@ -23,9 +24,7 @@ unter der Lizenz sind dem Lizenztext zu entnehmen. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> @@ -36,7 +35,7 @@ <groupId>de.ozgcloud.alfa</groupId> <artifactId>alfa</artifactId> - <version>2.2.0-SNAPSHOT</version> + <version>2.3.0-SNAPSHOT</version> <name>Alfa Parent</name> <packaging>pom</packaging> @@ -51,7 +50,7 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> - <vorgang-manager.version>2.0.0</vorgang-manager.version> + <vorgang-manager.version>2.2.0-SNAPSHOT</vorgang-manager.version> <ozgcloud-common-pdf.version>3.0.0</ozgcloud-common-pdf.version> <user-manager.version>2.0.0</user-manager.version> diff --git a/release-startdev.sh b/release-startdev.sh index 89a0cb7ad075c650489d959a961af8b86749a255..1a0b61139aba8cad4e1b13f77bcb9f9382148b8c 100755 --- a/release-startdev.sh +++ b/release-startdev.sh @@ -16,6 +16,8 @@ echo # projectname/pom.xml:parent,main -> project.parent.version und project.version setzen # PROJECTS="pom.xml:main + alfa-service/pom.xml:parent + alfa-xdomea/pom.xml:parent alfa-server/pom.xml:parent alfa-client/pom.xml:parent " diff --git a/src/main/helm/templates/_helpers.tpl b/src/main/helm/templates/_helpers.tpl index 3e7f6c684152ea241963aa5be95c0f153edc1fa2..604a5f5280aa5f86b7ce69a9b4351b1c84194565 100644 --- a/src/main/helm/templates/_helpers.tpl +++ b/src/main/helm/templates/_helpers.tpl @@ -58,7 +58,7 @@ app.kubernetes.io/namespace: {{ include "app.namespace" . }} {{ printf "%s.%s:9000" ( coalesce .Values.usermanagerName "user-manager" ) .Release.Namespace }} {{- end -}} -{{- define "app.baseUrlDirect" -}} +{{- define "app.baseUrl" -}} {{- required "baseUrl muss angegeben sein" .Values.baseUrl }} {{- end -}} @@ -66,7 +66,7 @@ app.kubernetes.io/namespace: {{ include "app.namespace" . }} {{- if (.Values).usermanagerUrl -}} {{ printf "%s" (.Values).usermanagerUrl }} {{- else -}} -{{ printf "https://%s-%s.%s" (include "app.ozgcloudBezeichner" .) .Values.usermanagerName (include "app.baseUrlDirect" .) }} +{{ printf "https://%s-%s.%s" (include "app.ozgcloudBezeichner" .) .Values.usermanagerName (include "app.baseUrl" .) }} {{- end -}} {{- end -}} @@ -82,8 +82,8 @@ app.kubernetes.io/namespace: {{ include "app.namespace" . }} {{- define "app.ozgcloudBezeichner" -}} {{- required "ozgcloud.bezeichner muss angegeben sein" (.Values.ozgcloud).bezeichner -}} -{{- if lt 27 (len (.Values.ozgcloud).bezeichner) -}} -{{ fail (printf "ozgcloud.bezeichner %s ist zu lang (max. 27 Zeichen)" (.Values.ozgcloud).bezeichner) }} +{{- if lt 46 (len (.Values.ozgcloud).bezeichner) -}} +{{ fail (printf "ozgcloud.bezeichner %s ist zu lang (max. 46 Zeichen)" (.Values.ozgcloud).bezeichner) }} {{- end -}} {{- end -}} @@ -117,8 +117,8 @@ app.kubernetes.io/namespace: {{ include "app.namespace" . }} {{- required "sso.serverUrl muss angegeben sein" (.Values.sso).serverUrl -}} {{- end -}} -{{- define "app.baseUrl" -}} -{{ printf "https://%s.%s" (include "app.ozgcloudBezeichner" .) .Values.baseUrl }} +{{- define "app.baseDomain" -}} +{{- printf "%s.%s" (include "app.ozgcloudBezeichner" .) (include "app.baseUrl" .) }} {{- end -}} {{- define "app.generateKeycloakGroupRessourceName" -}} diff --git a/src/main/helm/templates/ingress.yaml b/src/main/helm/templates/ingress.yaml index 2dea7390aa17f67f6566eacc6b712798b3180551..a4b5ccf04cc1ad289393b35dbeba455a6e9cf2df 100644 --- a/src/main/helm/templates/ingress.yaml +++ b/src/main/helm/templates/ingress.yaml @@ -52,10 +52,10 @@ spec: name: {{ include "app.name" . }} path: '' pathType: ImplementationSpecific - host: {{ trimPrefix "https://" ( include "app.baseUrl" . ) }} + host: {{ include "app.baseDomain" . }} tls: - hosts: - - {{ trimPrefix "https://" ( include "app.baseUrl" . ) }} + - {{ include "app.baseDomain" . }} {{- if (.Values.ingress).tlsSecretName }} secretName: {{ (.Values.ingress).tlsSecretName }} {{- else if ne (.Values).cluster_env "dataport" }} diff --git a/src/main/helm/templates/keycloak-client-crd.yaml b/src/main/helm/templates/keycloak-client-crd.yaml index 2a2b9b48e7ed0cc747f9acfcd18c76d555681ca4..5b0a6f895418a3ba333a2d6d0e83ec102b1ccd6d 100644 --- a/src/main/helm/templates/keycloak-client-crd.yaml +++ b/src/main/helm/templates/keycloak-client-crd.yaml @@ -21,7 +21,7 @@ spec: {{- if $client.client_base_url }} client_base_url: {{ $client.client_base_url }} {{- else }} - client_base_url: {{ include "app.baseUrl" $ }} + client_base_url: https://{{ include "app.baseDomain" $ }} {{- end }} {{- if $client.client_web_origins }} client_web_origins: @@ -30,7 +30,7 @@ spec: {{- end }} {{- else }} client_web_origins: - - {{ include "app.baseUrl" $ }} + - https://{{ include "app.baseDomain" $ }} {{- end }} {{- if $client.override_redirect_uris }} client_redirect_uris: @@ -39,8 +39,8 @@ spec: {{- end }} {{- else }} client_redirect_uris: - - {{ include "app.baseUrl" $ }} - - {{ include "app.baseUrl" $ }}/* + - https://{{ include "app.baseDomain" $ }} + - https://{{ include "app.baseDomain" $ }}/* {{- if $client.additional_redirect_uris }} {{- with $client.additional_redirect_uris }} {{ toYaml . | indent 4 }} diff --git a/src/main/helm/templates/keycloak-user-crd.yaml b/src/main/helm/templates/keycloak-user-crd.yaml index 3bc5c7ab019828a048b44aeaa1fcc3a210d5668b..2901efba99a56a551ce2fa0276e15e14440917b2 100644 --- a/src/main/helm/templates/keycloak-user-crd.yaml +++ b/src/main/helm/templates/keycloak-user-crd.yaml @@ -17,6 +17,7 @@ metadata: {{- end }} spec: keep_after_delete: {{ $.Values.sso.keep_after_delete | default false }} + update_user: {{ $user.update_user | default false }} keycloak_user: username: {{ $user.name | lower }} first_name: {{ $user.first_name | default "" }} diff --git a/src/main/helm/templates/tests/test-ingress-connection.yaml b/src/main/helm/templates/tests/test-ingress-connection.yaml index fad7cd0abb484fe0b8a05b5d4bd843ade88c67a7..d97aecdd4f4fee60a8e330cd98f2a077890c05a5 100644 --- a/src/main/helm/templates/tests/test-ingress-connection.yaml +++ b/src/main/helm/templates/tests/test-ingress-connection.yaml @@ -36,5 +36,5 @@ spec: image: busybox command: ['wget'] args: - - {{ include "app.baseUrl" . }} + - {{ include "app.baseDomain" . }} restartPolicy: Never diff --git a/src/test/helm/deployment_defaults_annotaion_test.yaml b/src/test/helm/deployment_defaults_annotaion_test.yaml index 3ccc5a5f7dbfba8f6eea2beeccdee5a650d661cb..e8185c86db2a54a1ad820863c7eb8ef98bab3324 100644 --- a/src/test/helm/deployment_defaults_annotaion_test.yaml +++ b/src/test/helm/deployment_defaults_annotaion_test.yaml @@ -36,6 +36,8 @@ set: tests: - it: check ingress annotaions for nginx + set: + baseUrl: "test.by.ozg-cloud.de" asserts: - isKind: of: Ingress diff --git a/src/test/helm/deployment_realm_name_length_test.yaml b/src/test/helm/deployment_realm_name_length_test.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8305d800d7d5c5ca3afca6acc2d5f6a6fe0f2bb1 --- /dev/null +++ b/src/test/helm/deployment_realm_name_length_test.yaml @@ -0,0 +1,42 @@ +# +# Copyright (C) 2022 Das Land Schleswig-Holstein vertreten durch den +# Ministerpräsidenten des Landes Schleswig-Holstein +# Staatskanzlei +# Abteilung Digitalisierung und zentrales IT-Management der Landesregierung +# +# Lizenziert unter der EUPL, Version 1.2 oder - sobald +# diese von der Europäischen Kommission genehmigt wurden - +# Folgeversionen der EUPL ("Lizenz"); +# Sie dürfen dieses Werk ausschließlich gemäß +# dieser Lizenz nutzen. +# Eine Kopie der Lizenz finden Sie hier: +# +# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12 +# +# Sofern nicht durch anwendbare Rechtsvorschriften +# gefordert oder in schriftlicher Form vereinbart, wird +# die unter der Lizenz verbreitete Software "so wie sie +# ist", OHNE JEGLICHE GEWÄHRLEISTUNG ODER BEDINGUNGEN - +# ausdrücklich oder stillschweigend - verbreitet. +# Die sprachspezifischen Genehmigungen und Beschränkungen +# unter der Lizenz sind dem Lizenztext zu entnehmen. +# + +suite: test ozgcloud bezeichner length +release: + name: alfa + namespace: sh-helm-test +templates: + - templates/deployment.yaml + +tests: + - it: should fail on bezeichner length longer than 46 characters + template: deployment.yaml + set: + ozgcloud: + bezeichner: test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890 + environment: test + bundesland: by + asserts: + - failedTemplate: + errorMessage: ozgcloud.bezeichner test1234567890123123456789012345678901234567890123456789012345678901234567890123456789012345678904567890 ist zu lang (max. 46 Zeichen) \ No newline at end of file diff --git a/src/test/helm/ingress-nginx-tests.yaml b/src/test/helm/ingress-nginx-tests.yaml index 6b0d88bfaae0f2a17d8fcb853f98fa305deffab7..a377b519ed5a9525826f71b63a6bbf5338f2a126 100644 --- a/src/test/helm/ingress-nginx-tests.yaml +++ b/src/test/helm/ingress-nginx-tests.yaml @@ -33,6 +33,8 @@ set: bundesland: by bezeichner: helm environment: test + baseUrl: test.by.ozg-cloud.de + tests: - it: should create ingress tls asserts: @@ -85,4 +87,16 @@ tests: asserts: - equal: path: spec.ingressClassName - value: nginx \ No newline at end of file + value: nginx + + - it: should create hostname correctly + asserts: + - equal: + path: spec.rules[0].host + value: helm.test.by.ozg-cloud.de + + - it: should create tls hosts name correctly + asserts: + - equal: + path: spec.tls[0].hosts[0] + value: helm.test.by.ozg-cloud.de \ No newline at end of file diff --git a/src/test/helm/keycloak-client-crd-test.yaml b/src/test/helm/keycloak-client-crd-test.yaml index 5b9300d1b6f2b7556411c203804194b4d5a78a52..dd1a33fce2b69b2b5a8140e8d8a68c141f987a9e 100644 --- a/src/test/helm/keycloak-client-crd-test.yaml +++ b/src/test/helm/keycloak-client-crd-test.yaml @@ -36,6 +36,7 @@ set: tests: - it: should contain header data set: + baseUrl: "test.by.ozg-cloud.de" sso: keycloak_clients: - client_name: alfa @@ -46,6 +47,7 @@ tests: of: OzgCloudKeycloakClient - it: should have metadata set: + baseUrl: "test.by.ozg-cloud.de" sso: keycloak_clients: - client_name: alfa @@ -58,6 +60,7 @@ tests: value: by-helm-test - it: should contain header data for kopOperator set: + baseUrl: "test.by.ozg-cloud.de" sso: keycloak_clients: - client_name: alfa @@ -69,6 +72,7 @@ tests: of: KopKeycloakClient - it: should have annotations for kopOperator set: + baseUrl: "test.by.ozg-cloud.de" sso: keycloak_clients: - client_name: alfa diff --git a/src/test/helm/keycloak-user-crd-test.yaml b/src/test/helm/keycloak-user-crd-test.yaml index 0685f872b3999b9e79ef7a532b9f558a7893d30a..31dd7d234885048a8ca2bcbd8b93cdec835f6a69 100644 --- a/src/test/helm/keycloak-user-crd-test.yaml +++ b/src/test/helm/keycloak-user-crd-test.yaml @@ -563,4 +563,25 @@ tests: - name: kop asserts: - hasDocuments: - count: 0 \ No newline at end of file + count: 0 + + - it: should set updateUser + set: + sso: + api_users: + - name: testapiuser + update_user: true + asserts: + - equal: + path: spec.update_user + value: true + + - it: should set default updateUser to false + set: + sso: + api_users: + - name: testapiuser + asserts: + - equal: + path: spec.update_user + value: false \ No newline at end of file