diff --git a/goofy-client/apps/goofy-e2e/src/fixtures/user-main/user_dorothea.json b/goofy-client/apps/goofy-e2e/src/fixtures/user-main/user_dorothea.json index a8ba2621cc268762b32f6b018cead29fcade336d..11aacfe7fa16de46359039d010d0d820cdc71c50 100644 --- a/goofy-client/apps/goofy-e2e/src/fixtures/user-main/user_dorothea.json +++ b/goofy-client/apps/goofy-e2e/src/fixtures/user-main/user_dorothea.json @@ -4,6 +4,7 @@ "firstName": "Dorothea", "lastName": "Doe", "fullName": "Dorothea Doe", + "email": "dorothea.doe@ozg-sh.de", "initials": "DD", "dataTestId": "Dorothea_Doe", "clientRoles": ["VERWALTUNG_USER"], diff --git a/goofy-client/apps/goofy-e2e/src/fixtures/user-main/user_sabine.json b/goofy-client/apps/goofy-e2e/src/fixtures/user-main/user_sabine.json index 130d36c8ec21f9bc4d8d1cc8660ebcc7153a1ae9..c608f053532e41204138be4cb64007efe5417a9e 100644 --- a/goofy-client/apps/goofy-e2e/src/fixtures/user-main/user_sabine.json +++ b/goofy-client/apps/goofy-e2e/src/fixtures/user-main/user_sabine.json @@ -4,9 +4,9 @@ "firstName": "Sabine", "lastName": "Sach", "fullName": "Sabine Sach", - "email": "susanne.fischer.dataport+sabine@gmail.com", + "email": "sabine.sach@ozg-sh.de", "initials": "SS", "dataTestId": "Sabine_Sach", "clientRoles": ["VERWALTUNG_USER"], "groups": ["E2E Tests"] -} \ No newline at end of file +} diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/interceptor/interceptor-unauthorized.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/interceptor/interceptor-unauthorized.e2e-spec.ts index 3fea971e8b5953ddbbb0b91929eeba20a7bcb989..c1dd2f5a8d0f1992cd38bb2d425b72191d672923 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/interceptor/interceptor-unauthorized.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/interceptor/interceptor-unauthorized.e2e-spec.ts @@ -33,6 +33,8 @@ import { contains, exist, notExist } from '../../../support/cypress.util'; import { loginAsSabine } from '../../../support/user-util'; 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.skip('Interceptor unauthorized', () => { const mainPage: MainPage = new MainPage(); const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/kommentar-attachment/kommentar-attachment.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/kommentar-attachment/kommentar-attachment.e2e-spec.ts index 02d5277b261b375b2a21f376eb1e915c6c5306f9..680f7f6bfc39e0121a9c8fd8753216d8c8b42633 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/kommentar-attachment/kommentar-attachment.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/kommentar-attachment/kommentar-attachment.e2e-spec.ts @@ -125,7 +125,7 @@ describe('Kommentar attachments', () => { }); }); - describe.skip('Download Kommentar attachments', () => { + describe('Download Kommentar attachments', () => { it('should upload attachment', () => { kommentarContainer.getKommentar(kommentarText).getRoot().click(); waitForSpinnerToDisappear(); diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-assign-unassign.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-assign-unassign.e2e-spec.ts index c89861dbe0b3fb04a43e749b589969f080a06adc..e267803ff8184d7680b35e73605a6cd5826aee49 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-assign-unassign.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-assign-unassign.e2e-spec.ts @@ -33,7 +33,7 @@ import { enter, exist, haveText, notExist } from '../../../support/cypress.util' import { getUserDorothea, getUserManagerUserDorothea, getUserManagerUserSabine, getUserSabine, initUsermanagerUsers, loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang } from '../../../support/vorgang-util'; -describe.skip('User Profile im ausgewählten Vorgang', () => { +describe('User Profile im ausgewählten Vorgang', () => { const mainPage: MainPage = new MainPage(); const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); @@ -114,7 +114,7 @@ describe.skip('User Profile im ausgewählten Vorgang', () => { notExist(userProfileContainer.getSearchContainer().getError()); }) - it.skip('should show assign icon', () => { + it('should show assign icon', { defaultCommandTimeout: 30000 }, () => { waitForSpinnerToDisappear(); exist(userProfileContainer.getIconContainer().getAssignedIcon()); haveText(userProfileContainer.getIconContainer().getAssignedIcon(), userSabine.initials) @@ -166,7 +166,8 @@ describe.skip('User Profile im ausgewählten Vorgang', () => { notExist(userProfileContainer.getSearchContainer().getError()); }) - it('should show assign icon', () => { + it('should show assign icon', { defaultCommandTimeout: 30000 }, () => { + waitForSpinnerToDisappear(); // TODO Hier muss aufs Verarbeiten im Backend gewartet werden - oder: wait(500) exist(userProfileContainer.getIconContainer().getAssignedIcon()); haveText(userProfileContainer.getIconContainer().getAssignedIcon(), userDorothea.initials) diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-in-postfach-nachricht-error.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-in-postfach-nachricht-error.e2e-spec.ts index bff338c11977880308688cdf3fa334945e68f3cb..f5557de7cb31ca4599ac2ee831d984c1e1dadf3f 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-in-postfach-nachricht-error.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/user-profile/user-profile-icon-in-postfach-nachricht-error.e2e-spec.ts @@ -31,8 +31,8 @@ import { VorgangPage } from '../../../page-objects/vorgang.po'; 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 { createPostfachNachrichtReplyItem, createVorgangAttachedItem, initVorgangAttachedItem } from '../../../support/vorgang-attached-item-util'; -import { createVorgang, initVorgang } from '../../../support/vorgang-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(); @@ -49,8 +49,8 @@ describe('Postfach nachricht user profile on backend error', () => { direction: DirectionE2E.OUT, sentAt: '2022-12-02T15:00:00.790Z[UTC]', sentSuccessful: true - } - const vorgangAttachedItem: VorgangAttachedItemE2E = { ...createVorgangAttachedItem(), item: postfachMailItem }; + }; + const vorgangAttachedItem: VorgangAttachedItemE2E = { ...createPostfachNachrichtAttachedItem(objectIds[0], vorgang._id.$oid), item: postfachMailItem }; before(() => { initVorgang(vorgang); diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts index df8c35cb98f7885e7655de3e46adc9db747ecbc7..6ad3cbb5641c25016bec1d267f1733ce6b00b249 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-detailansicht/vorgang-detailansicht.filtered-by-organisationseinheit.e2e-spec.ts @@ -33,7 +33,9 @@ import { MessagesE2E } from '../../../support/messages'; import { loginAsKfinder, loginAsKordner, loginAsZonk } from '../../../support/user-util'; import { buildVorgang, createVorgang, createVorgangUriById, initVorgaenge } from '../../../support/vorgang-util'; -describe.skip('Vorgang-detailansicht filtered by organisationseinheit', () => { +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(); @@ -73,7 +75,7 @@ describe.skip('Vorgang-detailansicht filtered by organisationseinheit', () => { exist(vorgangList.getRoot()); }) - it('should open detailpage', () => { + it('should open detailpage', { defaultCommandTimeout }, () => { visitUrl(authorizedUrl); waitforSpinnerToAppear(); @@ -82,7 +84,7 @@ describe.skip('Vorgang-detailansicht filtered by organisationseinheit', () => { exist(detailPage.getRoot()); }) - it('should not open detailpage', () => { + it('should not open detailpage', { defaultCommandTimeout }, () => { visitUrl(forbiddenUrl); waitforSpinnerToAppear(); @@ -111,7 +113,7 @@ describe.skip('Vorgang-detailansicht filtered by organisationseinheit', () => { exist(vorgangList.getRoot()); }) - it('should open detailpage', () => { + it('should open detailpage', { defaultCommandTimeout }, () => { visitUrl(authorizedUrl); waitforSpinnerToAppear(); @@ -120,7 +122,7 @@ describe.skip('Vorgang-detailansicht filtered by organisationseinheit', () => { exist(detailPage.getRoot()); }) - it('should not open detailpage', () => { + it('should not open detailpage', { defaultCommandTimeout }, () => { visitUrl(forbiddenUrl); waitforSpinnerToAppear(); diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-list/vorgang-view-wiedervorlagen.pages.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-list/vorgang-view-wiedervorlagen.pages.e2e-spec.ts index 3319539cce31bc2cb32f6af01032ef523c2b6789..b43658ea8fe8054cc69c62d1b995ef69accea3f1 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-list/vorgang-view-wiedervorlagen.pages.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/vorgang-list/vorgang-view-wiedervorlagen.pages.e2e-spec.ts @@ -17,7 +17,7 @@ import { Interception } from 'cypress/types/net-stubbing'; registerLocaleData(localeDe, 'de', localeDeExtra); -describe.skip('VorgangList View Wiedervorlagen', () => { +describe('VorgangList View Wiedervorlagen', () => { const mainPage: MainPage = new MainPage(); const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts index a41fb5862b75f88558d557b12f77509576c8dfc4..f3f81417223f0b351ef9711bd9644e8a644960e1 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage-attachment/wiedervorlage-attachment.e2e-spec.ts @@ -42,7 +42,7 @@ import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang, objectIds } from '../../../support/vorgang-util'; import { createWiedervorlageAttachedItem, createWiedervorlageItem } from '../../../support/wiedervorlage-util'; -describe.skip('Wiedervorlage attachments', () => { +describe('Wiedervorlage attachments', () => { const mainPage: MainPage = new MainPage(); const snackBar: SnackBarE2EComponent = mainPage.getSnackBar(); diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage-authorize-by-role.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage-authorize-by-role.e2e-spec.ts index f1a8524cbfc7916ff755480255dcfb42b62c6583..3c1d4deb32e5ae13d9de544ca48db5b611d1263c 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage-authorize-by-role.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage-authorize-by-role.e2e-spec.ts @@ -34,7 +34,7 @@ import { buildVorgang, initVorgaenge } from 'apps/goofy-e2e/src/support/vorgang- import { createWiedervorlageNeuUriByVorgangId } from 'apps/goofy-e2e/src/support/wiedervorlage-util'; import { dropCollections } from '../../../support/cypress-helper'; -describe.skip('Wiedervorlage should be authorized by role', () => { +describe('Wiedervorlage should be authorized by role', () => { const mainPage: MainPage = new MainPage(); const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.e2e-spec.ts index 4b56971cae221e9e62b409e6c13fa9f21cc1d1e5..bf77d79dacff2e909c12074011363e1d445e68b4 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.e2e-spec.ts @@ -42,7 +42,7 @@ import { createVorgang, initVorgaenge } from '../../../support/vorgang-util'; registerLocaleData(localeDe, 'de', localeDeExtra); -describe.skip('Wiedervorlage', () => { +describe('Wiedervorlage', () => { const mainPage: MainPage = new MainPage(); const vorgangList: VorgangListE2EComponent = mainPage.getVorgangList(); const snackbar: SnackBarE2EComponent = mainPage.getSnackBar(); diff --git a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.erledigen.e2e-spec.ts b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.erledigen.e2e-spec.ts index bc89021957f02597a88d177fb394b3f6976aa3b1..000e8fb12d3357f5360bc3cc3f00678a289a0c65 100644 --- a/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.erledigen.e2e-spec.ts +++ b/goofy-client/apps/goofy-e2e/src/integration/main-tests/wiedervorlage/wiedervorlage.erledigen.e2e-spec.ts @@ -41,7 +41,7 @@ import { loginAsSabine } from '../../../support/user-util'; import { createVorgang, initVorgang, objectIds } from '../../../support/vorgang-util'; import { createWiedervorlageAttachedItem, createWiedervorlageItem } from '../../../support/wiedervorlage-util'; -describe.skip('Wiedervorlage erledigen/wiedereroeffnen', () => { +describe('Wiedervorlage erledigen/wiedereroeffnen', () => { const mainPage: MainPage = new MainPage(); const views: VorgangViewsE2EComponent = mainPage.getViews(); @@ -255,7 +255,8 @@ describe.skip('Wiedervorlage erledigen/wiedereroeffnen', () => { }) - describe('View item icon', () => { + //Test an die richtige Stelle verschieben und den Test vereinfachen + describe.skip('View item icon', () => { const wiedervorlage: WiedervorlageInVorgangE2EComponent = wiedervorlageContainerInVorgang.getWiedervorlage(wiedervorlageZumWiedereroeffnen.betreff); const locatorIconIsOverdue: string = 'wiedervorlage-icon-is-overdue'; diff --git a/goofy-client/libs/api-root-shared/src/lib/api-root.service.ts b/goofy-client/libs/api-root-shared/src/lib/api-root.service.ts index 018858adf34bcf51e6a4f1180f5019f69456124c..bb39fd530a28972a77c50bb365f3f7a8c5ef9006 100644 --- a/goofy-client/libs/api-root-shared/src/lib/api-root.service.ts +++ b/goofy-client/libs/api-root-shared/src/lib/api-root.service.ts @@ -39,7 +39,7 @@ export class ApiRootService { public getApiRoot(): Observable<StateResource<ApiRootResource>> { doIfLoadingRequired(this.apiRoot$.value, () => this.loadApiRoot()) - return this.apiRoot$; + return this.apiRoot$.asObservable(); } private loadApiRoot(): void { diff --git a/goofy-client/libs/command-shared/src/index.ts b/goofy-client/libs/command-shared/src/index.ts index 2c8fd7566c3f074b39eb34b5264f231609800c67..db07aebcac401457822e15eb801f847861b3a494 100644 --- a/goofy-client/libs/command-shared/src/index.ts +++ b/goofy-client/libs/command-shared/src/index.ts @@ -23,6 +23,7 @@ */ export * from './lib/+state/command.actions'; export * from './lib/command-shared.module'; +export * from './lib/command.message'; export * from './lib/command.model'; export * from './lib/command.service'; export * from './lib/command.util'; diff --git a/goofy-client/libs/command-shared/src/lib/+state/command.effects.ts b/goofy-client/libs/command-shared/src/lib/+state/command.effects.ts index cdcc583478b5671739e78ea6fed0ff94eb81490a..ca1f5b3f9796842bb6c08053c9c45f80ac99e591 100644 --- a/goofy-client/libs/command-shared/src/lib/+state/command.effects.ts +++ b/goofy-client/libs/command-shared/src/lib/+state/command.effects.ts @@ -21,7 +21,7 @@ export class CommandEffects { 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))) + catchError(error => of(props.failureAction(error.error))) )) )); diff --git a/goofy-client/libs/command-shared/src/lib/command.repository.spec.ts b/goofy-client/libs/command-shared/src/lib/command.repository.spec.ts index 991ed85ea753539cfcf49534b1791b3ff0d0bc90..82680bf0d234464e2076c2141e8f7264891e8a4a 100644 --- a/goofy-client/libs/command-shared/src/lib/command.repository.spec.ts +++ b/goofy-client/libs/command-shared/src/lib/command.repository.spec.ts @@ -117,7 +117,7 @@ describe('CommandRepository', () => { it('should call resourceWrapper with revokeLinkRel and command order', () => { repository.revokeCommand(commandResource); - expect(resourceWrapper.patch).toHaveBeenCalledWith(CommandLinkRel.REVOKE, { status: CommandStatus.REVOKED, order: commandResource.order }) + expect(resourceWrapper.patch).toHaveBeenCalledWith(CommandLinkRel.REVOKE, { status: CommandStatus.REVOKED }) }) it('should return value', () => { diff --git a/goofy-client/libs/command-shared/src/lib/command.repository.ts b/goofy-client/libs/command-shared/src/lib/command.repository.ts index 5e47e5a98251d2cf0d8eac0abef4db77c674c2c4..60b918b6fd9e6fc776294964fb50ba38cb2b6b56 100644 --- a/goofy-client/libs/command-shared/src/lib/command.repository.ts +++ b/goofy-client/libs/command-shared/src/lib/command.repository.ts @@ -45,7 +45,7 @@ export class CommandRepository { } public revokeCommand(resource: CommandResource): Observable<CommandResource> { - return this.resourceFactory.from(resource).patch(CommandLinkRel.REVOKE, { status: CommandStatus.REVOKED, order: resource.order }); + return this.resourceFactory.from(resource).patch(CommandLinkRel.REVOKE, { status: CommandStatus.REVOKED }); } public getEffectedResource<T>(command: CommandResource): Observable<T> { diff --git a/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.actions.ts b/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.actions.ts index 59f29e65fe9288ae5a8587ab5a479c32ba1a6933..c3a62b795e46767355136240ed7621ae7a31cda3 100644 --- a/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.actions.ts +++ b/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.actions.ts @@ -1,4 +1,5 @@ -import { ApiErrorAction, TypedActionCreatorWithProps } from '@goofy-client/tech-shared'; +import { HttpErrorResponse } from '@angular/common/http'; +import { ApiErrorAction, TypedActionCreator, TypedActionCreatorWithProps } from '@goofy-client/tech-shared'; import { VorgangWithEingangAction } from '@goofy-client/vorgang-shared'; import { createAction, props } from '@ngrx/store'; import { LoeschAnforderungResource } from '../loesch-anforderung.model'; @@ -10,3 +11,11 @@ export interface LoeschAnforderungProps { 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 +} + +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 diff --git a/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.spec.ts b/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.spec.ts index a7bbea78f6ce1790ac6fb504c9bafc138e13c22b..610952a3b1c80a93fe37b4a3508ea9edc0c4ab75 100644 --- a/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.spec.ts +++ b/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.spec.ts @@ -1,7 +1,9 @@ +import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { TestBed } from '@angular/core/testing'; -import { CommandOrder, CommandResource } from '@goofy-client/command-shared'; +import { COMMAND_ERROR_MESSAGES, CommandErrorMessage, CommandOrder, CommandResource } from '@goofy-client/command-shared'; +import { NavigationService } from '@goofy-client/navigation-shared'; import { ApiError } from '@goofy-client/tech-shared'; -import { mock } from '@goofy-client/test-utils'; +import { Mock, mock } from '@goofy-client/test-utils'; import { SnackBarService } from '@goofy-client/ui'; import { VorgangWithEingangLinkRel, VorgangWithEingangResource } from '@goofy-client/vorgang-shared'; import { provideMockActions } from '@ngrx/effects/testing'; @@ -9,7 +11,7 @@ import { Action } from '@ngrx/store'; import { provideMockStore } from '@ngrx/store/testing'; import { cold, hot } from 'jest-marbles'; import { createCommandResource } from 'libs/command-shared/test/command'; -import { createApiError } from 'libs/tech-shared/test/error'; +import { createApiError, createHttpErrorResponse } from 'libs/tech-shared/test/error'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { Observable, of } from 'rxjs'; import { createLoeschAnforderungResource } from '../../../test/loesch-anforderung'; @@ -17,6 +19,8 @@ import { LoeschAnforderungResource } from '../loesch-anforderung.model'; import { LoeschAnforderungEffects } from './loesch-anforderung.effects'; import { LoeschAnforderungRepository } from './loesch-anforderung.repository'; +import faker from '@faker-js/faker'; + import * as CommandActions from '../../../../command-shared/src/lib/+state/command.actions'; import * as VorgangActions from '../../../../vorgang-shared/src/lib/+state/vorgang.actions'; import * as LoeschAnforderungActions from './loesch-anforderung.actions'; @@ -25,8 +29,9 @@ describe('LoeschAnforderungEffects', () => { let actions: Observable<Action>; let effects: LoeschAnforderungEffects; - const repository = mock(LoeschAnforderungRepository); - const snackbarService = mock(SnackBarService); + const repository: Mock<LoeschAnforderungRepository> = mock(LoeschAnforderungRepository); + const snackbarService: Mock<SnackBarService> = mock(SnackBarService); + const navigationService: Mock<NavigationService> = mock(NavigationService); beforeEach(() => { TestBed.configureTestingModule({ @@ -41,6 +46,10 @@ describe('LoeschAnforderungEffects', () => { { provide: SnackBarService, useValue: snackbarService + }, + { + provide: NavigationService, + useValue: navigationService } ] }); @@ -97,4 +106,41 @@ describe('LoeschAnforderungEffects', () => { 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 gelöscht.'); + }) + + it('should navigate to overview', () => { + actions = of(action) + + effects.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure$.subscribe(); + + expect(navigationService.navigate).toHaveBeenCalledWith(overviewUrl); + }) + }) }); \ No newline at end of file diff --git a/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.ts b/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.ts index c5b8341c8def5d9fdff96b9a3abbf711d48fb7ad..81efedebcfdcc4e75df73c7913a8a9e61a1eed6c 100644 --- a/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.ts +++ b/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.effects.ts @@ -1,14 +1,15 @@ import { Injectable } from '@angular/core'; -import { CommandProps } from '@goofy-client/command-shared'; -import { getApiErrorFromHttpErrorResponse } from '@goofy-client/tech-shared'; +import { COMMAND_ERROR_MESSAGES, CREATE_COMMAND_MESSAGE_BY_ORDER, CommandErrorMessage, CommandOrder, CommandProps } from '@goofy-client/command-shared'; +import { NavigationService } from '@goofy-client/navigation-shared'; +import { getApiErrorFromHttpErrorResponse, isNotFound } from '@goofy-client/tech-shared'; import { SnackBarService } from '@goofy-client/ui'; import { VorgangWithEingangAction, VorgangWithEingangLinkRel } from '@goofy-client/vorgang-shared'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { hasLink } from '@ngxp/rest'; -import { CREATE_COMMAND_MESSAGE_BY_ORDER } from 'libs/command-shared/src/lib/command.message'; import { of } from 'rxjs'; import { catchError, filter, map, switchMap, tap } from 'rxjs/operators'; import { isVorgangLoeschenCommand } from '../loesch-anforderung.util'; +import { loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps } from './loesch-anforderung.actions'; import { LoeschAnforderungRepository } from './loesch-anforderung.repository'; import * as CommandActions from '../../../../command-shared/src/lib/+state/command.actions'; @@ -18,7 +19,7 @@ import * as LoeschAnforderungActions from './loesch-anforderung.actions'; @Injectable() export class LoeschAnforderungEffects { - constructor(private readonly actions$: Actions, private repository: LoeschAnforderungRepository, private snackbarService: SnackBarService) { } + 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)), @@ -30,6 +31,19 @@ export class LoeschAnforderungEffects { 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])) + 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 }); + + loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure$ = createEffect(() => this.actions$.pipe(ofType(LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure), + filter((props: loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps) => isNotFound(props.error.error.status)), + tap((props: loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailureProps) => { + this.snackBarService.showInfo(CREATE_COMMAND_MESSAGE_BY_ORDER[CommandOrder.VORGANG_LOESCHEN]); + this.navigationService.navigate(props.overviewUrl); + }) ), { dispatch: false }); } \ No newline at end of file diff --git a/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.spec.ts b/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.spec.ts index 2a3f9895d9842c13dc8f7851ea9554379a3ec13e..77d764b3e10b963b6ef9839f7618f595b87ccd0e 100644 --- a/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.spec.ts +++ b/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.spec.ts @@ -1,6 +1,8 @@ import { CommandOrder, CommandResource } from '@goofy-client/command-shared'; import { ApiError, createEmptyStateResource, createErrorStateResource, createStateResource } from '@goofy-client/tech-shared'; +import { VorgangWithEingangResource } from '@goofy-client/vorgang-shared'; import { Action } from '@ngrx/store'; +import { TypedAction } from '@ngrx/store/src/models'; import { createCommand, createCommandResource } from 'libs/command-shared/test/command'; import { createLoeschAnforderungResource } from 'libs/loesch-anforderung-shared/test/loesch-anforderung'; import { createApiError } from 'libs/tech-shared/test/error'; @@ -12,6 +14,7 @@ import { LoeschAnforderungState, initialState, reducer } from './loesch-anforder import * as CommandActions from '../../../../command-shared/src/lib/+state/command.actions'; import * as NavigationActions from '../../../../navigation-shared/src/lib/+state/navigation.actions'; +import * as VorgangActions from '../../../../vorgang-shared/src/lib/+state/vorgang.actions'; import * as LoeschAnforderungActions from './loesch-anforderung.actions'; describe('LoeschAnforderung Reducer', () => { @@ -167,6 +170,19 @@ describe('LoeschAnforderung Reducer', () => { }) }) + 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', () => { @@ -180,39 +196,79 @@ describe('LoeschAnforderung Reducer', () => { }) }) + 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 = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); + const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); - const state: LoeschAnforderungState = reducer({ - ...initialState, - loeschenAnfordernCommand: createStateResource(createCommandResource()) - }, action); + const filledState: LoeschAnforderungState = { ...initialState, loeschenAnfordernCommand: createStateResource(createCommandResource()) }; + const state: LoeschAnforderungState = reducer(filledState, action); expect(state.loeschenAnfordernCommand).toEqual(createEmptyStateResource()); }) it('should clear loeschAnforderung', () => { - const action = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); + const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); - const state: LoeschAnforderungState = reducer({ - ...initialState, - loeschAnforderung: createStateResource(createLoeschAnforderungResource()) - }, action); + const filledState: LoeschAnforderungState = { ...initialState, loeschAnforderung: createStateResource(createLoeschAnforderungResource()) }; + const state: LoeschAnforderungState = reducer(filledState, action); expect(state.loeschAnforderung).toEqual(createEmptyStateResource()); }) it('should clear vorgangLoeschenCommand', () => { - const action = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); + const action: TypedAction<string> = NavigationActions.updateCurrentRouteData({ routeData: createRouteData() }); - const state: LoeschAnforderungState = reducer({ - ...initialState, - vorgangLoeschenCommand: createStateResource(createCommandResource()) - }, action); + 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 diff --git a/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.ts b/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.ts index 3b260c56252be8632d252bff638f10e0eb42d860..4298806cb95901b5f1f05aad5d0ff6d0554ce6c9 100644 --- a/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.ts +++ b/goofy-client/libs/loesch-anforderung-shared/src/lib/+state/loesch-anforderung.reducer.ts @@ -1,5 +1,5 @@ -import { CommandProps, CommandResource, CreateCommandProps } from '@goofy-client/command-shared'; -import { ApiErrorAction, StateResource, createEmptyStateResource, createErrorStateResource, createStateResource } from '@goofy-client/tech-shared'; +import { CommandProps, CommandResource, CreateCommandFailureProps, CreateCommandProps } from '@goofy-client/command-shared'; +import { ApiError, ApiErrorAction, StateResource, createEmptyStateResource, createErrorStateResource, createStateResource } from '@goofy-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'; @@ -7,6 +7,7 @@ import { LoeschAnforderungProps } from './loesch-anforderung.actions'; import * as CommandActions from '../../../../command-shared/src/lib/+state/command.actions'; import * as NavigationActions from '../../../../navigation-shared/src/lib/+state/navigation.actions'; +import * as VorgangActions from '../../../../vorgang-shared/src/lib/+state/vorgang.actions'; import * as LoeschAnforderungActions from './loesch-anforderung.actions'; export const LOESCH_ANFORDERUNG_FEATURE_KEY = 'LoeschAnforderungState'; @@ -83,6 +84,12 @@ const loeschAnforderungReducer: ActionReducer<LoeschAnforderungState, Action> = 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, @@ -90,13 +97,25 @@ const loeschAnforderungReducer: ActionReducer<LoeschAnforderungState, Action> = } : state; }), + //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() + vorgangLoeschenCommand: createEmptyStateResource(), + loeschAnforderungZuruecknehmenCommand: createEmptyStateResource() } }) ); diff --git a/goofy-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.spec.ts b/goofy-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.spec.ts index 1465197f8987932afc94940c56b9bbef90244caf..4c4f07b17dba592aa7d1b261ea3e257c43513063 100644 --- a/goofy-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.spec.ts +++ b/goofy-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.spec.ts @@ -1,13 +1,15 @@ +import { HttpStatusCode } from '@angular/common/http'; import faker from '@faker-js/faker'; import { CommandResource } from '@goofy-client/command-shared'; import { NavigationService } from '@goofy-client/navigation-shared'; -import { createEmptyStateResource, createStateResource } from '@goofy-client/tech-shared'; -import { VorgangService, VorgangWithEingangResource } from '@goofy-client/vorgang-shared'; +import { StateResource, createStateResource } from '@goofy-client/tech-shared'; +import { AdditionalActions, VorgangService, VorgangWithEingangResource } from '@goofy-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'; import { Mock, mock, useFromMock } from 'libs/test-utils/src/lib/mocking'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; -import { Observable, of } from 'rxjs'; +import { of } from 'rxjs'; import { LoeschAnforderungFacade } from './+state/loesch-anforderung.facade'; import { LoeschAnforderungResource } from './loesch-anforderung.model'; import { LoeschAnforderungService } from './loesch-anforderung.service'; @@ -129,20 +131,85 @@ describe('LoeschAnforderungService', () => { describe('getLoschAnforderungZuruecknehmenCommand', () => { + const backButtonUrl: string = faker.internet.url(); + const command: CommandResource = createCommandResource(); + const commandStateResource: StateResource<CommandResource> = createStateResource(command); + + beforeEach(() => { + facade.getLoeschAnforderungZuruecknehmenCommand.mockReturnValue(of(commandStateResource)); + vorgangService.getBackButtonUrl.mockReturnValue(of(backButtonUrl)); + }) + it('should call facade', () => { service.getLoschAnforderungZuruecknehmenCommand(); expect(facade.getLoeschAnforderungZuruecknehmenCommand).toHaveBeenCalled(); }) - it('should return command', () => { - const command = createEmptyStateResource(); - const commandObservable = new Observable(o => o.next(command)) - facade.getLoeschAnforderungZuruecknehmenCommand.mockReturnValue(commandObservable); + it('should get back button Url', () => { + service.getLoschAnforderungZuruecknehmenCommand(); + + expect(vorgangService.getBackButtonUrl).toHaveBeenCalled(); + }) + + it('should handleLoeschAnforderungZuruecknehmenCommandChanges', () => { + service.handleLoeschAnforderungZuruecknehmenCommandChanges = jest.fn(); + + service.getLoschAnforderungZuruecknehmenCommand().subscribe(); + + expect(service.handleLoeschAnforderungZuruecknehmenCommandChanges).toHaveBeenCalledWith(commandStateResource, backButtonUrl); + }) + + it('should return command', (done) => { + service.getLoschAnforderungZuruecknehmenCommand().subscribe(command => { + expect(command).toBe(commandStateResource); + done(); + }); + }) + }) + + describe('handleLoeschAnforderungZuruecknehmenCommandChanges', () => { + + const overviewUrl: string = faker.internet.url(); + const command: CommandResource = createCommandResource(); + const commandStateResource: StateResource<CommandResource> = { ...createStateResource(command), error: <any>{ ...createHttpErrorResponse(), status: HttpStatusCode.NotFound } }; + + it('should reload current vorgang on not found error', () => { + service.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStateResource, overviewUrl); + + expect(vorgangService.reloadCurrentVorgangWithAddtionalActions).toHaveBeenCalled(); + }) + + it('should create additionalAction', () => { + service.createAdditionalActions = jest.fn(); + + service.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStateResource, overviewUrl); + + expect(service.createAdditionalActions).toHaveBeenCalledWith(overviewUrl); + }) + + it('should reload current vorgang on not found error with additional actions', () => { + const additionalActions: AdditionalActions = <any>{}; + service.createAdditionalActions = jest.fn().mockReturnValue(additionalActions); + + service.handleLoeschAnforderungZuruecknehmenCommandChanges(commandStateResource, overviewUrl); + + expect(vorgangService.reloadCurrentVorgangWithAddtionalActions).toHaveBeenCalledWith(additionalActions); + }) + + describe('createAdditionalActions', () => { + + it('shouldContainsAdditionalSuccessAction', () => { + const additionalActions = service.createAdditionalActions(overviewUrl); + + expect(additionalActions.additionalSuccessAction).not.toBeNull(); + }) - const result = service.getLoschAnforderungZuruecknehmenCommand(); + it('shouldContainsAdditionalFailureAction', () => { + const additionalActions = service.createAdditionalActions(overviewUrl); - expect(result).toBe(commandObservable); + expect(additionalActions.additionalFailureAction).not.toBeNull(); + }) }) }) diff --git a/goofy-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.ts b/goofy-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.ts index 9c3971cfdc4a993e81aafb385acb58a740443751..ec5ba829ed6f460c2a0e3e1447c116bee68b5fd8 100644 --- a/goofy-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.ts +++ b/goofy-client/libs/loesch-anforderung-shared/src/lib/loesch-anforderung.service.ts @@ -1,15 +1,16 @@ +import { HttpErrorResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { CommandResource } from '@goofy-client/command-shared'; import { NavigationService } from '@goofy-client/navigation-shared'; -import { StateResource } from '@goofy-client/tech-shared'; -import { VorgangService, VorgangWithEingangResource } from '@goofy-client/vorgang-shared'; +import { StateResource, isNotFound } from '@goofy-client/tech-shared'; +import { AdditionalActions, VorgangService, VorgangWithEingangResource } from '@goofy-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 * as CommandUtil from '../../../command-shared/src/lib/command.util'; - +import * as LoeschAnforderungActions from './+state/loesch-anforderung.actions'; @Injectable() export class LoeschAnforderungService { @@ -46,7 +47,22 @@ export class LoeschAnforderungService { } public getLoschAnforderungZuruecknehmenCommand(): Observable<StateResource<CommandResource>> { - return this.facade.getLoeschAnforderungZuruecknehmenCommand(); + 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)); + } + } + + createAdditionalActions(overviewUrl: string): AdditionalActions { + const additionalSuccessAction = LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangSuccess; + const additionalFailureAction = (error: HttpErrorResponse) => LoeschAnforderungActions.loeschAnforderungZuruecknehmenFailedAndReloadVorgangFailure({ error, overviewUrl }); + return { additionalSuccessAction, additionalFailureAction }; } public zuruecknehmen(loeschAnforderung: LoeschAnforderungResource): void { diff --git a/goofy-client/libs/navigation-shared/src/lib/+state/navigation.actions.ts b/goofy-client/libs/navigation-shared/src/lib/+state/navigation.actions.ts index 5a26cd14ec9a162b9abe0af6a622f30fd23fc879..616c040c7639b684319498e1d73e718c54ea2d56 100644 --- a/goofy-client/libs/navigation-shared/src/lib/+state/navigation.actions.ts +++ b/goofy-client/libs/navigation-shared/src/lib/+state/navigation.actions.ts @@ -21,10 +21,14 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import { TypedActionCreator } from '@goofy-client/tech-shared'; +import { TypedActionCreator, TypedActionCreatorWithProps } from '@goofy-client/tech-shared'; import { createAction, props } from '@ngrx/store'; import { RouteData } from './navigation.models'; -export const updateCurrentRouteData = createAction('[Navigation] Update current route data', props<{ routeData: RouteData }>()); +export interface UpdateCurrentRouteDataProps { + routeData: RouteData +} + +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 diff --git a/goofy-client/libs/tech-shared/test/ngrx.ts b/goofy-client/libs/tech-shared/test/ngrx.ts new file mode 100644 index 0000000000000000000000000000000000000000..890981ddad3b622196c2df0137f67629698b5d64 --- /dev/null +++ b/goofy-client/libs/tech-shared/test/ngrx.ts @@ -0,0 +1,3 @@ +import { TypedAction } from '@ngrx/store/src/models'; + +export const DUMMY_ACTION: TypedAction<string> = { type: 'Dummy Action'}; \ No newline at end of file diff --git a/goofy-client/libs/ui/src/lib/interceptor/http-error.interceptor.ts b/goofy-client/libs/ui/src/lib/interceptor/http-error.interceptor.ts index 10669551bebdee684544f28a04a07d30c87b152d..eb26cc4472beb1b40dceff08cb194afbf8a49e26 100644 --- a/goofy-client/libs/ui/src/lib/interceptor/http-error.interceptor.ts +++ b/goofy-client/libs/ui/src/lib/interceptor/http-error.interceptor.ts @@ -41,7 +41,7 @@ export class HttpErrorInterceptor implements HttpInterceptor { private authService: AuthService ) { } - intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> { + 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)), diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts index 8796e7fef152c464d4a8f16eccfa395ab8cc5694..944f38f895da2efb07852b5e122b69b904d2593e 100644 --- a/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts +++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.spec.ts @@ -23,11 +23,11 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatIconModule } from '@angular/material/icon'; -import { MatLegacySnackBarRef as MatSnackBarRef, MAT_LEGACY_SNACK_BAR_DATA as MAT_SNACK_BAR_DATA } from '@angular/material/legacy-snack-bar'; +import { MAT_LEGACY_SNACK_BAR_DATA as MAT_SNACK_BAR_DATA, MatLegacySnackBarRef as MatSnackBarRef } from '@angular/material/legacy-snack-bar'; import { mock } from '@goofy-client/test-utils'; -import { SnackBarData } from '@goofy-client/ui'; import { MockComponent } from 'ng-mocks'; import { SnackbarCloseButtonComponent } from '../snackbar-close-button/snackbar-close-button.component'; +import { SnackBarData } from '../snackbar.model'; import { SnackbarErrorComponent } from './snackbar-error.component'; describe('SnackbarErrorComponent', () => { @@ -38,7 +38,7 @@ describe('SnackbarErrorComponent', () => { const snackBarRef = { ...mock(MatSnackBarRef), dissmis: jest.fn(), dismissWithAction: jest.fn() }; beforeEach(async () => { - await TestBed.configureTestingModule({ + TestBed.configureTestingModule({ imports: [ MatIconModule ], diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts index ed763917eee41d9b2c622bbba8990ff51e8c6734..25da2ddea5c90acfd022b9b85007bf358eda1c4f 100644 --- a/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts +++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-error/snackbar-error.component.ts @@ -22,8 +22,8 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Component, Inject } from '@angular/core'; -import { MatLegacySnackBarRef as MatSnackBarRef, MAT_LEGACY_SNACK_BAR_DATA as MAT_SNACK_BAR_DATA } from '@angular/material/legacy-snack-bar'; -import { SnackBarData } from '../snackbar.service'; +import { MAT_LEGACY_SNACK_BAR_DATA as MAT_SNACK_BAR_DATA, MatLegacySnackBarRef as MatSnackBarRef } from '@angular/material/legacy-snack-bar'; +import { SnackBarData } from '../snackbar.model'; @Component({ selector: 'goofy-client-snackbar-error', diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts index aae405534e9ed13aa2701d4a473b6b37b68dc79c..081db1db257210f1bfbb4bd61a9823ef3912f6b3 100644 --- a/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts +++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.spec.ts @@ -23,14 +23,14 @@ */ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { MatIconModule } from '@angular/material/icon'; -import { MatLegacySnackBarModule as MatSnackBarModule, MatLegacySnackBarRef as MatSnackBarRef, MAT_LEGACY_SNACK_BAR_DATA as MAT_SNACK_BAR_DATA } from '@angular/material/legacy-snack-bar'; +import { MAT_LEGACY_SNACK_BAR_DATA as MAT_SNACK_BAR_DATA, MatLegacySnackBarModule as MatSnackBarModule, MatLegacySnackBarRef as MatSnackBarRef } from '@angular/material/legacy-snack-bar'; import { mock } from '@goofy-client/test-utils'; import { CommandLinkRel } from 'libs/command-shared/src/lib/command.linkrel'; import { createCommandResource } from 'libs/command-shared/test/command'; import { getDataTestIdOf } from 'libs/tech-shared/test/data-test'; import { MockComponent } from 'ng-mocks'; import { SnackbarCloseButtonComponent } from '../snackbar-close-button/snackbar-close-button.component'; -import { SnackBarData } from '../snackbar.service'; +import { SnackBarData } from '../snackbar.model'; import { SnackbarInfoComponent } from './snackbar-info.component'; describe('SnackbarInfoComponent', () => { @@ -43,7 +43,7 @@ describe('SnackbarInfoComponent', () => { const revokeButton: string = getDataTestIdOf('snackbar-revoke-button'); beforeEach(async () => { - await TestBed.configureTestingModule({ + TestBed.configureTestingModule({ imports: [ MatSnackBarModule, MatIconModule diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts index 062b980cf680de8a76c1d6ec8d04742268603137..440b15971c0013628f31312d9175bce849e13326 100644 --- a/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts +++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar-info/snackbar-info.component.ts @@ -22,10 +22,10 @@ * unter der Lizenz sind dem Lizenztext zu entnehmen. */ import { Component, Inject } from '@angular/core'; -import { MatLegacySnackBarRef as MatSnackBarRef, MAT_LEGACY_SNACK_BAR_DATA as MAT_SNACK_BAR_DATA } from '@angular/material/legacy-snack-bar'; +import { MAT_LEGACY_SNACK_BAR_DATA as MAT_SNACK_BAR_DATA, MatLegacySnackBarRef as MatSnackBarRef } from '@angular/material/legacy-snack-bar'; import { isRevokeable } from '@goofy-client/command-shared'; import { isUndefined } from 'lodash-es'; -import { SnackBarData } from '../snackbar.service'; +import { SnackBarData } from '../snackbar.model'; @Component({ selector: 'goofy-client-snackbar-info', diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar.model.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..085d4fcfa069908904ae2206802d71a935d11f29 --- /dev/null +++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar.model.ts @@ -0,0 +1,6 @@ +import { CommandResource } from '@goofy-client/command-shared'; + +export interface SnackBarData { + message: string, + commandResource?: CommandResource +} diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts index 3b521851693652fba0d05f12b1266a4761d27afe..fd3570d58d575353dc5d2f09807134b8133f84f0 100644 --- a/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts +++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.spec.ts @@ -23,7 +23,7 @@ */ import { TestBed } from '@angular/core/testing'; import { MatLegacySnackBar as MatSnackBar } from '@angular/material/legacy-snack-bar'; -import { MatSnackBarRef } from '@angular/material/snack-bar'; +import { MatSnackBarConfig, MatSnackBarRef } from '@angular/material/snack-bar'; import { faker } from '@faker-js/faker'; import { CommandResource, CommandStatus } from '@goofy-client/command-shared'; import { mock, useFromMock } from '@goofy-client/test-utils'; @@ -44,7 +44,7 @@ describe('SnackBarService', () => { const message: string = faker.lorem.words(5); beforeEach(async () => { - await TestBed.configureTestingModule({ + TestBed.configureTestingModule({ providers: [ { provide: MatSnackBar, useValue: mockMatSnackBar }, ], @@ -130,6 +130,33 @@ describe('SnackBarService', () => { }) }) + describe('show info', () => { + + beforeEach(() => { + service.listenOnAfterDismissed = jest.fn(); + service.closeSnackBarIfVisible = jest.fn(); + }) + + it('should close snackbar if exists', () => { + service.showInfo(message); + + expect(service.closeSnackBarIfVisible).toHaveBeenCalled(); + }) + + it('should open from component', () => { + service.showInfo(message); + + const config: MatSnackBarConfig = { data: { message }, duration: 10000 }; + expect(matSnackBar.openFromComponent).toHaveBeenCalledWith(SnackbarInfoComponent, config); + }) + + it('should listen to snackbar after dismissed', () => { + service.showInfo(message); + + expect(service.listenOnAfterDismissed).toHaveBeenCalled(); + }) + }) + describe('close snackbar if visible', () => { beforeEach(() => { diff --git a/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.ts b/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.ts index 816e890b7ed9d921c6f3c033ab8c53f1d0b22996..68e6aa4f8939a585744578d1f3b54528aad65c37 100644 --- a/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.ts +++ b/goofy-client/libs/ui/src/lib/snackbar/snackbar.service.ts @@ -21,8 +21,10 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +import { ComponentType } from '@angular/cdk/overlay'; import { Injectable } from '@angular/core'; import { MatLegacySnackBar as MatSnackBar, MatLegacySnackBarRef as MatSnackBarRef } from '@angular/material/legacy-snack-bar'; +import { MatSnackBarConfig } from '@angular/material/snack-bar'; import { CommandResource, CommandStatus } from '@goofy-client/command-shared'; import { isNotUndefined } from '@goofy-client/tech-shared'; import { isUndefined } from 'lodash-es'; @@ -42,22 +44,31 @@ export class SnackBarService { constructor(private snackBar: MatSnackBar) { } public show(commandResource: CommandResource, message: string, revokeAction?: () => void): void { - this.closeSnackBarIfVisible(); if (commandResource.status === CommandStatus.ERROR) { this.showError(message); } else { - this.snackBarRef = this.snackBar.openFromComponent(SnackbarInfoComponent, { data: { message, commandResource }, duration: this.durationTime }); + this.openFromComponent(SnackbarInfoComponent, { data: { message, commandResource } }); } - this.listenOnAfterDismissed(); + 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(SnackbarErrorComponent, { data: { message }, duration: this.durationTime, panelClass: 'error' }); + this.snackBarRef = this.snackBar.openFromComponent(component, { ...config, duration: this.durationTime }); this.listenOnAfterDismissed(); } @@ -69,7 +80,7 @@ export class SnackBarService { return isUndefined(this.snackBarRef); } - closeSnackBarIfVisible() { + closeSnackBarIfVisible(): void { if (isNotUndefined(this.snackBarRef)) this.closeSnackBar(); } @@ -92,9 +103,4 @@ export class SnackBarService { private unsubscribe(): void { if (isNotUndefined(this.subscription)) this.subscription.unsubscribe(); } -} - -export interface SnackBarData { - message: string, - commandResource?: CommandResource -} +} \ No newline at end of file diff --git a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.actions.ts b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.actions.ts index 727319cfa84b898718505a69adbcaac9d8ff5ce5..23173a542c152caf83e97549ea433e6e8ab8a393 100644 --- a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.actions.ts +++ b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.actions.ts @@ -27,7 +27,7 @@ import { LoadBinaryFileListSuccessProps } from '@goofy-client/binary-file-shared import { CommandStateResourceProps, LoadCommandListSuccessProps } from '@goofy-client/command-shared'; import { ApiErrorAction, ResourceUriProps, TypedActionCreator, TypedActionCreatorWithProps } from '@goofy-client/tech-shared'; import { createAction, props } from '@ngrx/store'; -import { VorgangListResource, VorgangWithEingangResource } from '../vorgang.model'; +import { AdditionalActions, VorgangListResource, VorgangWithEingangResource } from '../vorgang.model'; export interface SearchVorgaengeByProps { apiRoot: ApiRootResource, @@ -60,6 +60,10 @@ export interface VorgangWithEingangAction { vorgangWithEingang: VorgangWithEingangResource } +export interface VorgangUriWithContextProps extends ResourceUriProps { + additionalActions?: AdditionalActions +} + //VorgangList export const noOperation: TypedActionCreator = createAction('[Vorgang-Routing] No Operation'); @@ -85,7 +89,7 @@ export const clearSearchString: TypedActionCreator = createAction('[Vorgang] Cle export const setSearchString: TypedActionCreatorWithProps<StringBasedProps> = createAction('[Vorgang] Set search string', props<StringBasedProps>()); //VorgangWithEingang -export const loadVorgangWithEingang: TypedActionCreatorWithProps<ResourceUriProps> = createAction('[Vorgang] Load VorgangWithEingang', props<ResourceUriProps>()); +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>()); diff --git a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.spec.ts b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.spec.ts index 4dec2bdd5fc73d5d6ca4303a15daf83bc1f8d193..4b6b854e3b328814a8652d1fcd7bd71ebfb8e401 100644 --- a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.spec.ts +++ b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.spec.ts @@ -31,6 +31,7 @@ import { mock } from '@goofy-client/test-utils'; import { SnackBarService } from '@goofy-client/ui'; import { provideMockActions } from '@ngrx/effects/testing'; import { Action } from '@ngrx/store'; +import { TypedAction } from '@ngrx/store/src/models'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { ResourceUri } from '@ngxp/rest'; import { cold, hot } from 'jest-marbles'; @@ -41,8 +42,9 @@ 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 { Observable, of } from 'rxjs'; +import { DUMMY_ACTION } from '../../../../tech-shared/test/ngrx'; import { VorgangWithEingangLinkRel } from '../vorgang.linkrel'; -import { 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'; @@ -306,27 +308,66 @@ describe('VorgangEffects', () => { describe('loadVorgangWithEingang', () => { const resourceUri: ResourceUri = faker.internet.url(); - const action = VorgangActions.loadVorgangWithEingang({ resourceUri }); + const additionalSuccessAction = () => DUMMY_ACTION; + const additionalFailureAction = (error: HttpErrorResponse) => DUMMY_ACTION; + const additionalActions: AdditionalActions = { additionalSuccessAction, additionalFailureAction }; - it('should dispatch success action', () => { - vorgangRepository.getVorgang.mockReturnValue(of(vorgangWithEingang)); + const action: TypedAction<string> = VorgangActions.loadVorgangWithEingang({ resourceUri }); - actions = hot('-a-|', { a: action }); + describe('on success', () => { + + beforeEach(() => { + vorgangRepository.getVorgang.mockReturnValue(of(vorgangWithEingang)); + }) + + it('should dispatch action', () => { + actions = hot('-a-|', { a: action }); + + const expected = hot('-a-|', { a: VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }) }); + 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 = hot('-a-|', { a: VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }) }); - expect(effects.loadVorgangWithEingang$).toBeObservable(expected); + const expected = cold('-(bc)', { + b: VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang }), + c: additionalSuccessAction() + }); + expect(effects.loadVorgangWithEingang$).toBeObservable(expected); + }) }) - it('should dispatch failure action', () => { + describe('on failure', () => { + const apiError: ApiError = createApiError() const error = { error: { error: apiError } }; - const errorResponse = cold('-#', {}, error); - vorgangRepository.getVorgang = jest.fn(() => errorResponse); - const expected = cold('--c', { c: VorgangActions.loadVorgangWithEingangFailure({ apiError }) }); - actions = hot('-a', { a: action }); + beforeEach(() => { + const errorResponse = cold('-#', {}, error); + vorgangRepository.getVorgang = jest.fn(() => errorResponse); + }) + + it('should dispatch action', () => { + actions = hot('-a', { a: action }); - expect(effects.loadVorgangWithEingang$).toBeObservable(expected); + 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); + }) }) }) diff --git a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.ts b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.ts index 464b0ee8498b786043115e31a55926e11084b5df..18f1eaa55d45c4a6d2b4dcc37718b2a865daad86 100644 --- a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.ts +++ b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.effects.ts @@ -26,19 +26,20 @@ import { Injectable } from '@angular/core'; import { ApiRootFacade } from '@goofy-client/api-root-shared'; import { BinaryFileListResource, LoadBinaryFileListProps, loadBinaryFileList } from '@goofy-client/binary-file-shared'; import { CommandListResource, LoadCommandListProps, loadCommandList } from '@goofy-client/command-shared'; -import { ApiError, BlobWithFileName, ResourceUriProps, getApiErrorFromHttpErrorResponse, isServiceUnavailable } from '@goofy-client/tech-shared'; +import { ApiError, BlobWithFileName, getApiErrorFromHttpErrorResponse, isNotUndefined, isServiceUnavailable } from '@goofy-client/tech-shared'; import { SnackBarService } from '@goofy-client/ui'; import { Actions, concatLatestFrom, createEffect, ofType } from '@ngrx/effects'; import { Store } from '@ngrx/store'; +import { TypedAction } from '@ngrx/store/src/models'; import { hasLink } from '@ngxp/rest'; -import { of } from 'rxjs'; +import { Observable, of } from 'rxjs'; import { catchError, filter, map, mergeMap, switchMap } from 'rxjs/operators'; import { VorgangListService } from '../vorgang-list.service'; import { getSearchLinkRel } from '../vorgang-navigation.util'; import { VorgangWithEingangLinkRel } from '../vorgang.linkrel'; import { VorgangMessages } from '../vorgang.messages'; -import { VorgangWithEingangResource } from '../vorgang.model'; -import { ApiRootWithLinkRelProps, HttpErrorAction, SearchVorgaengeByProps, VorgangWithEingangAction } from './vorgang.actions'; +import { AdditionalActions, VorgangWithEingangResource } from '../vorgang.model'; +import { ApiRootWithLinkRelProps, HttpErrorAction, SearchVorgaengeByProps, VorgangUriWithContextProps, VorgangWithEingangAction } from './vorgang.actions'; import { VorgangFacade } from './vorgang.facade'; import { VorgangRepository } from './vorgang.repository'; @@ -103,12 +104,26 @@ export class VorgangEffects { //VorgangWithEingang loadVorgangWithEingang$ = createEffect(() => this.actions$.pipe( ofType(VorgangActions.loadVorgangWithEingang), - switchMap((props: ResourceUriProps) => this.repository.getVorgang(props.resourceUri).pipe( - map(vorgangWithEingang => VorgangActions.loadVorgangWithEingangSuccess({ vorgangWithEingang })), - catchError(error => of(VorgangActions.loadVorgangWithEingangFailure({ apiError: getApiErrorFromHttpErrorResponse(error) })))) + 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)), diff --git a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.spec.ts b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.spec.ts index 3748aa078c2d8295b110980af7d2b89b561a092a..6167e8affa9adab1ff8a592837615f7bce3ee83a 100644 --- a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.spec.ts +++ b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.spec.ts @@ -21,6 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +import { HttpErrorResponse } from '@angular/common/http'; import { ApiRootResource } from '@goofy-client/api-root-shared'; import { Command, CommandOrder, CommandResource } from '@goofy-client/command-shared'; import { StateResource, createStateResource } from '@goofy-client/tech-shared'; @@ -32,7 +33,7 @@ import { createCommand, createCommandResource } from 'libs/command-shared/test/c import { createVorgangListResource, createVorgangResources, createVorgangStatistic, createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { Subject } from 'rxjs'; import { VorgangWithEingangLinkRel } from '../vorgang.linkrel'; -import { 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'; @@ -353,6 +354,26 @@ describe('VorgangFacade', () => { }) }) + 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', () => { diff --git a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.ts b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.ts index aae4247b800c452476d80a7e558ea2e81f3419c6..fe5d68b28148e7d847c3f0e5f168be317f42bd0c 100644 --- a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.ts +++ b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.facade.ts @@ -30,7 +30,7 @@ import { Store } from '@ngrx/store'; import { ResourceUri } from '@ngxp/rest'; import { Observable } from 'rxjs'; import { VorgangWithEingangLinkRel } from '../vorgang.linkrel'; -import { CreateAssignUserCommand, VorgangFilter, VorgangListResource, VorgangResource, VorgangStatistic, VorgangView, VorgangWithEingangResource } from '../vorgang.model'; +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'; @@ -125,6 +125,10 @@ export class VorgangFacade { 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); } diff --git a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts index f89a565649fc610b9dba9e173f5dbdc01f3ff50a..f95f0eae0c4bdf5e975326211c1898d8ab06c651 100644 --- a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts +++ b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.reducer.ts @@ -33,7 +33,7 @@ import { StatusCommandMap, VorgangFilter, VorgangListResource, VorgangResource, import { getVorgaengeFromList, isAssignUserCommand, isStatusCommand } from '../vorgang.util'; import { HttpErrorAction, StringBasedProps, VorgangListAction, VorgangWithEingangAction } from './vorgang.actions'; -import * as CommandAction from '../../../../command-shared/src/lib/+state/command.actions'; +import * as CommandActions from '../../../../command-shared/src/lib/+state/command.actions'; import * as NavigationActions from '../../../../navigation-shared/src/lib/+state/navigation.actions'; import * as VorgangActions from './vorgang.actions'; import * as VorgangReducer from './vorgang.reducer'; @@ -254,30 +254,30 @@ const vorgangReducer: ActionReducer<VorgangState, Action> = createReducer( //Command - on(CommandAction.createCommand, (state, props: CreateCommandProps): VorgangState => { + on(CommandActions.createCommand, (state, props: CreateCommandProps): VorgangState => { return {...state, statusCommandMap: VorgangReducer.getStatusCommandMapByCreateCommand(state, props.command), assignUserCommand: VorgangReducer.getAssignUserCommandByCreateCommand(state, props.command) }; }), - on(CommandAction.createCommandSuccess, (state, props: CommandProps): VorgangState => { + 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(CommandAction.revokeCommand, (state): VorgangState => { + on(CommandActions.revokeCommand, (state): VorgangState => { return { ...state, revokeCommand: createEmptyStateResource(true) }; }), - on(CommandAction.revokeCommandSuccess, (state, props: CommandProps): VorgangState => { + on(CommandActions.revokeCommandSuccess, (state, props: CommandProps): VorgangState => { return {...state, statusCommandMap: <any>{}, vorgangWithEingang: { ...state.vorgangWithEingang, reload: true }, revokeCommand: createStateResource(props.command) } }), - on(CommandAction.publishConcurrentModificationAction, (state): VorgangState => { + on(CommandActions.publishConcurrentModificationAction, (state): VorgangState => { return { ...state, vorgangWithEingang: { ...state.vorgangWithEingang, reload: true } }; }), diff --git a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.ts b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.ts index 852041b4e0d8ce6bf737391ace5d61d9ce65f02f..91a07bc031383785ce5d61ef21e0f38398ff50f5 100644 --- a/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.ts +++ b/goofy-client/libs/vorgang-shared/src/lib/+state/vorgang.repository.ts @@ -25,7 +25,7 @@ import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { ApiRootLinkRel, ApiRootResource } from '@goofy-client/api-root-shared'; import { BinaryFileListResource } from '@goofy-client/binary-file-shared'; -import { BlobWithFileName, CatchHttpError, ContentType, EMPTY_STRING, GetRequestOptions, HttpHeader, SkipInterceptor, buildBlobWithFileName, isNotUndefined } from '@goofy-client/tech-shared'; +import { BlobWithFileName, ContentType, EMPTY_STRING, GetRequestOptions, HttpHeader, SkipInterceptor, buildBlobWithFileName, isNotUndefined } from '@goofy-client/tech-shared'; import { Resource, ResourceFactory, ResourceUri, getUrl } from '@ngxp/rest'; import { Observable, map } from 'rxjs'; import { VorgangListLinkRel, VorgangWithEingangLinkRel } from './../vorgang.linkrel'; @@ -54,7 +54,6 @@ export class VorgangRepository { return this.resourceFactory.fromId(url.href).get(); } - @CatchHttpError(VorgangRepository.GET_VORGANG) public getVorgang(vorgangWithEingangUrl: ResourceUri): Observable<VorgangWithEingangResource> { return this.resourceFactory.fromId(vorgangWithEingangUrl).get(); } diff --git a/goofy-client/libs/vorgang-shared/src/lib/vorgang.model.ts b/goofy-client/libs/vorgang-shared/src/lib/vorgang.model.ts index 2372ccbc6bb2e785112c8714346891736f1f1afd..27c7bd07a0c29571e99de847c74c6ca0b041d9e6 100644 --- a/goofy-client/libs/vorgang-shared/src/lib/vorgang.model.ts +++ b/goofy-client/libs/vorgang-shared/src/lib/vorgang.model.ts @@ -21,7 +21,9 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ +import { HttpErrorResponse } from '@angular/common/http'; import { ListResource, StateResource } from '@goofy-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'; @@ -184,4 +186,9 @@ export interface StatusCommandMap { [CommandOrder.VORGANG_WIEDEREROEFFNEN]: StateResource<CommandResource>, [CommandOrder.VORGANG_ZURUECKHOLEN]: StateResource<CommandResource>, [CommandOrder.VORGANG_ZURUECKSTELLEN]: StateResource<CommandResource> -} \ No newline at end of file +} + +export interface AdditionalActions { + additionalSuccessAction: () => TypedAction<string>, + additionalFailureAction: (error: HttpErrorResponse) => TypedAction<string> +} diff --git a/goofy-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts b/goofy-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts index b544490bcaecdc681d52d489098b8f415002a8ed..83ead4351ed2d4a35364cc46ebf15eb3508036e9 100644 --- a/goofy-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts +++ b/goofy-client/libs/vorgang-shared/src/lib/vorgang.service.spec.ts @@ -21,7 +21,7 @@ * Die sprachspezifischen Genehmigungen und Beschränkungen * unter der Lizenz sind dem Lizenztext zu entnehmen. */ -import faker from '@faker-js/faker'; +import { HttpErrorResponse } from '@angular/common/http'; import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@goofy-client/api-root-shared'; import { BinaryFileListResource } from '@goofy-client/binary-file-shared'; import { CommandResource } from '@goofy-client/command-shared'; @@ -37,9 +37,11 @@ import { createCommandResource } from 'libs/command-shared/test/command'; import { createVorgangWithEingangResource } from 'libs/vorgang-shared/test/vorgang'; import { Observable, of } from 'rxjs'; import { VorgangFacade } from './+state/vorgang.facade'; -import { VorgangWithEingangResource } from './vorgang.model'; +import { AdditionalActions, VorgangWithEingangResource } from './vorgang.model'; import { VorgangService } from './vorgang.service'; +import faker from '@faker-js/faker'; + import * as VorgangNavigationUtil from './vorgang-navigation.util'; describe('VorgangService', () => { @@ -345,6 +347,30 @@ describe('VorgangService', () => { }) }) + 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.skip('should call facade', () => { diff --git a/goofy-client/libs/vorgang-shared/src/lib/vorgang.service.ts b/goofy-client/libs/vorgang-shared/src/lib/vorgang.service.ts index 1e26a225a2d46e96364232bdfc91d70368acdb78..ef847f348ab80293d740b5a86d8a8a788bd53e94 100644 --- a/goofy-client/libs/vorgang-shared/src/lib/vorgang.service.ts +++ b/goofy-client/libs/vorgang-shared/src/lib/vorgang.service.ts @@ -33,7 +33,7 @@ import { Observable, combineLatest } from 'rxjs'; import { filter, map, startWith, tap, withLatestFrom } from 'rxjs/operators'; import { VorgangFacade } from './+state/vorgang.facade'; import { buildLinkRelFromPathSegments } from './vorgang-navigation.util'; -import { VorgangWithEingangResource } from './vorgang.model'; +import { AdditionalActions, VorgangWithEingangResource } from './vorgang.model'; import { createAssignUserCommand } from './vorgang.util'; @Injectable({ providedIn: 'root' }) @@ -52,10 +52,6 @@ export class VorgangService { startWith(createEmptyStateResource<VorgangWithEingangResource>(true))); } - getVorgangWithEingangUri(): ResourceUri { - return this.navigationService.getDecodedParam(VorgangService.VORGANG_WITH_EINGANG_URL); - } - public getAttachments(): Observable<StateResource<BinaryFileListResource>> { return this.facade.getAttachmentList().pipe( withLatestFrom(this.facade.getVorgangWithEingang()), @@ -98,11 +94,18 @@ export class VorgangService { 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(); @@ -147,3 +150,5 @@ export class VorgangService { this.facade.export(vorgangWithEingang); } } + + diff --git a/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.ts b/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.ts index cbc431598bab68a8137ab7d4a7dd7220364ca83f..1bc5a3d13a50a9b3afb9037330d1a113b4954b3c 100644 --- a/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.ts +++ b/goofy-client/libs/vorgang/src/lib/vorgang-list-page-container/vorgang-list-page/vorgang-list-page.component.ts @@ -25,7 +25,6 @@ import { Component, Input } from '@angular/core'; import { ApiRootLinkRel, ApiRootResource } from '@goofy-client/api-root-shared'; import { StateResource } from '@goofy-client/tech-shared'; -//TODO unter vorgang-list-page-container schieben @Component({ selector: 'goofy-client-vorgang-list-page', templateUrl: './vorgang-list-page.component.html', diff --git a/goofy-client/package-lock.json b/goofy-client/package-lock.json index 40106b5a7753dc3db7eaa0a3cd86da29d6a707d5..10b14ffa4b27a46ef2939f8e675a77ce7c43d90c 100644 --- a/goofy-client/package-lock.json +++ b/goofy-client/package-lock.json @@ -150,23 +150,6 @@ } } }, - "node_modules/@angular-devkit/architect/node_modules/ajv": { - "version": "8.12.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@angular-devkit/architect/node_modules/rxjs": { "version": "6.6.7", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-6.6.7.tgz", @@ -465,23 +448,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@angular-devkit/build-angular/node_modules/ajv": { - "version": "8.12.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@angular-devkit/build-angular/node_modules/enhanced-resolve": { "version": "5.12.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", @@ -716,6 +682,24 @@ } } }, + "node_modules/@angular-devkit/core/node_modules/ajv": { + "version": "8.11.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@angular-devkit/core/node_modules/rxjs": { "version": "6.6.7", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-6.6.7.tgz", @@ -786,6 +770,24 @@ } } }, + "node_modules/@angular-devkit/schematics/node_modules/ajv": { + "version": "8.11.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, "node_modules/@angular-devkit/schematics/node_modules/jsonc-parser": { "version": "3.1.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/jsonc-parser/-/jsonc-parser-3.1.0.tgz", @@ -1030,23 +1032,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@angular/cli/node_modules/ajv": { - "version": "8.12.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@angular/cli/node_modules/rxjs": { "version": "6.6.7", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-6.6.7.tgz", @@ -7277,22 +7262,6 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "license": "0BSD" }, - "node_modules/@nrwl/angular/node_modules/ajv": { - "version": "8.12.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@nrwl/angular/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", @@ -8666,22 +8635,6 @@ "yarn": ">= 1.13.0" } }, - "node_modules/@schematics/angular/node_modules/ajv": { - "version": "8.12.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, "node_modules/@schematics/angular/node_modules/rxjs": { "version": "6.6.7", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-6.6.7.tgz", @@ -10200,9 +10153,9 @@ } }, "node_modules/ajv": { - "version": "8.11.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "version": "8.12.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -11247,14 +11200,6 @@ "dev": true, "license": "BSD-2-Clause" }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true, - "license": "ISC", - "peer": true - }, "node_modules/browserify-aes": { "version": "1.2.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/browserify-aes/-/browserify-aes-1.2.0.tgz", @@ -13462,20 +13407,6 @@ } } }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/decimal.js": { "version": "10.4.3", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/decimal.js/-/decimal.js-10.4.3.tgz", @@ -22384,286 +22315,6 @@ "node": ">=10" } }, - "node_modules/mocha": { - "version": "10.2.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/mocha/node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/mocha/node_modules/argparse": { - "version": "2.0.1", - "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", - "peer": true - }, - "node_modules/mocha/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/find-up": { - "version": "5.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/mocha/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", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/mocha/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", - "peer": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/mocha/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "license": "ISC", - "peer": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/minimatch/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", - "peer": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT", - "peer": true - }, - "node_modules/mocha/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/mocha/node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "license": "BSD-3-Clause", - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/mocha/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/mocha/node_modules/yargs": { - "version": "16.2.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "license": "ISC", - "peer": true, - "engines": { - "node": ">=10" - } - }, "node_modules/mochawesome": { "version": "7.1.3", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/mochawesome/-/mochawesome-7.1.3.tgz", @@ -23241,20 +22892,6 @@ "license": "MIT", "optional": true }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, "node_modules/nanomatch": { "version": "1.2.13", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/nanomatch/-/nanomatch-1.2.13.tgz", @@ -26678,9 +26315,9 @@ "license": "ISC" }, "node_modules/rxjs": { - "version": "7.8.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "version": "7.8.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" @@ -30917,14 +30554,6 @@ "errno": "~0.1.7" } }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true, - "license": "Apache-2.0", - "peer": true - }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -31100,48 +30729,6 @@ "node": ">=12" } }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/yargs/node_modules/cliui": { "version": "8.0.1", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/cliui/-/cliui-8.0.1.tgz", @@ -31231,18 +30818,6 @@ "source-map": "0.7.4" } }, - "ajv": { - "version": "8.12.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, "rxjs": { "version": "6.6.7", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-6.6.7.tgz", @@ -31463,18 +31038,6 @@ } } }, - "ajv": { - "version": "8.12.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, "enhanced-resolve": { "version": "5.12.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", @@ -31637,6 +31200,19 @@ "source-map": "0.7.4" }, "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "peer": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, "rxjs": { "version": "6.6.7", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-6.6.7.tgz", @@ -31684,6 +31260,19 @@ "source-map": "0.7.4" } }, + "ajv": { + "version": "8.11.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "peer": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, "jsonc-parser": { "version": "3.1.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/jsonc-parser/-/jsonc-parser-3.1.0.tgz", @@ -31849,18 +31438,6 @@ "rxjs": "6.6.7" } }, - "ajv": { - "version": "8.12.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, "rxjs": { "version": "6.6.7", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-6.6.7.tgz", @@ -36218,17 +35795,6 @@ } } }, - "ajv": { - "version": "8.12.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, "ansi-styles": { "version": "4.3.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -37135,17 +36701,6 @@ "rxjs": "6.6.7" } }, - "ajv": { - "version": "8.12.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "requires": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - } - }, "rxjs": { "version": "6.6.7", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-6.6.7.tgz", @@ -38289,9 +37844,9 @@ } }, "ajv": { - "version": "8.11.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.11.0.tgz", - "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "version": "8.12.0", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -39019,13 +38574,6 @@ "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", "dev": true }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true, - "peer": true - }, "browserify-aes": { "version": "1.2.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/browserify-aes/-/browserify-aes-1.2.0.tgz", @@ -40584,13 +40132,6 @@ "ms": "2.1.2" } }, - "decamelize": { - "version": "4.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "peer": true - }, "decimal.js": { "version": "10.4.3", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/decimal.js/-/decimal.js-10.4.3.tgz", @@ -46830,206 +46371,6 @@ "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, - "mocha": { - "version": "10.2.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "peer": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "peer": true - }, - "argparse": { - "version": "2.0.1", - "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, - "peer": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "peer": true - }, - "find-up": { - "version": "5.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "peer": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "glob": { - "version": "7.2.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "peer": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "minimatch": { - "version": "3.1.2", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "peer": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "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, - "peer": true - }, - "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, - "peer": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "peer": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "peer": true, - "requires": { - "brace-expansion": "^2.0.1" - }, - "dependencies": { - "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, - "peer": true, - "requires": { - "balanced-match": "^1.0.0" - } - } - } - }, - "ms": { - "version": "2.1.3", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "peer": true - }, - "p-locate": { - "version": "5.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "peer": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "peer": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "supports-color": { - "version": "8.1.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "peer": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "yargs": { - "version": "16.2.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "peer": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true, - "peer": true - } - } - }, "mochawesome": { "version": "7.1.3", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/mochawesome/-/mochawesome-7.1.3.tgz", @@ -47455,13 +46796,6 @@ "dev": true, "optional": true }, - "nanoid": { - "version": "3.3.3", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true, - "peer": true - }, "nanomatch": { "version": "1.2.13", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/nanomatch/-/nanomatch-1.2.13.tgz", @@ -49818,9 +49152,9 @@ } }, "rxjs": { - "version": "7.8.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-7.8.0.tgz", - "integrity": "sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==", + "version": "7.8.1", + "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "requires": { "tslib": "^2.1.0" } @@ -52847,13 +52181,6 @@ "errno": "~0.1.7" } }, - "workerpool": { - "version": "6.2.1", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true, - "peer": true - }, "wrap-ansi": { "version": "7.0.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -52977,35 +52304,6 @@ "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "peer": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "camelcase": { - "version": "6.3.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "peer": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "peer": true - } - } - }, "yauzl": { "version": "2.10.0", "resolved": "http://nexus.ozg-sh.de/repository/npm-proxy/yauzl/-/yauzl-2.10.0.tgz", diff --git a/goofy-client/package.json b/goofy-client/package.json index 8853a6fb94624300383b40b6434ba68032c0b2a2..be70ff2f992f202170ab0f9d3b05369c3bdf0652 100644 --- a/goofy-client/package.json +++ b/goofy-client/package.json @@ -4,7 +4,8 @@ "license": "MIT", "scripts": { "postinstall": "node ./decorate-angular-cli.js && ngcc --properties es2020 browser module main --first-only --create-ivy-entry-points", - "start": "nx serve --port 4300 --disable-host-check --verbose", + "start": "nx serve --port 4300 --disable-host-check", + "start:debug": "nx serve --port 4300 --disable-host-check --verbose", "start-for-screenreader": "nx serve --host 192.168.178.20 --port 4300 --disable-host-check --verbose", "start:devbe": "nx serve --port 4300 --disable-host-check --proxy-config proxy.dev.conf.json --verbose", "build": "nx build", diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/RootModelAssembler.java b/goofy-server/src/main/java/de/ozgcloud/alfa/RootModelAssembler.java index d4305b05b11aa12772219c5cb5c1dbc1dfa9e78c..eb118111e22b3a37841b63c1ef39d6788de7a818 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/RootModelAssembler.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/RootModelAssembler.java @@ -57,8 +57,7 @@ public class RootModelAssembler implements RepresentationModelAssembler<Root, En } boolean hasVerwaltungRole() { - return currentUserService.hasRole(UserRole.VERWALTUNG_USER) - || currentUserService.hasRole(UserRole.VERWALTUNG_POSTSTELLE); + return currentUserService.hasRole(UserRole.VERWALTUNG_USER) || currentUserService.hasRole(UserRole.VERWALTUNG_POSTSTELLE); } private Optional<Link> buildCurrentUserLink() { diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemRemoteService.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemRemoteService.java index cb0ff7dd25b96be7df9ab209d194ba0d4abb5b48..5555924cfaf071f746deb96e0384f630dd6fe88f 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemRemoteService.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemRemoteService.java @@ -7,8 +7,12 @@ import org.springframework.stereotype.Service; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemRequest; +import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemResponse; import de.itvsh.ozg.pluto.vorgangAttachedItem.VorgangAttachedItemServiceGrpc.VorgangAttachedItemServiceBlockingStub; import de.ozgcloud.alfa.AlfaServerApplication; +import de.ozgcloud.alfa.common.errorhandling.ResourceNotFoundException; +import io.grpc.Status.Code; +import io.grpc.StatusRuntimeException; import net.devh.boot.grpc.client.inject.GrpcClient; @Service @@ -34,11 +38,22 @@ class VorgangAttachedItemRemoteService { } public VorgangAttachedItem getById(String id) { - var response = vorgangAttachedItemServiceStub.getById(buildGetByIdRequest(id)); + var response = doGetById(id); return mapper.fromGrpc(response.getVorgangAttachedItem()); } + GrpcVorgangAttachedItemResponse doGetById(String id) { + try { + return vorgangAttachedItemServiceStub.getById(buildGetByIdRequest(id)); + } catch (StatusRuntimeException e) { + if (e.getStatus().getCode() == Code.NOT_FOUND) { + throw new ResourceNotFoundException(VorgangAttachedItem.class, id); + } + throw e; + } + } + GrpcVorgangAttachedItemRequest buildGetByIdRequest(String id) { return GrpcVorgangAttachedItemRequest.newBuilder().setId(id).build(); } diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemService.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemService.java index 717a0cba58169d84732503b29888838740c20ba8..a9b88453e2d38222894083df83543ce34546c6ba 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemService.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemService.java @@ -148,16 +148,18 @@ public class VorgangAttachedItemService { } public Command deleteAttachedItem(VorgangAttachedItem vorgangAttachedItem) { - var createCommand = buildDeleteAttachedItemCreateCommand(vorgangAttachedItem); + var createCommand = buildDeleteCommand(vorgangAttachedItem); + return commandService.createCommand(createCommand, vorgangAttachedItem.getVersion()); } - CreateCommand buildDeleteAttachedItemCreateCommand(VorgangAttachedItem vorgangAttachedItem) { + CreateCommand buildDeleteCommand(VorgangAttachedItem vorgangAttachedItem) { return CreateCommand.builder() .vorgangId(vorgangAttachedItem.getVorgangId()) - .relationVersion(vorgangAttachedItem.getVersion()) .relationId(vorgangAttachedItem.getId()) + .relationVersion(vorgangAttachedItem.getVersion()) .order(CommandOrder.DELETE_ATTACHED_ITEM) - .body(vorgangAttachedItem).build(); + .body(vorgangAttachedItem) + .build(); } } \ No newline at end of file diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/CommandHelper.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/CommandHelper.java new file mode 100644 index 0000000000000000000000000000000000000000..142c457fc85fa9686b15ccdbec16b14c11d9a268 --- /dev/null +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/CommandHelper.java @@ -0,0 +1,25 @@ +package de.ozgcloud.alfa.common.command; + +import java.util.function.Predicate; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class CommandHelper { + + static final Predicate<Command> IS_DONE = command -> command.getStatus() == CommandStatus.FINISHED + || command.getStatus() == CommandStatus.REVOKED || command.getStatus() == CommandStatus.ERROR; + + static final Predicate<Command> IS_PENDING = command -> { + return command.getStatus() == CommandStatus.PENDING + || command.getStatus() == CommandStatus.REVOKE_PENDING; + }; + + public static final Predicate<Command> IS_REVOKEABLE = command -> command.getOrder().isRevokeable() + && command.getStatus() == CommandStatus.FINISHED; + + public static final Predicate<Command> IS_LOESCHANFORDERUNG = command -> command.getOrder() == CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN + || command.getOrder() == CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN; + +} \ No newline at end of file diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/CommandModelAssembler.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/CommandModelAssembler.java index 6ab2aef2720f032b3ce03a3a1d9e804bb69c0938..f4ec586934bf6cc2b20b881d86d53bf87a854902 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/CommandModelAssembler.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/CommandModelAssembler.java @@ -25,7 +25,6 @@ package de.ozgcloud.alfa.common.command; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; -import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Stream; @@ -37,8 +36,8 @@ import org.springframework.hateoas.server.RepresentationModelAssembler; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.springframework.stereotype.Component; +import de.ozgcloud.alfa.common.ModelBuilder; import de.ozgcloud.alfa.kommentar.KommentarController; -import de.ozgcloud.alfa.loeschanforderung.LoeschAnforderungCommandByVorgangController; import de.ozgcloud.alfa.postfach.PostfachMailController; import de.ozgcloud.alfa.vorgang.VorgangController; import de.ozgcloud.alfa.vorgang.forwarding.ForwardingController; @@ -51,58 +50,37 @@ class CommandModelAssembler implements RepresentationModelAssembler<Command, Ent static final LinkRelation REL_REVOKE = LinkRelation.of("revoke"); static final LinkRelation REL_UPDATE = LinkRelation.of("update"); - private static final Predicate<Command> IS_REVOKEABLE = command -> command.getOrder().isRevokeable() - && command.getStatus() == CommandStatus.FINISHED; - - private static final Predicate<Command> IS_DONE = command -> command.getStatus() == CommandStatus.FINISHED - || command.getStatus() == CommandStatus.REVOKED || command.getStatus() == CommandStatus.ERROR; - - private static final Predicate<Command> IS_PENDING = command -> command.getStatus() == CommandStatus.PENDING - || command.getStatus() == CommandStatus.REVOKE_PENDING; + static final Predicate<Command> IS_NOT_LOESCH_ANFORDERUNG_AND_REVOKEABLE = command -> !CommandHelper.IS_LOESCHANFORDERUNG.test(command) + && CommandHelper.IS_REVOKEABLE.test(command); @Override - public EntityModel<Command> toModel(Command entity) { - WebMvcLinkBuilder selfLinkBuilder = linkTo(CommandController.class).slash(entity.getId()); - - var resultModel = EntityModel.of(entity, selfLinkBuilder.withSelfRel()); - resultModel = addIf(IS_DONE, resultModel, effectedResourceLinkByOrderType(entity)); - resultModel = addIf(IS_PENDING, resultModel, selfLinkBuilder.withRel(REL_UPDATE)); - resultModel = addIf(IS_REVOKEABLE, resultModel, buildRevokeLinkByOrder(entity)); - return resultModel; + public EntityModel<Command> toModel(Command command) { + return ModelBuilder.fromEntity(command) + .addLink(linkTo(CommandController.class).slash(command.getId()).withSelfRel()) + .ifMatch(CommandHelper.IS_DONE) + .addLink(() -> effectedResourceLinkByOrderType(command)) + .ifMatch(CommandHelper.IS_PENDING) + .addLink(() -> linkTo(CommandController.class).slash(command.getId()).withRel(REL_UPDATE)) + .ifMatch(IS_NOT_LOESCH_ANFORDERUNG_AND_REVOKEABLE) + .addLink(() -> linkTo(methodOn(CommandController.class).revoke(command.getId(), null)).withRel(REL_REVOKE)) + .buildModel(); } Link effectedResourceLinkByOrderType(Command entity) { var type = entity.getOrder().getType(); WebMvcLinkBuilder linkBuilder = switch (type) { - case FORWARDING -> linkTo(methodOn(ForwardingController.class).findByVorgangId(entity.getVorgangId())); - case KOMMENTAR -> linkTo(KommentarController.class).slash(entity.getRelationId()); - case POSTFACH -> linkTo(methodOn(PostfachMailController.class).getAll(entity.getVorgangId())); - case VORGANG -> linkTo(VorgangController.class).slash(entity.getRelationId()); - case VORGANG_LIST -> linkTo(VorgangController.class); - case WIEDERVORLAGE -> linkTo(WiedervorlageController.class).slash(entity.getRelationId()); + case FORWARDING -> linkTo(methodOn(ForwardingController.class).findByVorgangId(entity.getVorgangId())); + case KOMMENTAR -> linkTo(KommentarController.class).slash(entity.getRelationId()); + case POSTFACH -> linkTo(methodOn(PostfachMailController.class).getAll(entity.getVorgangId())); + case VORGANG -> linkTo(VorgangController.class).slash(entity.getRelationId()); + case VORGANG_LIST -> linkTo(VorgangController.class); + case WIEDERVORLAGE -> linkTo(WiedervorlageController.class).slash(entity.getRelationId()); }; return linkBuilder.withRel(REL_EFFECTED_RESOURCE); } - private Link buildRevokeLinkByOrder(Command command) { - if (relatedToLoeschAnforderung(command)) { - return linkTo(methodOn(LoeschAnforderungCommandByVorgangController.class).revoke(command.getVorgangId(), command.getId(), null)) - .withRel(REL_REVOKE); - } - return linkTo(methodOn(CommandController.class).revoke(command.getId(), null)).withRel(REL_REVOKE); - } - - private boolean relatedToLoeschAnforderung(Command command) { - return command.getOrder() == CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN - || command.getOrder() == CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN; - } - - private EntityModel<Command> addIf(Predicate<Command> condition, EntityModel<Command> model, Link link) { - return Optional.ofNullable(model.getContent()).filter(condition).map(command -> model.add(link)).orElse(model); - } - public CollectionModel<EntityModel<Command>> toCollectionModel(Stream<Command> entities) { return CollectionModel.of(entities.map(this::toModel).toList(), linkTo(CommandController.class).withSelfRel()); } diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/StatusPatch.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/StatusPatch.java index 371aad6f61e58e11b35898589ddd682ee2f298ab..4ab402317633a079df71dc697683ad486337ccc7 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/StatusPatch.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/common/command/StatusPatch.java @@ -13,6 +13,6 @@ import lombok.ToString; @Builder @Getter public class StatusPatch { + private CommandStatus status; - private CommandOrder order; } \ No newline at end of file diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ExceptionController.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ExceptionController.java index d328597708a3bf2cb880e22db90fa4f0233acde2..0772ce937792cb74d362034fea4ea1e4d58792c0 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ExceptionController.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ExceptionController.java @@ -62,7 +62,6 @@ public class ExceptionController { static final String RUNTIME_MESSAGE_CODE = "generale.server_error"; static final String RESOURCE_NOT_FOUNT_MESSAGE_CODE = "resource.not_found"; static final String ACCESS_DENIED_MESSAGE_CODE = "generale.access_denied"; - static final String SERVICE_UNAVAILABLE_MESSAGE_CODE = "generale.service_unavailable"; @ExceptionHandler(FunctionalException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) @@ -190,28 +189,4 @@ public class ExceptionController { private Issue createIssueForRuntimeException(String message, String exceptionId) { return Issue.builder().messageCode(RUNTIME_MESSAGE_CODE).message(message).exceptionId(exceptionId).build(); } - - @ExceptionHandler(ServiceUnavailableException.class) - @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE) - @ResponseBody - public ApiError handleServiceUnavailableException(ServiceUnavailableException exception) { - return buildServiceUnavailableApiError(exception); - } - - private ApiError buildServiceUnavailableApiError(ServiceUnavailableException exception) { - return ApiError.builder().issue(createIssueForServiceUnavailableException(exception)).build(); - } - - private Issue createIssueForServiceUnavailableException(ServiceUnavailableException exception) { - return Issue.builder().messageCode(exception.getMessageCode()).message(exception.getMessage()).build(); - } - - @ExceptionHandler(RequestDataNotAllowedException.class) - @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY) - @ResponseBody - public ApiError handleRequestDataNotAllowedException(RequestDataNotAllowedException exception) { - return ApiError.builder() - .issue(Issue.builder().message(exception.getMessage()).messageCode(exception.getMessageCode()).exceptionId(exception.getExceptionId()) - .build()).build(); - } } \ No newline at end of file diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/MessageCode.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/MessageCode.java deleted file mode 100644 index aec58d21a7d03dc32f96463c4b00db34f7337c6a..0000000000000000000000000000000000000000 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/MessageCode.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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. - */ -package de.ozgcloud.alfa.common.errorhandling; - -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class MessageCode { - - public static final String USER_MANAGER_SERVICE_UNAVAILABLE = "general.service_unavailable.usermanager"; - public static final String NOT_ALLOWED_DATA_FOR_OPERATION = "general.not_allowed_data_for_operation"; -} diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/OrderNotAllowedException.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/OrderNotAllowedException.java new file mode 100644 index 0000000000000000000000000000000000000000..6a0c85ff123da982c3c4c3f60ccd827dfdf946cb --- /dev/null +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/OrderNotAllowedException.java @@ -0,0 +1,25 @@ +package de.ozgcloud.alfa.common.errorhandling; + +import de.itvsh.kop.common.errorhandling.FunctionalErrorCode; +import de.ozgcloud.alfa.common.command.CommandOrder; + +public class OrderNotAllowedException extends FunctionalException { + + private static final long serialVersionUID = 1L; + + private static final FunctionalErrorCode MESSAGE_CODE = () -> "loeschanforderung.order_not_allowed"; + private static final String MESSAGE_TEMPLATE = "Order '%s' is not allowed. Expected 'VORGANG_LOESCHEN or LOESCH_ANFORDERUNG_ZURUECKNEHMEN'."; + + private final CommandOrder order; + + public OrderNotAllowedException(CommandOrder order) { + super(MESSAGE_CODE); + + this.order = order; + } + + @Override + public String getMessage() { + return super.getMessage() + String.format(MESSAGE_TEMPLATE, order.name()); + } +} \ No newline at end of file diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/RequestDataNotAllowedException.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/RequestDataNotAllowedException.java deleted file mode 100644 index 51b182e7bfa73984c5be162fbe1c4a3f3b16f379..0000000000000000000000000000000000000000 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/RequestDataNotAllowedException.java +++ /dev/null @@ -1,36 +0,0 @@ -package de.ozgcloud.alfa.common.errorhandling; - -import java.util.UUID; - -import de.itvsh.kop.common.errorhandling.IdentifiableException; - -public class RequestDataNotAllowedException extends RuntimeException implements IdentifiableException { - - private static final String MESSAGE_TEMPLATE = "Request data '%s' is not allowed for this operation. Expected is '%s'."; - - private final String messageCode; - private final String requestValueDescription; - private final String expectedValueDescription; - private final String exceptionId; - - public RequestDataNotAllowedException(String requestValueDescription, String expectedValueDescription) { - this.requestValueDescription = requestValueDescription; - this.expectedValueDescription = expectedValueDescription; - this.exceptionId = UUID.randomUUID().toString(); - this.messageCode = MessageCode.NOT_ALLOWED_DATA_FOR_OPERATION; - } - - @Override - public String getMessage() { - return String.format(MESSAGE_TEMPLATE, requestValueDescription, expectedValueDescription); - } - - @Override - public String getExceptionId() { - return exceptionId; - } - - public String getMessageCode() { - return messageCode; - } -} diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ResourceNotFoundException.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ResourceNotFoundException.java index 6981a09428a2cb0cbd774802d67d7a1ac263d143..c6a0dfc73557a301833cefed1289e51aabe70413 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ResourceNotFoundException.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ResourceNotFoundException.java @@ -32,14 +32,8 @@ public class ResourceNotFoundException extends FunctionalException { private static final long serialVersionUID = 1L; private static final String MESSAGE_TEMPLATE = "Resource '%s' with id '%s' not found."; - private final String resourceName; - private final transient Object id; - public ResourceNotFoundException(Class<?> resource, Object id) { super(buildErrorCode(resource, id)); - - this.resourceName = resource.getSimpleName(); - this.id = id; } private static FunctionalErrorCode buildErrorCode(Class<?> resource, Object id) { diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ServiceUnavailableException.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ServiceUnavailableException.java deleted file mode 100644 index bd6819b0bdf58e2e9b6e32073bf4b14fccbdbe2c..0000000000000000000000000000000000000000 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/common/errorhandling/ServiceUnavailableException.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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. - */ -package de.ozgcloud.alfa.common.errorhandling; - -import lombok.Getter; - -public class ServiceUnavailableException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - @Getter - private String messageCode; - - public ServiceUnavailableException(String messageCode, Throwable throwable) { - super("Service Unavailable", throwable); - - this.messageCode = messageCode; - } -} \ No newline at end of file diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/common/user/UserManagerUnavailableException.java b/goofy-server/src/main/java/de/ozgcloud/alfa/common/user/UserManagerUnavailableException.java index 0cc51d0972263c8178bad34762b5b9cdf86aa31d..4c11fed98cb9a9944e59784ffc8850c21c745c8f 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/common/user/UserManagerUnavailableException.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/common/user/UserManagerUnavailableException.java @@ -5,6 +5,7 @@ import de.ozgcloud.alfa.common.errorhandling.FunctionalException; public class UserManagerUnavailableException extends FunctionalException { + private static final long serialVersionUID = 1L; static final FunctionalErrorCode USER_MANAGER_UNAVAILABLE = () -> "general.service_unavailable.usermanager"; public UserManagerUnavailableException() { diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java b/goofy-server/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java index 07442fc6ec077e4837dadae7e895bdab83864ab5..dc735be8bf8f3da848fd631fa28612ff23a444fb 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/historie/HistorieCommandHandler.java @@ -107,16 +107,16 @@ class HistorieCommandHandler { public Command translateOrder(Command command) { HistorieCommandHandler translator = new HistorieCommandHandler(); return switch (command.getOrder()) { - case CREATE_ATTACHED_ITEM: - yield translator.mapCreateOrder(command); - case UPDATE_ATTACHED_ITEM: - yield translator.mapUpdateOrder(command); - case PATCH_ATTACHED_ITEM: - yield translator.mapPatchOrder(command); - case SEND_POSTFACH_MAIL: - yield command.toBuilder().order(CommandOrder.SEND_POSTFACH_NACHRICHT).build(); - default: - yield command; + case CREATE_ATTACHED_ITEM: + yield translator.mapCreateOrder(command); + case UPDATE_ATTACHED_ITEM: + yield translator.mapUpdateOrder(command); + case PATCH_ATTACHED_ITEM: + yield translator.mapPatchOrder(command); + case SEND_POSTFACH_MAIL: + yield command.toBuilder().order(CommandOrder.SEND_POSTFACH_NACHRICHT).build(); + default: + yield command; }; } diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/historie/HistorieController.java b/goofy-server/src/main/java/de/ozgcloud/alfa/historie/HistorieController.java index 5c10baab1e4b7741211cba8f735429a089c2133a..46eebc40a9a1f899d2cd8c7cf95b0a4ad6330305 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/historie/HistorieController.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/historie/HistorieController.java @@ -47,7 +47,7 @@ public class HistorieController { private HistorieModelAssembler modelAssembler; @GetMapping(params = PARAM_VORGANG_ID) - public CollectionModel<EntityModel<Command>> getHistorieList(@RequestParam String vorgangId) { + public CollectionModel<EntityModel<Command>> getAll(@RequestParam String vorgangId) { return modelAssembler.toCollectionModel(historieService.findFinishedCommands(vorgangId)); } } \ No newline at end of file diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungByVorgangController.java b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungByVorgangController.java deleted file mode 100644 index c6f5fa5cdd096cac319d61e85adf35ba0253519f..0000000000000000000000000000000000000000 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungByVorgangController.java +++ /dev/null @@ -1,41 +0,0 @@ -package de.ozgcloud.alfa.loeschanforderung; - -import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import de.ozgcloud.alfa.common.command.CommandController; -import de.ozgcloud.alfa.common.command.CreateCommand; -import de.ozgcloud.alfa.vorgang.VorgangController; - -@RestController -@RequestMapping(LoeschAnforderungByVorgangController.BASE_PATH) -public class LoeschAnforderungByVorgangController { - - public static final String BASE_PATH = "/api/vorgangs"; // NOSONAR - public static final String CREATE_LOESCHANFORDERUNG_SUB_PATH = "/{vorgangId}/relationVersion/{relationVersion}/loeschanforderung"; // NOSONAR - public static final String CREATE_LOESCHANFORDERUNG_PATH = BASE_PATH + CREATE_LOESCHANFORDERUNG_SUB_PATH; - - @Autowired - private LoeschAnforderungService loeschAnforderungService; - - @Autowired - private VorgangController vorgangController; - - @PostMapping(CREATE_LOESCHANFORDERUNG_SUB_PATH) - public ResponseEntity<Void> createLoeschAnforderung(@PathVariable String vorgangId, @PathVariable long relationVersion, - @RequestBody CreateCommand command) { - - var vorgang = vorgangController.getVorgang(vorgangId); - var created = loeschAnforderungService.createLoeschAnforderung(command, vorgang, relationVersion); - - return ResponseEntity.created(linkTo(CommandController.class).slash(created.getId()).toUri()).build(); - } - -} diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandByVorgangController.java b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandByVorgangController.java deleted file mode 100644 index 08a70201df370f6fe13df2efd1386f9c70d0b42e..0000000000000000000000000000000000000000 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandByVorgangController.java +++ /dev/null @@ -1,57 +0,0 @@ -package de.ozgcloud.alfa.loeschanforderung; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.hateoas.EntityModel; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import de.ozgcloud.alfa.common.command.Command; -import de.ozgcloud.alfa.common.command.CommandController; -import de.ozgcloud.alfa.common.command.CommandOrder; -import de.ozgcloud.alfa.common.command.CommandStatus; -import de.ozgcloud.alfa.common.command.StatusPatch; - -@RestController -@RequestMapping(LoeschAnforderungCommandByVorgangController.PATH) -public class LoeschAnforderungCommandByVorgangController { - - static final String PATH = "/api/vorgangs/{vorgangId}/commands"; // NOSONAR - - @Autowired - private LoeschAnforderungService loeschAnforderungService; - - @Autowired - private CommandController commandController; - - @PatchMapping("{commandId}") - public ResponseEntity<EntityModel<Command>> revoke(@PathVariable String vorgangId, @PathVariable String commandId, - @RequestBody StatusPatch patch) { - if (patch.getStatus() == CommandStatus.REVOKED) { - if (patch.getOrder() == CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN) { - return handleVorgangZumLoeschenMarkierenCommand(vorgangId, commandId, patch); - } - if (patch.getOrder() == CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN) { - return handleLoeschAnforderungZuruecknehmenCommand(commandId, patch); - } - } - return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); - } - - ResponseEntity<EntityModel<Command>> handleVorgangZumLoeschenMarkierenCommand(String vorgangId, String commandId, StatusPatch patch) { - loeschAnforderungService.deleteLoeschAnforderung(vorgangId); - - return commandController.revoke(commandId, patch); - } - - ResponseEntity<EntityModel<Command>> handleLoeschAnforderungZuruecknehmenCommand(String commandId, StatusPatch patch) { - loeschAnforderungService.reCreateLoeschAnforderung(commandId); - var changeStatusCommandId = loeschAnforderungService.getChangeStatusCommandId(commandId); - - return commandController.revoke(changeStatusCommandId, patch); - } -} diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandController.java b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandController.java index 29bb6d2c7314370bab2ac2f09da81f7eca3575fc..d7f901d67009df0d504388cbc6564342d6457a0a 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandController.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandController.java @@ -1,11 +1,13 @@ package de.ozgcloud.alfa.loeschanforderung; -import static de.ozgcloud.alfa.common.command.CommandOrder.*; import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.hateoas.EntityModel; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -15,16 +17,18 @@ import org.springframework.web.bind.annotation.RestController; import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItemService; import de.ozgcloud.alfa.common.command.Command; import de.ozgcloud.alfa.common.command.CommandController; +import de.ozgcloud.alfa.common.command.CommandOrder; +import de.ozgcloud.alfa.common.command.CommandStatus; import de.ozgcloud.alfa.common.command.CreateCommand; -import de.ozgcloud.alfa.common.errorhandling.RequestDataNotAllowedException; +import de.ozgcloud.alfa.common.command.StatusPatch; +import de.ozgcloud.alfa.common.errorhandling.OrderNotAllowedException; import de.ozgcloud.alfa.vorgang.VorgangController; @RestController -@RequestMapping(LoeschAnforderungCommandController.COMMAND_PATH) +@RequestMapping(LoeschAnforderungCommandController.BASE_PATH) public class LoeschAnforderungCommandController { - public static final String COMMAND_SUB_PATH = "/commands"; // NOSONAR - public static final String COMMAND_PATH = LoeschAnforderungController.LOESCHANFORDERUNG_PATH + COMMAND_SUB_PATH; + static final String BASE_PATH = "/api/loeschanforderungs/{loeschAnforderungId}/commands"; // NOSONAR @Autowired private LoeschAnforderungService loeschAnforderungService; @@ -35,24 +39,58 @@ public class LoeschAnforderungCommandController { @Autowired private VorgangController vorgangController; - @PreAuthorize("@loeschAnforderungPreAuthorizeHandler.hasPermissionForOrder(#id, #command.order)") + @Autowired + private CommandController commandController; + + @PreAuthorize("@loeschAnforderungPreAuthorizeHandler.hasPermissionForOrder(#loeschAnforderungId, #command.order)") @PostMapping - public ResponseEntity<Void> createCommand(@PathVariable String id, @RequestBody CreateCommand command) { - - var order = command.getOrder(); - var createdCommand = switch (order) { - case VORGANG_LOESCHEN -> loeschAnforderungService.vorgangLoeschen(command, id); - case LOESCH_ANFORDERUNG_ZURUECKNEHMEN -> loeschAnforderungZuruecknehmen(id); - default -> throw new RequestDataNotAllowedException(String.format("command order %s", order), - String.format("%s or %s", VORGANG_LOESCHEN, LOESCH_ANFORDERUNG_ZURUECKNEHMEN)); - }; + public ResponseEntity<Void> createCommand(@PathVariable String loeschAnforderungId, @RequestBody CreateCommand command) { + var createdCommand = executeCommand(command, loeschAnforderungId); return ResponseEntity.created(linkTo(CommandController.class).slash(createdCommand.getId()).toUri()).build(); } + private Command executeCommand(CreateCommand command, String loeschAnforderungId) { + return switch (command.getOrder()) { + case VORGANG_LOESCHEN -> loeschAnforderungService.vorgangLoeschen(command, loeschAnforderungId); + case LOESCH_ANFORDERUNG_ZURUECKNEHMEN -> loeschAnforderungZuruecknehmen(loeschAnforderungId); + default -> throw new OrderNotAllowedException(command.getOrder()); + }; + } + private Command loeschAnforderungZuruecknehmen(String loeschAnforderungId) { var vorgangAttachedItem = vorgangAttachedItemService.getById(loeschAnforderungId); var vorgang = vorgangController.getVorgang(vorgangAttachedItem.getVorgangId()); return loeschAnforderungService.zuruecknehmen(vorgangAttachedItem, vorgang); } -} + + @PatchMapping("{commandId}") + public ResponseEntity<EntityModel<Command>> revoke(@PathVariable String loeschAnforderungId, @PathVariable String commandId, + @RequestBody StatusPatch patch) { + if (patch.getStatus() == CommandStatus.REVOKED) { + var command = commandController.getById(commandId).getContent(); + + if (command.getOrder() == CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN) { + return handleVorgangZumLoeschenMarkierenRevokeCommand(loeschAnforderungId, command, patch); + } + if (command.getOrder() == CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN) { + return handleLoeschAnforderungZuruecknehmenRevokeCommand(command, patch); + } + } + return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); + } + + ResponseEntity<EntityModel<Command>> handleVorgangZumLoeschenMarkierenRevokeCommand(String loeschAnforderungId, Command command, + StatusPatch patch) { + loeschAnforderungService.deleteLoeschAnforderung(loeschAnforderungId); + + return commandController.revoke(command.getId(), patch); + } + + ResponseEntity<EntityModel<Command>> handleLoeschAnforderungZuruecknehmenRevokeCommand(Command command, StatusPatch patch) { + loeschAnforderungService.reCreateLoeschAnforderung(command); + + var changeStatusCommandId = loeschAnforderungService.getChangeStatusCommandId(command); + return commandController.revoke(changeStatusCommandId, patch); + } +} \ No newline at end of file diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandProzessor.java b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandProzessor.java new file mode 100644 index 0000000000000000000000000000000000000000..2ba01235fea6c79e36bcc8f82ccea4663558a793 --- /dev/null +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandProzessor.java @@ -0,0 +1,59 @@ +package de.ozgcloud.alfa.loeschanforderung; + +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; + +import java.util.Objects; +import java.util.Optional; +import java.util.function.Predicate; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.Link; +import org.springframework.hateoas.LinkRelation; +import org.springframework.hateoas.server.RepresentationModelProcessor; +import org.springframework.stereotype.Component; + +import de.ozgcloud.alfa.common.ModelBuilder; +import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItem; +import de.ozgcloud.alfa.common.command.Command; +import de.ozgcloud.alfa.common.command.CommandHelper; +import de.ozgcloud.alfa.common.command.CommandOrder; + +@Component +class LoeschAnforderungCommandProzessor implements RepresentationModelProcessor<EntityModel<Command>> { + + @Autowired + private LoeschAnforderungService service; + + static final LinkRelation REL_REVOKE = LinkRelation.of("revoke"); + + private static final Predicate<Command> IS_VORGANG_ZUM_LOESCHEN_MARKIEREN_AND_REVOKEABLE = command -> command + .getOrder() == CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN && CommandHelper.IS_REVOKEABLE.test(command); + static final Predicate<Command> IS_LOESCHEN_ANFORDERUNG_ZURUECKNEHMEN_AND_REVOKEABLE = command -> command + .getOrder() == CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN && CommandHelper.IS_REVOKEABLE.test(command); + + @Override + public EntityModel<Command> process(EntityModel<Command> model) { + var command = model.getContent(); + + if (Objects.isNull(command)) { + return model; + } + return ModelBuilder.fromModel(model) + .ifMatch(IS_LOESCHEN_ANFORDERUNG_ZURUECKNEHMEN_AND_REVOKEABLE) + .addLink(() -> linkTo(methodOn(LoeschAnforderungCommandController.class).revoke(command.getRelationId(), command.getId(), null)) + .withRel(REL_REVOKE)) + .ifMatch(IS_VORGANG_ZUM_LOESCHEN_MARKIEREN_AND_REVOKEABLE) + .addLinkIfPresent(() -> buildLink(command)) + .buildModel(); + } + + Optional<Link> buildLink(Command command) { + return service.findLoeschAnforderung(command.getVorgangId()).map(loeschAnforderung -> buildLink(loeschAnforderung, command.getId())); + } + + Link buildLink(VorgangAttachedItem loeschAnforderung, String commandId) { + return linkTo(methodOn(LoeschAnforderungCommandController.class).revoke(loeschAnforderung.getId(), commandId, null)) + .withRel(REL_REVOKE); + } +} \ No newline at end of file diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungController.java b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungController.java index c07675b9ac0e63ff2b5accc1634af8f685f0aed7..0d6dce957f181211ef7fcd178c4021cece54b2a9 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungController.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungController.java @@ -1,29 +1,57 @@ package de.ozgcloud.alfa.loeschanforderung; +import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.hateoas.EntityModel; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import de.ozgcloud.alfa.common.command.CommandController; +import de.ozgcloud.alfa.common.command.CreateCommand; +import de.ozgcloud.alfa.vorgang.VorgangController; + @RestController @RequestMapping(LoeschAnforderungController.BASE_PATH) public class LoeschAnforderungController { - public static final String BASE_PATH = "/api/loeschanforderungs"; // NOSONAR - public static final String LOESCHANFORDERUNG_SUB_PATH = "/{id}"; // NOSONAR - public static final String LOESCHANFORDERUNG_PATH = BASE_PATH + LOESCHANFORDERUNG_SUB_PATH; // NOSONAR + static final String BASE_PATH = "/api/loeschanforderungs"; // NOSONAR @Autowired - private LoeschAnforderungService loeschAnforderungService; + private LoeschAnforderungService service; @Autowired - private LoeschAnforderungModelAssembler loeschAnforderungModelAssembler; + private LoeschAnforderungModelAssembler modelAssembler; - @GetMapping(LOESCHANFORDERUNG_SUB_PATH) + @GetMapping("/{id}") public EntityModel<LoeschAnforderung> getLoeschanforderung(@PathVariable String id) { - return loeschAnforderungModelAssembler.toModel(loeschAnforderungService.getById(id)); + return modelAssembler.toModel(service.getById(id)); } + @RestController + @RequestMapping(LoeschAnforderungByVorgangController.BASE_PATH) + public static class LoeschAnforderungByVorgangController { + + public static final String BASE_PATH = "/api/vorgangs/{vorgangId}/vorgangVersion/{vorgangVersion}/loeschanforderung"; // NOSONAR + + @Autowired + private LoeschAnforderungService loeschAnforderungService; + + @Autowired + private VorgangController vorgangController; + + @PostMapping + public ResponseEntity<Void> createLoeschAnforderung(@PathVariable String vorgangId, @PathVariable long vorgangVersion, + @RequestBody CreateCommand command) { + var vorgang = vorgangController.getVorgang(vorgangId); + var created = loeschAnforderungService.createLoeschAnforderung(command, vorgang, vorgangVersion); + + return ResponseEntity.created(linkTo(CommandController.class).slash(created.getId()).toUri()).build(); + } + } } diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungMapper.java b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungMapper.java index 094afaf7e190bd33fde3e954400f2d05540a046b..f38c2b97f7dc26cc2cdf645fcc0c22c9f0644991 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungMapper.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungMapper.java @@ -9,7 +9,6 @@ import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItem; import de.ozgcloud.alfa.common.command.Command; import de.ozgcloud.alfa.common.command.CommandBodyMapper; import de.ozgcloud.alfa.common.user.UserId; -import de.ozgcloud.alfa.vorgang.Vorgang; import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; @Component @@ -45,6 +44,6 @@ class LoeschAnforderungMapper { } private VorgangStatus getPrevState(Map<String, Object> item) { - return Vorgang.VorgangStatus.valueOf(MapUtils.getString(item, LoeschAnforderung.PREV_STATUS_FIELD)); + return VorgangStatus.valueOf(MapUtils.getString(item, LoeschAnforderung.PREV_STATUS_FIELD)); } } diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungService.java b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungService.java index 6c2fcdfc86f2e7a8c443c8b7f337e4f115213686..d215118ece078659764cff242d4a87101a9bf4a1 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungService.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungService.java @@ -41,10 +41,10 @@ class LoeschAnforderungService { private CurrentUserService currentUserService; public Command createLoeschAnforderung(@Valid @RequiredOrder(CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN) CreateCommand command, Vorgang vorgang, - long relationVersion) { - + long vorgangVersion) { createVorgangAttachedItem(vorgang); - return createCreateCommand(command, vorgang, relationVersion); + + return createCreateCommand(command, vorgang, vorgangVersion); } void createVorgangAttachedItem(Vorgang vorgang) { @@ -58,20 +58,23 @@ class LoeschAnforderungService { .build(); } - Command createCreateCommand(CreateCommand command, Vorgang vorgang, long relationVersion) { + Command createCreateCommand(CreateCommand command, Vorgang vorgang, long vorgangVersion) { var createCommand = command.toBuilder().relationId(vorgang.getId()).vorgangId(vorgang.getId()).build(); - return commandService.createCommand(createCommand, relationVersion); + return commandService.createCommand(createCommand, vorgangVersion); } public Command vorgangLoeschen(CreateCommand command, String loeschAnforderungId) { var loeschAnforderung = getById(loeschAnforderungId); - return commandService.createCommandDeprecated( - command.toBuilder().vorgangId(loeschAnforderung.getVorgangId()).relationId(loeschAnforderung.getVorgangId()).build()); + + command = command.toBuilder().vorgangId(loeschAnforderung.getVorgangId()).relationId(loeschAnforderung.getVorgangId()).build(); + + return commandService.createCommand(command); } public LoeschAnforderung getById(String id) { var vorgangAttachedItem = vorgangAttachedItemService.getById(id); + return mapper.fromVorgangAttachedItem(vorgangAttachedItem); } @@ -114,10 +117,10 @@ class LoeschAnforderungService { CommandOrder getCommandOrderForPreviousStatus(LoeschAnforderung loeschAnforderung) { return switch (loeschAnforderung.getPrevStatus()) { - case ABGESCHLOSSEN -> CommandOrder.VORGANG_ABSCHLIESSEN; - case VERWORFEN -> CommandOrder.VORGANG_VERWERFEN; - default -> throw new TechnicalException( - String.format("Unexpected prevStatus %s in LoeschAnforderung.", loeschAnforderung.getPrevStatus())); + case ABGESCHLOSSEN -> CommandOrder.VORGANG_ABSCHLIESSEN; + case VERWORFEN -> CommandOrder.VORGANG_VERWERFEN; + default -> throw new TechnicalException( + String.format("Unexpected prevStatus %s in LoeschAnforderung.", loeschAnforderung.getPrevStatus())); }; } @@ -138,11 +141,10 @@ class LoeschAnforderungService { .build(); } - public void deleteLoeschAnforderung(String vorgangId) { - findLoeschAnforderung(vorgangId).ifPresentOrElse(vorgangAttachedItemService::deleteAttachedItem, - () -> { - throw new TechnicalException("Expected to find Löschanforderung."); - }); + public void deleteLoeschAnforderung(String loeschAnforderungId) { + var vorgangAttachedItem = vorgangAttachedItemService.getById(loeschAnforderungId); + + vorgangAttachedItemService.deleteAttachedItem(vorgangAttachedItem); } public Optional<VorgangAttachedItem> findLoeschAnforderung(String vorgangId) { @@ -162,9 +164,7 @@ class LoeschAnforderungService { items.subList(1, items.size()).forEach(vorgangAttachedItemService::deleteAttachedItem); } - public void reCreateLoeschAnforderung(String commandId) { - var command = commandService.getById(commandId); - + public void reCreateLoeschAnforderung(Command command) { var deleteLoschAnforderungCommand = commandService.getById(getDeleteVorgangAttachedItemCommandId(command)); var loeschAnforderung = mapper.fromCommand(deleteLoschAnforderungCommand); @@ -175,13 +175,7 @@ class LoeschAnforderungService { return MapUtils.getString(command.getBody(), DeleteLoeschAnforderung.DELETE_ATTACHED_ITEM_COMMAND_ID_FIELD); } - public String getChangeStatusCommandId(String zuruecknehmenCommandId) { - var command = commandService.getById(zuruecknehmenCommandId); - - return getChangeStatusCommandId(command); - } - - private String getChangeStatusCommandId(Command command) { + public String getChangeStatusCommandId(Command command) { return MapUtils.getString(command.getBody(), DeleteLoeschAnforderung.CHANGE_STATUS_COMMAND_ID_FIELD); } } \ No newline at end of file diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungVorgangProzessor.java b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungVorgangProzessor.java index d4c5d6d6e02d9d2ca02c6ff939661c6d9f3b1aa7..c38c32598272716277a088d0fc416ace4263e3c3 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungVorgangProzessor.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungVorgangProzessor.java @@ -17,6 +17,7 @@ import de.ozgcloud.alfa.common.ModelBuilder; import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItem; import de.ozgcloud.alfa.common.user.CurrentUserService; import de.ozgcloud.alfa.common.user.UserRole; +import de.ozgcloud.alfa.loeschanforderung.LoeschAnforderungController.LoeschAnforderungByVorgangController; import de.ozgcloud.alfa.vorgang.Vorgang; import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; @@ -53,8 +54,15 @@ class LoeschAnforderungVorgangProzessor implements RepresentationModelProcessor< } boolean isLoeschenAnfordernAllowed(Vorgang vorgang) { - return VORGANG_STATUSES_ALLOWED_TO_LOESCHEN_ANFORDERN.contains(vorgang.getStatus()) - && USER_ROLES_ALLOWED_TO_LOESCHEN_ANFORDERN.stream().anyMatch(currentUserService::hasRole); + return isAllowedStatus(vorgang) && isAllowedUserRole(); + } + + private boolean isAllowedStatus(Vorgang vorgang) { + return VORGANG_STATUSES_ALLOWED_TO_LOESCHEN_ANFORDERN.contains(vorgang.getStatus()); + } + + private boolean isAllowedUserRole() { + return USER_ROLES_ALLOWED_TO_LOESCHEN_ANFORDERN.stream().anyMatch(currentUserService::hasRole); } private Link buildLoschenAnfordernLink(Vorgang vorgang) { diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessor.java b/goofy-server/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessor.java index 0daf31963aae9d6ef3a34bd17c66c9bf4fad6fbe..4db632f692b5f54ac348753a93d1e85ba2e8ce30 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessor.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/vorgang/VorgangWithEingangProzessor.java @@ -95,7 +95,7 @@ class VorgangWithEingangProzessor implements RepresentationModelProcessor<Entity .addLink(linkTo(methodOn(PostfachMailController.class).getAll(vorgang.getId())).withRel(REL_POSTFACH_MAILS)) .ifMatch(this::isEinheitlicherAnsprechpartner) .addLink(linkTo(methodOn(ForwardingController.class).findByVorgangId(vorgang.getId())).withRel(REL_VORGANG_FORWARDING)) - .addLink(linkTo(methodOn(HistorieController.class).getHistorieList(vorgang.getId())).withRel(REL_HISTORIE)) + .addLink(linkTo(methodOn(HistorieController.class).getAll(vorgang.getId())).withRel(REL_HISTORIE)) .ifMatch(() -> userManagerUrlProvider.isConfiguredForSearchUserProfile() && hasOrganisationsEinheitId(vorgang)) .addLink(() -> buildSearchUserProfilesLink(vorgang)) .buildModel(); diff --git a/goofy-server/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandController.java b/goofy-server/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandController.java index 8d1ebef977782a852b9c014bc12c5864c523ebbc..18edcca8983c5c2a9be02c6b3ddb9a736e1d053f 100644 --- a/goofy-server/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandController.java +++ b/goofy-server/src/main/java/de/ozgcloud/alfa/wiedervorlage/WiedervorlageCommandController.java @@ -59,17 +59,18 @@ public class WiedervorlageCommandController { Command createCommand(Wiedervorlage wiedervorlage, WiedervorlageCommand command) { switch (command.getOrder()) { - case WIEDERVORLAGE_ERLEDIGEN: { - return service.erledigen(wiedervorlage); - } - case WIEDERVORLAGE_WIEDEREROEFFNEN: { - return service.wiedereroeffnen(wiedervorlage); - } - case EDIT_WIEDERVORLAGE: { - return service.editWiedervorlage(updateWiedervorlageByCommand(wiedervorlage, command), wiedervorlage.getId(), wiedervorlage.getVersion()); - } - default: - throw new TechnicalException("Unsupported order " + command.getOrder()); + case WIEDERVORLAGE_ERLEDIGEN: { + return service.erledigen(wiedervorlage); + } + case WIEDERVORLAGE_WIEDEREROEFFNEN: { + return service.wiedereroeffnen(wiedervorlage); + } + case EDIT_WIEDERVORLAGE: { + return service.editWiedervorlage(updateWiedervorlageByCommand(wiedervorlage, command), wiedervorlage.getId(), + wiedervorlage.getVersion()); + } + default: + throw new TechnicalException("Unsupported order " + command.getOrder()); } } diff --git a/goofy-server/src/main/resources/application-e2e.yml b/goofy-server/src/main/resources/application-e2e.yml index ffc124b992bf02195692092c36674b8c8c9506bc..6b4c84428d26ff921ab8c233062ebd1b8837dce4 100644 --- a/goofy-server/src/main/resources/application-e2e.yml +++ b/goofy-server/src/main/resources/application-e2e.yml @@ -12,3 +12,7 @@ kop: ozgcloud: feature: vorgang-export: true + createBescheid: true + user-assistance: + documentation: + url: /assets/benutzerleitfaden/Benutzerleitfaden_2.5.pdf \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemRemoteServiceTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemRemoteServiceTest.java index f6d98ed0a632d41c1308df3145a256cbb5ba02f9..eac7c683c1e11882cf91e0d98d6fddeb3752cd58 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemRemoteServiceTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemRemoteServiceTest.java @@ -8,6 +8,9 @@ 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.EnumSource; +import org.junit.jupiter.params.provider.EnumSource.Mode; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; @@ -17,10 +20,13 @@ import org.mockito.Spy; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemRequest; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcFindVorgangAttachedItemResponse; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItem; -import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemRequest; import de.itvsh.ozg.pluto.vorgangAttachedItem.GrpcVorgangAttachedItemResponse; import de.itvsh.ozg.pluto.vorgangAttachedItem.VorgangAttachedItemServiceGrpc.VorgangAttachedItemServiceBlockingStub; +import de.ozgcloud.alfa.common.errorhandling.ResourceNotFoundException; import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; +import io.grpc.Status; +import io.grpc.Status.Code; +import io.grpc.StatusRuntimeException; class VorgangAttachedItemRemoteServiceTest { @@ -110,34 +116,24 @@ class VorgangAttachedItemRemoteServiceTest { } + @DisplayName("Get by id") @Nested class TestGetById { - private final GrpcVorgangAttachedItemRequest request = GrpcVorgangAttachedItemRequestTestFactory.create(); private final GrpcVorgangAttachedItemResponse response = GrpcVorgangAttachedItemResponseTestFactory.create(); private final VorgangAttachedItem vorgangAttachedItem = VorgangAttachedItemTestFactory.create(); @BeforeEach void init() { - doReturn(request).when(service).buildGetByIdRequest(VorgangAttachedItemTestFactory.ID); - when(grpcService.getById(request)).thenReturn(response); when(mapper.fromGrpc(any())).thenReturn(vorgangAttachedItem); + doReturn(response).when(service).doGetById(any()); } @Test - void shouldBuildRequest() { + void shouldDoGetById() { service.getById(VorgangAttachedItemTestFactory.ID); - verify(service).buildGetByIdRequest(VorgangAttachedItemTestFactory.ID); - } - - @Test - void shouldCallGrpcService() { - var request = GrpcVorgangAttachedItemRequestTestFactory.create(); - - service.getById(VorgangAttachedItemTestFactory.ID); - - verify(grpcService).getById(request); + verify(service).doGetById(VorgangAttachedItemTestFactory.ID); } @Test @@ -154,4 +150,54 @@ class VorgangAttachedItemRemoteServiceTest { assertThat(result).isEqualTo(vorgangAttachedItem); } } + + @DisplayName("Do get by id") + @Nested + class TestDoGetById { + + @Test + void shouldBuildRequest() { + service.doGetById(VorgangAttachedItemTestFactory.ID); + + verify(service).buildGetByIdRequest(VorgangAttachedItemTestFactory.ID); + } + + @Test + void shouldCallGrpcService() { + var request = GrpcVorgangAttachedItemRequestTestFactory.create(); + + service.doGetById(VorgangAttachedItemTestFactory.ID); + + verify(grpcService).getById(request); + } + + @DisplayName("on grpc exception") + @Nested + class TestOnGrpcException { + + @DisplayName("not found") + @Nested + class TestNotFound { + + @Test + void shouldThrowResourceNotFoundException() { + var statusRuntimeException = new StatusRuntimeException(Status.NOT_FOUND); + + when(grpcService.getById(any())).thenThrow(statusRuntimeException); + + assertThatThrownBy(() -> service.doGetById(VorgangAttachedItemTestFactory.ID)).isInstanceOf(ResourceNotFoundException.class); + } + } + + @ParameterizedTest + @EnumSource(mode = Mode.EXCLUDE, names = { "NOT_FOUND" }) + void shouldThrowException(Code code) { + var statusRuntimeException = new StatusRuntimeException(code.toStatus()); + + when(grpcService.getById(any())).thenThrow(statusRuntimeException); + + assertThatThrownBy(() -> service.doGetById(VorgangAttachedItemTestFactory.ID)).isInstanceOf(StatusRuntimeException.class); + } + } + } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemServiceTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemServiceTest.java index b0cbc7074873e46f37ca57ebee9a4793e0725307..149d5b65ef7dc89e30f9f0b1a0becb599ea2db5b 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemServiceTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemServiceTest.java @@ -159,21 +159,21 @@ class VorgangAttachedItemServiceTest { @Test void shouldSetItemName() { - CreateCommand command = service.createPatchCommand(WiedervorlageTestFactory.create(), false); + var command = service.createPatchCommand(WiedervorlageTestFactory.create(), false); assertThat(((VorgangAttachedItem) command.getBody()).getItemName()).isEqualTo(Wiedervorlage.class.getSimpleName()); } @Test void shouldSetItem() { - CreateCommand command = service.createPatchCommand(WiedervorlageTestFactory.create(), false); + var command = service.createPatchCommand(WiedervorlageTestFactory.create(), false); assertThat(((VorgangAttachedItem) command.getBody()).getItem()).isNotEmpty(); } @Test void shouldSetItemDoneValue() { - CreateCommand command = service.createPatchCommand(WiedervorlageTestFactory.create(), true); + var command = service.createPatchCommand(WiedervorlageTestFactory.create(), true); assertThat(((VorgangAttachedItem) command.getBody()).getItem()).containsEntry("done", true); } @@ -371,10 +371,7 @@ class VorgangAttachedItemServiceTest { void shouldBuildVorgangAttachedItem() { callCreateVorgangAttachedItem(); - verify(service).buildVorgangAttachedItem( - itemBody, - VorgangHeaderTestFactory.ID, - VorgangAttachedItemService.LOESCH_ANFORDERUNG_ITEM_NAME); + verify(service).buildVorgangAttachedItem(itemBody, VorgangHeaderTestFactory.ID, VorgangAttachedItemService.LOESCH_ANFORDERUNG_ITEM_NAME); } @Test @@ -432,12 +429,16 @@ class VorgangAttachedItemServiceTest { @Test void shouldReturnTrue() { - assertThat(service.isLoeschAnforderung(VorgangAttachedItemService.LOESCH_ANFORDERUNG_ITEM_NAME)).isTrue(); + var isLoeschAnforderung = service.isLoeschAnforderung(VorgangAttachedItemService.LOESCH_ANFORDERUNG_ITEM_NAME); + + assertThat(isLoeschAnforderung).isTrue(); } @Test void shouldReturnFalse() { - assertThat(service.isLoeschAnforderung(VorgangAttachedItemService.WIEDERVORLAGE_ITEM_NAME)).isFalse(); + var isLoeschAnforderung = service.isLoeschAnforderung(VorgangAttachedItemService.WIEDERVORLAGE_ITEM_NAME); + + assertThat(isLoeschAnforderung).isFalse(); } } @@ -454,7 +455,7 @@ class VorgangAttachedItemServiceTest { @BeforeEach void init() { - doReturn(createCommand).when(service).buildDeleteAttachedItemCreateCommand(vorgangAttachedItem); + doReturn(createCommand).when(service).buildDeleteCommand(vorgangAttachedItem); when(commandService.createCommand(createCommand, VorgangAttachedItemTestFactory.VERSION)).thenReturn(command); } @@ -462,7 +463,7 @@ class VorgangAttachedItemServiceTest { void shouldBuildCreateCommand() { service.deleteAttachedItem(vorgangAttachedItem); - verify(service).buildDeleteAttachedItemCreateCommand(vorgangAttachedItem); + verify(service).buildDeleteCommand(vorgangAttachedItem); } @Test @@ -478,20 +479,49 @@ class VorgangAttachedItemServiceTest { var resultCommand = service.deleteAttachedItem(vorgangAttachedItem); assertThat(resultCommand).isEqualTo(command); - } } + @DisplayName("Build deleteCommand") @Nested - class TestBuildDeleteAttachedItemCreateCommand { + class TestBuildDeleteCommand { + + private final VorgangAttachedItem item = VorgangAttachedItemTestFactory.create(); @Test - void shouldBuildCreateCommand() { - var createCommand = service.buildDeleteAttachedItemCreateCommand(VorgangAttachedItemTestFactory.create()); + void shouldContainsVorgangId() { + var createCommand = service.buildDeleteCommand(item); + + assertThat(createCommand.getVorgangId()).isEqualTo(VorgangHeaderTestFactory.ID); + } + + @Test + void shouldContainsRelationId() { + var createCommand = service.buildDeleteCommand(item); + + assertThat(createCommand.getRelationId()).isEqualTo(VorgangAttachedItemTestFactory.ID); + } + + @Test + void shouldContainsRelationVersion() { + var createCommand = service.buildDeleteCommand(item); + + assertThat(createCommand.getRelationVersion()).isEqualTo(VorgangAttachedItemTestFactory.VERSION); + } + + @Test + void shouldContainsOrder() { + var createCommand = service.buildDeleteCommand(item); + + assertThat(createCommand.getOrder()).isEqualTo(CommandOrder.DELETE_ATTACHED_ITEM); + } + + @Test + + void shouldContainsBody() { + var createCommand = service.buildDeleteCommand(item); - assertThat(createCommand).usingRecursiveComparison() - .isEqualTo(CommandTestFactory.createCreateCommandBuilder().body(VorgangAttachedItemTestFactory.create()) - .relationId(VorgangAttachedItemTestFactory.ID).order(CommandOrder.DELETE_ATTACHED_ITEM).build()); + assertThat(createCommand.getBody()).usingRecursiveComparison().isEqualTo(item); } } diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemTestFactory.java b/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemTestFactory.java index 2cfc3359eb664a769f762d1e9acbac9b867c5abe..da2eae80a1f3b51ad0972b0e53318ca851ad5f1e 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemTestFactory.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/common/attacheditem/VorgangAttachedItemTestFactory.java @@ -26,12 +26,14 @@ package de.ozgcloud.alfa.common.attacheditem; import java.util.Map; import java.util.UUID; +import org.apache.commons.lang3.RandomUtils; + import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; public class VorgangAttachedItemTestFactory { public static final String ID = UUID.randomUUID().toString(); - public static final long VERSION = 42; + public static final long VERSION = RandomUtils.nextLong(); public static final String CLIENT = "Alfa"; public static final String ITEM_NAME = "ItemName"; public static final String ITEM_KEY = "oneKey"; diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandByRelationControllerTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandByRelationControllerTest.java index 1bf9e6acff0c3af729cd81dc785c2d23887b8f3a..568ee45b2f4502af1c5631d1d4566e0b2a49eed0 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandByRelationControllerTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandByRelationControllerTest.java @@ -30,6 +30,8 @@ import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.nio.charset.StandardCharsets; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -125,10 +127,10 @@ class CommandByRelationControllerTest { private ResultActions doRequest(String content) throws Exception { return mockMvc - .perform(post(CommandByRelationController.COMMAND_BY_RELATION_PATH, VorgangHeaderTestFactory.ID, - CommandTestFactory.RELATION_ID, VorgangHeaderTestFactory.VERSION) + .perform(post(CommandByRelationController.COMMAND_BY_RELATION_PATH, VorgangHeaderTestFactory.ID, CommandTestFactory.RELATION_ID, + CommandTestFactory.RELATION_VERSION) .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("UTF-8") + .characterEncoding(StandardCharsets.UTF_8.name()) .content(content)) .andExpect(status().is2xxSuccessful()); } diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandModelAssemblerTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandModelAssemblerTest.java index 1b986904285b110db6859afa761979c459b86be3..e6c9a99ffa03e77b4e12d0641c81cfd8de2f9079 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandModelAssemblerTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandModelAssemblerTest.java @@ -42,11 +42,11 @@ import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; class CommandModelAssemblerTest { - @InjectMocks // NOSONAR - private CommandModelAssembler modelAssembler; - private static final String COMMAND_SINGLE_PATH = "/api/commands/" + CommandTestFactory.ID; + @InjectMocks + private CommandModelAssembler modelAssembler; + @Test void shouldHaveSelfLink() { var model = modelAssembler.toModel(CommandTestFactory.create()); @@ -198,11 +198,10 @@ class CommandModelAssemblerTest { @ParameterizedTest @EnumSource(names = { "VORGANG_ZUM_LOESCHEN_MARKIEREN", "LOESCH_ANFORDERUNG_ZURUECKNEHMEN" }) - void shouldBePresentOnOrder(CommandOrder order) { + void shouldNotBePresentOnOrder(CommandOrder order) { var model = toModelWithOrder(order); - assertThat(model.getLink(REL_REVOKE)).isPresent().get().extracting(Link::getHref) - .isEqualTo("/api/vorgangs/" + VorgangHeaderTestFactory.ID + "/commands/" + CommandTestFactory.ID); + assertThat(model.getLink(REL_REVOKE)).isNotPresent(); } } diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandRemoteServiceTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandRemoteServiceTest.java index 562bd7325986aaec2a0faeb931acdbaa01bf0a68..43886084cd681d691cfe51589b6a86a5c8a401c9 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandRemoteServiceTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandRemoteServiceTest.java @@ -189,7 +189,7 @@ class CommandRemoteServiceTest { void shouldHaveVersion() { var request = buildRequest(); - assertThat(request.getRelationVersion()).isEqualTo(VorgangHeaderTestFactory.VERSION); + assertThat(request.getRelationVersion()).isEqualTo(CommandTestFactory.RELATION_VERSION); } @Test diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandTestFactory.java b/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandTestFactory.java index 661019dcc25572791f62b9f56270f3498a3f1a01..653918b8ec82927a7bfcd3cf9df3aaecd5743e92 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandTestFactory.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/common/command/CommandTestFactory.java @@ -25,10 +25,11 @@ package de.ozgcloud.alfa.common.command; import java.util.UUID; +import org.apache.commons.lang3.RandomUtils; + import de.itvsh.kop.common.test.TestUtils; import de.ozgcloud.alfa.common.user.UserProfileTestFactory; import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; -import de.ozgcloud.alfa.vorgang.forwarding.ForwardingTestFactory; public class CommandTestFactory { @@ -37,8 +38,8 @@ public class CommandTestFactory { public static final CommandStatus STATUS = CommandStatus.FINISHED; public static final CommandOrder ORDER = CommandOrder.VORGANG_ANNEHMEN; - public static final String RELATION_ID = ForwardingTestFactory.ID; - public static final long RELATION_VERSION = VorgangHeaderTestFactory.VERSION; + public static final String RELATION_ID = UUID.randomUUID().toString(); + public static final long RELATION_VERSION = RandomUtils.nextLong(); public static Command create() { return createBuilder().build(); @@ -66,7 +67,11 @@ public class CommandTestFactory { .order(ORDER); } - public static String buildStatusPatchContent(CommandStatus status, CommandOrder order) { - return TestUtils.loadTextFile("jsonTemplates/command/statusPatch.json.tmpl", status.name(), order.name()); + public static String buildStatusPatchContent(CommandStatus status) { + return TestUtils.loadTextFile("jsonTemplates/command/statusPatch.json.tmpl", status.name()); + } + + public static String buildCreateVorgangCommandContent(CommandOrder order) { + return TestUtils.loadTextFile("jsonTemplates/command/createVorgangCommand.json.tmpl", order.name()); } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/common/errorhandling/ExceptionControllerTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/common/errorhandling/ExceptionControllerTest.java index 2748174c06e7cedb0c6fda3238a3d118f9e09f60..376bfbc299b60769cfe5231ce72b01ef67133d79 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/common/errorhandling/ExceptionControllerTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/common/errorhandling/ExceptionControllerTest.java @@ -312,64 +312,34 @@ class ExceptionControllerTest { } } - @DisplayName("Handle ServiceUnavailableException") + @DisplayName("Handle OrderNotAllowedException") @Nested - class TestHandleServiceUnavailableException { + class TestOrderNotAllowedException { - private final ServiceUnavailableException exception = new ServiceUnavailableException(MessageCode.USER_MANAGER_SERVICE_UNAVAILABLE, - new Throwable()); - - @Test - void shouldHaveMessageCode() { - var error = handleException(); - - assertThat(error.getIssues()).hasSize(1); - assertThat(error.getIssues().get(0).getMessageCode()).isEqualTo(MessageCode.USER_MANAGER_SERVICE_UNAVAILABLE); - } + private final OrderNotAllowedException exception = new OrderNotAllowedException(CommandOrder.EDIT_WIEDERVORLAGE); @Test void shouldHaveMessage() { - var error = handleException(); + var apiError = exceptionController.handleFunctionalException(exception); - assertThat(error.getIssues()).hasSize(1); - assertThat(error.getIssues().get(0).getMessage()).isEqualTo("Service Unavailable"); + var messageString = "Order 'EDIT_WIEDERVORLAGE' is not allowed. Expected 'VORGANG_LOESCHEN or LOESCH_ANFORDERUNG_ZURUECKNEHMEN'."; + assertThat(apiError.getIssues().get(0).getMessage()).contains(messageString); } - private ApiError handleException() { - return exceptionController.handleServiceUnavailableException(exception); - } - } - - @DisplayName("Handle RequestDataNotAllowedException") - @Nested - class TestRequestDataNotAllowedException { - - private final RequestDataNotAllowedException exception = new RequestDataNotAllowedException( - String.format("command order %s", CommandOrder.EDIT_WIEDERVORLAGE), CommandOrder.VORGANG_LOESCHEN.name()); - @Test - void shouldHaveMessage() { - var apiError = exceptionController.handleRequestDataNotAllowedException(exception); + void shouldHaveExceptionId() { + var apiError = exceptionController.handleFunctionalException(exception); - assertThat(apiError.getIssues()).hasSize(1).first().extracting(Issue::getMessage) - .isEqualTo(String.format( - "Request data 'command order EDIT_WIEDERVORLAGE' is not allowed for this operation. Expected is 'VORGANG_LOESCHEN'.")); + assertThat(apiError.getIssues()).hasSize(1).first().extracting(Issue::getExceptionId) + .isEqualTo(exception.getExceptionId()); } @Test void shouldHaveMessageCode() { - var apiError = exceptionController.handleRequestDataNotAllowedException(exception); + var apiError = exceptionController.handleFunctionalException(exception); - assertThat(apiError.getIssues()).hasSize(1).first().extracting(Issue::getMessageCode) - .isEqualTo(MessageCode.NOT_ALLOWED_DATA_FOR_OPERATION); - } - - @Test - void shouldHaveExceptionId() { - var apiError = exceptionController.handleRequestDataNotAllowedException(exception); - - assertThat(apiError.getIssues()).hasSize(1).first().extracting(Issue::getExceptionId) - .isEqualTo(exception.getExceptionId()); + var messageCode = "loeschanforderung.order_not_allowed"; + assertThat(apiError.getIssues()).hasSize(1).first().extracting(Issue::getMessageCode).isEqualTo(messageCode); } } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/historie/HistorieControllerITCase.java b/goofy-server/src/test/java/de/ozgcloud/alfa/historie/HistorieControllerITCase.java index ea8391a6b5b9fc6fd6cbf34c122cf68ae7f11eac..b8f140beb4457efb139c0f394b7c1afdb40ccb6d 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/historie/HistorieControllerITCase.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/historie/HistorieControllerITCase.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.stream.Stream; 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.springframework.beans.factory.annotation.Autowired; @@ -41,6 +42,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.web.servlet.MockMvc; +import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItemService; import de.ozgcloud.alfa.common.command.Command; import de.ozgcloud.alfa.common.command.CommandOrder; import de.ozgcloud.alfa.common.command.CommandService; @@ -55,16 +57,20 @@ class HistorieControllerITCase { @MockBean private CommandService service; + @MockBean + private VorgangAttachedItemService vorgangAttachedItemService; @Autowired private MockMvc mockMvc; + @DisplayName("Get all") @WithMockUser @Nested - class TestGetHistorieList { + class TestGetAll { @BeforeEach void init() { + when(vorgangAttachedItemService.findLoeschAnforderung(any())).thenReturn(Stream.empty()); when(service.findFinishedCommands(any())).thenReturn(createCommandStream()); } @@ -81,8 +87,7 @@ class HistorieControllerITCase { void shouldContainCommands() throws Exception { var response = mockMvc.perform(get(PATH + VorgangHeaderTestFactory.ID)).andExpect(status().isOk()); - response.andExpect(jsonPath("$._embedded.commandList[0].order") - .value(CommandOrder.VORGANG_ANNEHMEN.name())) + response.andExpect(jsonPath("$._embedded.commandList[0].order").value(CommandOrder.VORGANG_ANNEHMEN.name())) .andExpect(jsonPath("$._embedded.commandList[0]").isNotEmpty()); } diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungByVorgangControllerTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungByVorgangControllerTest.java index eacbda81b473a990ad4c7d0958433472f7093799..9172170d24c93be09f361368c0271ddc7d9378bb 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungByVorgangControllerTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungByVorgangControllerTest.java @@ -2,11 +2,15 @@ package de.ozgcloud.alfa.loeschanforderung; import static de.ozgcloud.alfa.common.command.CommandController.*; import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.nio.charset.StandardCharsets; + 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.mockito.ArgumentCaptor; @@ -18,15 +22,16 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import de.itvsh.kop.common.test.TestUtils; import de.ozgcloud.alfa.common.command.CommandOrder; import de.ozgcloud.alfa.common.command.CommandTestFactory; import de.ozgcloud.alfa.common.command.CreateCommand; import de.ozgcloud.alfa.common.errorhandling.ExceptionController; -import de.ozgcloud.alfa.vorgang.Vorgang; +import de.ozgcloud.alfa.loeschanforderung.LoeschAnforderungController.LoeschAnforderungByVorgangController; import de.ozgcloud.alfa.vorgang.VorgangController; import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; +import de.ozgcloud.alfa.vorgang.VorgangWithEingang; import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory; +import lombok.SneakyThrows; class LoeschAnforderungByVorgangControllerTest { @@ -34,7 +39,7 @@ class LoeschAnforderungByVorgangControllerTest { private LoeschAnforderungByVorgangController controller; @Mock - private LoeschAnforderungService loeschAnforderungService; + private LoeschAnforderungService service; @Mock private VorgangController vorgangController; @@ -46,58 +51,50 @@ class LoeschAnforderungByVorgangControllerTest { mockMvc = MockMvcBuilders.standaloneSetup(controller).setControllerAdvice(new ExceptionController()).build(); } + @DisplayName("Create LoeschAnforderung") @Nested class TestCreateLoeschAnforderung { - @Captor - private ArgumentCaptor<Vorgang> vorgangArgumentCaptor; @Captor private ArgumentCaptor<CreateCommand> createCommandArgumentCaptor; + private final VorgangWithEingang vorgang = VorgangWithEingangTestFactory.create(); + @BeforeEach void init() { - when(loeschAnforderungService.createLoeschAnforderung(any(), any(Vorgang.class), anyLong())).thenReturn(CommandTestFactory.create()); - when(vorgangController.getVorgang(VorgangHeaderTestFactory.ID)).thenReturn(VorgangWithEingangTestFactory.create()); + when(vorgangController.getVorgang(any())).thenReturn(vorgang); + when(service.createLoeschAnforderung(any(), any(), anyLong())).thenReturn(CommandTestFactory.create()); } + @SneakyThrows @Test - void shouldLoadVorgang() throws Exception { + void shouldLoadVorgang() { doRequest(); verify(vorgangController).getVorgang(VorgangHeaderTestFactory.ID); } + @SneakyThrows @Test - void shouldCallLoeschAnforderungService() throws Exception { + void shouldCallService() { doRequest(); - verify(loeschAnforderungService).createLoeschAnforderung( - createCommandArgumentCaptor.capture(), - vorgangArgumentCaptor.capture(), - eq(CommandTestFactory.RELATION_VERSION)); - - assertThat(vorgangArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo(VorgangWithEingangTestFactory.create()); + verify(service).createLoeschAnforderung(createCommandArgumentCaptor.capture(), eq(vorgang), eq(VorgangHeaderTestFactory.VERSION)); assertThat(createCommandArgumentCaptor.getValue().getOrder()).isEqualTo(CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN); } + @SneakyThrows @Test - void shouldReturnLinkToCommand() throws Exception { + void shouldReturnLinkToCommand() { doRequest().andExpect(header().stringValues("location", "http://localhost" + COMMANDS_PATH + "/" + CommandTestFactory.ID)); } + @SneakyThrows private ResultActions doRequest() throws Exception { - var requestBody = TestUtils.loadTextFile( - "jsonTemplates/command/createVorgangCommand.json.tmpl", - CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN.name()); - - return doRequest(requestBody); - } - - private ResultActions doRequest(String requestBody) throws Exception { - return mockMvc.perform(post( - LoeschAnforderungByVorgangController.CREATE_LOESCHANFORDERUNG_PATH, - CommandTestFactory.VORGANG_ID, - CommandTestFactory.RELATION_VERSION).content(requestBody).contentType(MediaType.APPLICATION_JSON).characterEncoding("UTF-8")) + var requestBody = CommandTestFactory.buildCreateVorgangCommandContent(CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN); + return mockMvc.perform(post(LoeschAnforderungByVorgangController.BASE_PATH, + VorgangHeaderTestFactory.ID, VorgangHeaderTestFactory.VERSION) + .content(requestBody).contentType(MediaType.APPLICATION_JSON).characterEncoding(StandardCharsets.UTF_8.name())) .andExpect(status().isCreated()); } } diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandByVorgangControllerTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandByVorgangControllerTest.java deleted file mode 100644 index 00829f333e1223336f5ecd2a6291ef0fb2f1021d..0000000000000000000000000000000000000000 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandByVorgangControllerTest.java +++ /dev/null @@ -1,165 +0,0 @@ -package de.ozgcloud.alfa.loeschanforderung; - -import static org.assertj.core.api.Assertions.*; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - -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.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.test.web.servlet.MockMvc; -import org.springframework.test.web.servlet.ResultActions; -import org.springframework.test.web.servlet.setup.MockMvcBuilders; - -import de.ozgcloud.alfa.common.command.CommandController; -import de.ozgcloud.alfa.common.command.CommandOrder; -import de.ozgcloud.alfa.common.command.CommandStatus; -import de.ozgcloud.alfa.common.command.CommandTestFactory; -import de.ozgcloud.alfa.common.command.StatusPatch; -import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; -import lombok.SneakyThrows; - -class LoeschAnforderungCommandByVorgangControllerTest { - - @Spy - @InjectMocks - private LoeschAnforderungCommandByVorgangController controller; - @Mock - private LoeschAnforderungService service; - - @Mock - private CommandController commandController; - - private MockMvc mockMvc; - - @BeforeEach - void initMockMvc() { - mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); - } - - @DisplayName("Revoke") - @Nested - class TestRevoke { - - @DisplayName("on revoke command status patch") - @Nested - class TestOnRevokedStatus { - - private static final CommandStatus STATUS = CommandStatus.REVOKED; - - @SneakyThrows - @Test - void shouldHandleVorgangZumLoeschenMarkierenCommand() { - doReturn(ResponseEntity.ok().build()).when(controller).handleVorgangZumLoeschenMarkierenCommand(any(), any(), any()); - - doRequest(STATUS, CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN).andExpect(status().isOk()); - - verify(controller).handleVorgangZumLoeschenMarkierenCommand(eq(VorgangHeaderTestFactory.ID), eq(CommandTestFactory.ID), any()); - } - - @Test - void shouldHandleLoeschAnforderungZuruecknehmenCommand() { - doReturn(ResponseEntity.ok().build()).when(controller).handleLoeschAnforderungZuruecknehmenCommand(any(), any()); - - doRequest(STATUS, CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN); - - verify(controller).handleLoeschAnforderungZuruecknehmenCommand(any(), any()); - } - } - - @SneakyThrows - @Test - void shouldReturnForbiddenOnNonRevokedCommand() { - var request = doRequest(CommandStatus.FINISHED, CommandTestFactory.ORDER); - - request.andExpect(status().isForbidden()); - } - - @SneakyThrows - private ResultActions doRequest(CommandStatus status, CommandOrder order) { - return mockMvc.perform(patch("/api/vorgangs/" + VorgangHeaderTestFactory.ID + "/commands/" + CommandTestFactory.ID) - .contentType(MediaType.APPLICATION_JSON_VALUE) - .content(CommandTestFactory.buildStatusPatchContent(status, order))) - .andDo(print()); - } - - @DisplayName("handle vorgang zum loeschen markieren command") - @Nested - class TestHandleVorgangZumLoeschenMarkierenCommand { - - private final StatusPatch statusPatch = StatusPatch.builder().build(); - - @Test - void shouldCallService() { - controller.handleVorgangZumLoeschenMarkierenCommand(VorgangHeaderTestFactory.ID, CommandTestFactory.ID, statusPatch); - - verify(service).deleteLoeschAnforderung(VorgangHeaderTestFactory.ID); - } - - @Test - void shouldCallController() { - controller.handleVorgangZumLoeschenMarkierenCommand(VorgangHeaderTestFactory.ID, CommandTestFactory.ID, statusPatch); - - verify(commandController).revoke(CommandTestFactory.ID, statusPatch); - } - - @Test - void shouldReturnOk() { - when(commandController.revoke(any(), any())).thenReturn(ResponseEntity.ok().build()); - - var result = controller.handleVorgangZumLoeschenMarkierenCommand(VorgangHeaderTestFactory.ID, CommandTestFactory.ID, statusPatch); - - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - } - } - - @DisplayName("handle loeschAnforderung zuruecknehmen command") - @Nested - class TestHandleLoeschVorgangZuruecknehmenCommand { - - private final StatusPatch statusPatch = StatusPatch.builder().build(); - - @Test - void shouldCreateLoeschAnforderung() { - controller.handleLoeschAnforderungZuruecknehmenCommand(CommandTestFactory.ID, statusPatch); - - verify(service).reCreateLoeschAnforderung(CommandTestFactory.ID); - } - - @Test - void shouldGetChangeStatusCommandId() { - controller.handleLoeschAnforderungZuruecknehmenCommand(CommandTestFactory.ID, statusPatch); - - verify(service).getChangeStatusCommandId(CommandTestFactory.ID); - } - - @Test - void shouldCallController() { - when(service.getChangeStatusCommandId(any())).thenReturn(CommandTestFactory.ID); - - controller.handleLoeschAnforderungZuruecknehmenCommand(CommandTestFactory.ID, statusPatch); - - verify(commandController).revoke(CommandTestFactory.ID, statusPatch); - } - - @Test - void shouldReturnOk() { - when(commandController.revoke(any(), any())).thenReturn(ResponseEntity.ok().build()); - - var result = controller.handleLoeschAnforderungZuruecknehmenCommand(VorgangHeaderTestFactory.ID, statusPatch); - - assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); - } - } - } -} diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandControllerITCase.java b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandControllerITCase.java index 226c4dc227f4256af2f020201983468b648dd231..4ab04b7ef7a132ff4be843f5a8dacf7291e3ebbf 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandControllerITCase.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandControllerITCase.java @@ -5,6 +5,8 @@ import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.nio.charset.StandardCharsets; + import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; @@ -63,7 +65,9 @@ class LoeschAnforderungCommandControllerITCase { void shouldReturnForbidden() throws Exception { when(loeschAnforderungService.isAllowedToVorgangLoeschen(loeschAnforderung)).thenReturn(false); - doRequest(CommandOrder.VORGANG_LOESCHEN).andExpect(status().isForbidden()); + var response = doRequest(CommandOrder.VORGANG_LOESCHEN); + + response.andExpect(status().isForbidden()); } @WithMockUser(roles = UserRole.VERWALTUNG_LOESCHEN) @@ -71,7 +75,9 @@ class LoeschAnforderungCommandControllerITCase { void shouldReturnCreated() throws Exception { when(loeschAnforderungService.isAllowedToVorgangLoeschen(loeschAnforderung)).thenReturn(true); - doRequest(CommandOrder.VORGANG_LOESCHEN).andExpect(status().isCreated()); + var response = doRequest(CommandOrder.VORGANG_LOESCHEN).andExpect(status().isCreated()); + + response.andExpect(status().isCreated()); } } @@ -95,7 +101,9 @@ class LoeschAnforderungCommandControllerITCase { void shouldReturnCreated() throws Exception { when(loeschAnforderungService.isAllowedToVorgangLoeschen(loeschAnforderung)).thenReturn(false); - doRequest(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN).andExpect(status().isCreated()); + var response = doRequest(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN); + + response.andExpect(status().isCreated()); } @WithMockUser(roles = UserRole.VERWALTUNG_POSTSTELLE) @@ -103,7 +111,9 @@ class LoeschAnforderungCommandControllerITCase { void shouldReturnForbidden() throws Exception { when(loeschAnforderungService.isAllowedToVorgangLoeschen(loeschAnforderung)).thenReturn(false); - doRequest(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN).andExpect(status().isForbidden()); + var response = doRequest(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN); + + response.andExpect(status().isForbidden()); } } } @@ -113,8 +123,7 @@ class LoeschAnforderungCommandControllerITCase { "jsonTemplates/command/createVorgangCommand.json.tmpl", commandOrder.name()); - return mockMvc.perform(post( - LoeschAnforderungCommandController.COMMAND_PATH, - LoeschAnforderungTestFactory.ID).content(requestBody).contentType(MediaType.APPLICATION_JSON).characterEncoding("UTF-8")); + return mockMvc.perform(post(LoeschAnforderungCommandController.BASE_PATH, LoeschAnforderungTestFactory.ID) + .content(requestBody).contentType(MediaType.APPLICATION_JSON).characterEncoding(StandardCharsets.UTF_8.name())); } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandControllerTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandControllerTest.java index acf8ba0fd868f1215e704c5a69947d9d6332b56e..d5ab14a18f70eb0ef33c791bb17bcefee961e718 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandControllerTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandControllerTest.java @@ -2,39 +2,52 @@ package de.ozgcloud.alfa.loeschanforderung; import static de.ozgcloud.alfa.common.command.CommandController.*; import static org.assertj.core.api.Assertions.*; +import static org.hamcrest.CoreMatchers.*; import static org.mockito.ArgumentMatchers.*; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.nio.charset.StandardCharsets; + 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.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; +import org.springframework.hateoas.EntityModel; +import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import de.itvsh.kop.common.test.TestUtils; import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItem; import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItemService; import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItemTestFactory; +import de.ozgcloud.alfa.common.command.Command; +import de.ozgcloud.alfa.common.command.CommandController; import de.ozgcloud.alfa.common.command.CommandOrder; +import de.ozgcloud.alfa.common.command.CommandStatus; import de.ozgcloud.alfa.common.command.CommandTestFactory; import de.ozgcloud.alfa.common.command.CreateCommand; +import de.ozgcloud.alfa.common.command.StatusPatch; import de.ozgcloud.alfa.common.errorhandling.ExceptionController; -import de.ozgcloud.alfa.common.errorhandling.MessageCode; import de.ozgcloud.alfa.vorgang.VorgangController; import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; import de.ozgcloud.alfa.vorgang.VorgangWithEingang; import de.ozgcloud.alfa.vorgang.VorgangWithEingangTestFactory; +import lombok.SneakyThrows; class LoeschAnforderungCommandControllerTest { + @Spy @InjectMocks private LoeschAnforderungCommandController controller; @@ -47,6 +60,9 @@ class LoeschAnforderungCommandControllerTest { @Mock private VorgangAttachedItemService vorgangAttachedItemService; + @Mock + private CommandController commandController; + private MockMvc mockMvc; @BeforeEach @@ -54,6 +70,7 @@ class LoeschAnforderungCommandControllerTest { mockMvc = MockMvcBuilders.standaloneSetup(controller).setControllerAdvice(new ExceptionController()).build(); } + @DisplayName("Create command") @Nested class TestCreateCommand { @@ -80,8 +97,9 @@ class LoeschAnforderungCommandControllerTest { @Test void shouldReturnLinkToCommand() throws Exception { - doRequest(CommandOrder.VORGANG_LOESCHEN).andExpect( - header().stringValues("location", "http://localhost" + COMMANDS_PATH + "/" + CommandTestFactory.ID)); + var response = doRequest(CommandOrder.VORGANG_LOESCHEN); + + response.andExpect(header().stringValues("location", "http://localhost" + COMMANDS_PATH + "/" + CommandTestFactory.ID)); } } @@ -124,32 +142,181 @@ class LoeschAnforderungCommandControllerTest { @Test void shouldReturnLinkToCommand() throws Exception { - doRequest(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN).andExpect( - header().stringValues("location", "http://localhost" + COMMANDS_PATH + "/" + CommandTestFactory.ID)); + var response = doRequest(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN); + + response.andExpect(header().stringValues("location", "http://localhost" + COMMANDS_PATH + "/" + CommandTestFactory.ID)); } } @Test - void shouldThrowRequestDataNotAllowedException() throws Exception { - doRequest(CommandOrder.CREATE_KOMMENTAR).andExpect(status().isUnprocessableEntity()) + void shouldThrowOrderNotAllowedException() throws Exception { + var message = "Order 'CREATE_KOMMENTAR' is not allowed. Expected 'VORGANG_LOESCHEN or LOESCH_ANFORDERUNG_ZURUECKNEHMEN'."; + + doRequest(CommandOrder.CREATE_KOMMENTAR).andExpect(status().isBadRequest()) .andExpect(jsonPath("issues[0].field").isEmpty()) .andExpect(jsonPath("issues[0].exceptionId").isNotEmpty()) - .andExpect(jsonPath("issues[0].messageCode").value(MessageCode.NOT_ALLOWED_DATA_FOR_OPERATION)) - .andExpect(jsonPath("issues[0].message").value( - "Request data 'command order CREATE_KOMMENTAR' is not allowed for this operation. Expected is 'VORGANG_LOESCHEN or LOESCH_ANFORDERUNG_ZURUECKNEHMEN'.")); - ; + .andExpect(jsonPath("issues[0].messageCode").value("loeschanforderung.order_not_allowed")) + .andExpect(jsonPath("issues[0].message").value(containsString(message))); } private ResultActions doRequest(CommandOrder commandOrder) throws Exception { - var requestBody = TestUtils.loadTextFile( - "jsonTemplates/command/createVorgangCommand.json.tmpl", - commandOrder.name()); + return mockMvc.perform(post(LoeschAnforderungCommandController.BASE_PATH, LoeschAnforderungTestFactory.ID) + .content(CommandTestFactory.buildCreateVorgangCommandContent(commandOrder)) + .contentType(MediaType.APPLICATION_JSON) + .characterEncoding(StandardCharsets.UTF_8.name())); + } + } + + @DisplayName("Revoke") + @Nested + class TestRevoke { + + @DisplayName("on revoke command status patch") + @Nested + class TestOnRevokedStatus { + + private static final CommandStatus STATUS = CommandStatus.REVOKED; + + @Test + void shouldGetCommand() { + when(commandController.getById(any())).thenReturn(EntityModel.of(CommandTestFactory.create())); + + doRequest(STATUS); + + verify(commandController).getById(CommandTestFactory.ID); + } + + @DisplayName("with VORGANG_ZUM_LOESCHEN_MARKIEREN order") + @Nested + class TestWithVorgangZumLoeschenMarkierenOrder { - return mockMvc.perform(post( - LoeschAnforderungCommandController.COMMAND_PATH, - LoeschAnforderungTestFactory.ID).content(requestBody).contentType(MediaType.APPLICATION_JSON).characterEncoding("UTF-8")); + private final Command command = CommandTestFactory.createBuilder().order(CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN).build(); + + @BeforeEach + void mockCommandController() { + when(commandController.getById(any())).thenReturn(EntityModel.of(command)); + doReturn(ResponseEntity.ok().build()).when(controller).handleVorgangZumLoeschenMarkierenRevokeCommand(any(), any(), any()); + } + + @SneakyThrows + @Test + void shouldHandleVorgangZumLoeschenMarkierenRevokeCommand() { + doRequest(STATUS).andExpect(status().isOk()); + + verify(controller).handleVorgangZumLoeschenMarkierenRevokeCommand(eq(LoeschAnforderungTestFactory.ID), eq(command), any()); + } + } + + @DisplayName("with LOESCH_ANFORDERUNG_ZURUECKNEHMEN order") + @Nested + class TestWithLoeschAnforderungZuruecknehmenOrder { + + private final Command command = CommandTestFactory.createBuilder().order(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN).build(); + + @BeforeEach + void mockCommandController() { + when(commandController.getById(any())).thenReturn(EntityModel.of(command)); + doReturn(ResponseEntity.ok().build()).when(controller).handleLoeschAnforderungZuruecknehmenRevokeCommand(any(), any()); + } + + @Test + void shouldHandleLoeschAnforderungZuruecknehmenRevokeCommand() { + doRequest(STATUS); + + verify(controller).handleLoeschAnforderungZuruecknehmenRevokeCommand(any(), any()); + } + } } - } + @SneakyThrows + @Test + void shouldReturnForbiddenOnNonRevokedCommand() { + var request = doRequest(CommandStatus.FINISHED); + + request.andExpect(status().isForbidden()); + } + + @SneakyThrows + private ResultActions doRequest(CommandStatus status) { + return mockMvc.perform( + patch(LoeschAnforderungCommandController.BASE_PATH + "/{commandId}", LoeschAnforderungTestFactory.ID, CommandTestFactory.ID) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(CommandTestFactory.buildStatusPatchContent(status))); + } + + @DisplayName("handle vorgang zum loeschen markieren revoke command") + @Nested + class TestHandleVorgangZumLoeschenMarkierenRevokeCommand { + + private final StatusPatch statusPatch = StatusPatch.builder().build(); + @Test + void shouldCallService() { + handVorgangZumLoeschenMarkierenCommand(); + + verify(loeschAnforderungService).deleteLoeschAnforderung(LoeschAnforderungTestFactory.ID); + } + + @Test + void shouldCallController() { + handVorgangZumLoeschenMarkierenCommand(); + + verify(commandController).revoke(CommandTestFactory.ID, statusPatch); + } + + @Test + void shouldReturnOk() { + when(commandController.revoke(any(), any())).thenReturn(ResponseEntity.ok().build()); + + var result = handVorgangZumLoeschenMarkierenCommand(); + + assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); + } + + private ResponseEntity<EntityModel<Command>> handVorgangZumLoeschenMarkierenCommand() { + return controller.handleVorgangZumLoeschenMarkierenRevokeCommand(LoeschAnforderungTestFactory.ID, CommandTestFactory.create(), + statusPatch); + } + } + + @DisplayName("handle loeschAnforderung zuruecknehmen revoke command") + @Nested + class TestHandleLoeschVorgangZuruecknehmenRevokeCommand { + + private final StatusPatch statusPatch = StatusPatch.builder().build(); + private final Command command = CommandTestFactory.create(); + + @Test + void shouldCreateLoeschAnforderung() { + controller.handleLoeschAnforderungZuruecknehmenRevokeCommand(command, statusPatch); + + verify(loeschAnforderungService).reCreateLoeschAnforderung(command); + } + + @Test + void shouldGetChangeStatusCommandId() { + controller.handleLoeschAnforderungZuruecknehmenRevokeCommand(command, statusPatch); + + verify(loeschAnforderungService).getChangeStatusCommandId(command); + } + + @Test + void shouldCallController() { + when(loeschAnforderungService.getChangeStatusCommandId(any())).thenReturn(CommandTestFactory.ID); + + controller.handleLoeschAnforderungZuruecknehmenRevokeCommand(command, statusPatch); + + verify(commandController).revoke(CommandTestFactory.ID, statusPatch); + } + + @Test + void shouldReturnOk() { + when(commandController.revoke(any(), any())).thenReturn(ResponseEntity.ok().build()); + + var result = controller.handleLoeschAnforderungZuruecknehmenRevokeCommand(command, statusPatch); + + assertThat(result.getStatusCode()).isEqualTo(HttpStatus.OK); + } + } + } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandProzessorTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandProzessorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..74b04a5bee8c54c496fb2488717922a83068c82c --- /dev/null +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungCommandProzessorTest.java @@ -0,0 +1,134 @@ +package de.ozgcloud.alfa.loeschanforderung; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; + +import java.util.Optional; + +import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.EnumSource.Mode; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.Link; + +import de.ozgcloud.alfa.common.UserProfileUrlProvider; +import de.ozgcloud.alfa.common.UserProfileUrlProviderTestFactory; +import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItemTestFactory; +import de.ozgcloud.alfa.common.command.Command; +import de.ozgcloud.alfa.common.command.CommandOrder; +import de.ozgcloud.alfa.common.command.CommandStatus; +import de.ozgcloud.alfa.common.command.CommandTestFactory; + +class LoeschAnforderungCommandProzessorTest { + + @Spy + @InjectMocks + private LoeschAnforderungCommandProzessor prozessor; + + @Mock + private LoeschAnforderungService service; + + @DisplayName("Prozess") + @Nested + class TestProcess { + + @BeforeEach + void mock() { + UserProfileUrlProviderTestFactory.initUserProfileUrlProvider(new UserProfileUrlProvider()); + } + + @DisplayName("on revokeable") + @Nested + class TestRevokeableCommand { + + @DisplayName("zum loeschen markieren command") + @Nested + class TestLoeschAnforderungCommand { + + private final Command finishedCommand = CommandTestFactory.createBuilder().status(CommandStatus.FINISHED).build(); + + @BeforeEach + void mock() { + when(service.findLoeschAnforderung(any())).thenReturn(Optional.of(VorgangAttachedItemTestFactory.create())); + } + + @Test + void shouldAddLink() { + var entityModel = EntityModel.of(finishedCommand.toBuilder().order(CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN).build()); + + var prozessedCommand = prozessor.process(entityModel); + + assertThat(prozessedCommand.getLink(LoeschAnforderungCommandProzessor.REL_REVOKE)).isPresent().get().extracting(Link::getHref) + .isEqualTo("/api/loeschanforderungs/" + VorgangAttachedItemTestFactory.ID + "/commands/" + CommandTestFactory.ID); + } + + @Test + void shouldCallService() { + var entityModel = EntityModel.of(finishedCommand.toBuilder().order(CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN).build()); + + var prozessedCommand = prozessor.process(entityModel); + + assertThat(prozessedCommand.getLink(LoeschAnforderungCommandProzessor.REL_REVOKE)).isPresent().get().extracting(Link::getHref) + .isEqualTo("/api/loeschanforderungs/" + VorgangAttachedItemTestFactory.ID + "/commands/" + CommandTestFactory.ID); + } + } + + @DisplayName("loeschAnforderung zuruecknehmen command") + @Nested + class TestLoeschAnforderungZuruecknehmenCommand { + + private final Command finishedCommand = CommandTestFactory.createBuilder().status(CommandStatus.FINISHED).build(); + + @Test + void shouldAddLink() { + var entityModel = EntityModel.of(finishedCommand.toBuilder().order(CommandOrder.LOESCH_ANFORDERUNG_ZURUECKNEHMEN).build()); + + var prozessedCommand = prozessor.process(entityModel); + + assertThat(prozessedCommand.getLink(LoeschAnforderungCommandProzessor.REL_REVOKE)).isPresent().get().extracting(Link::getHref) + .isEqualTo("/api/loeschanforderungs/" + CommandTestFactory.RELATION_ID + "/commands/" + CommandTestFactory.ID); + } + } + + @DisplayName("on other commands") + @Nested + class TestOnOtherCommand { + + private final Command finishedCommand = CommandTestFactory.createBuilder().status(CommandStatus.FINISHED).build(); + + @DisplayName("except zum loeschen markieren") + @Nested + class TestsExceptLoeschAnforderungZuruecknehmen { + + @ParameterizedTest + @EnumSource(mode = Mode.EXCLUDE, names = { "VORGANG_ZUM_LOESCHEN_MARKIEREN" }) + void shouldNotCallService(CommandOrder order) { + var command = finishedCommand.toBuilder().order(order).build(); + + prozessor.process(EntityModel.of(command)); + + verify(service, never()).findLoeschAnforderung(any()); + } + } + + @ParameterizedTest + @EnumSource(mode = Mode.EXCLUDE, names = { "VORGANG_ZUM_LOESCHEN_MARKIEREN", "LOESCH_ANFORDERUNG_ZURUECKNEHMEN" }) + void NotAddRevokeLink(CommandOrder order) { + var command = finishedCommand.toBuilder().order(order).build(); + + var prozessedCommand = prozessor.process(EntityModel.of(command)); + + assertThat(prozessedCommand.getLink(LoeschAnforderungCommandProzessor.REL_REVOKE)).isEmpty(); + } + } + } + } +} \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungControllerTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungControllerTest.java index 70603dce3653fa3c3ddbe8f54ada202d462583d6..a0ea03964f79264344bb89b24f16bddcc4cf0ed1 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungControllerTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungControllerTest.java @@ -17,6 +17,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import de.ozgcloud.alfa.common.UserProfileUrlProvider; import de.ozgcloud.alfa.common.errorhandling.ExceptionController; +import lombok.SneakyThrows; class LoeschAnforderungControllerTest { @@ -48,14 +49,14 @@ class LoeschAnforderungControllerTest { } @Test - void shouldLoadLoeschAnforderung() throws Exception { + void shouldLoadLoeschAnforderung() { doRequest(); verify(loeschAnforderungService).getById(LoeschAnforderungTestFactory.ID); } @Test - void shouldCallModelAssembler() throws Exception { + void shouldCallModelAssembler() { doRequest(); verify(modelAssembler).toModel(loeschAnforderung); @@ -65,14 +66,14 @@ class LoeschAnforderungControllerTest { void shouldReturn200() throws Exception { initUserProfileUrlProvider(new UserProfileUrlProvider()); - doRequest().andExpect(status().isOk()); + var response = doRequest(); + + response.andExpect(status().isOk()); } - private ResultActions doRequest() throws Exception { - return mockMvc.perform(get( - LoeschAnforderungController.LOESCHANFORDERUNG_PATH, - LoeschAnforderungTestFactory.ID)); + @SneakyThrows + private ResultActions doRequest() { + return mockMvc.perform(get(LoeschAnforderungController.BASE_PATH + "/" + LoeschAnforderungTestFactory.ID)); } } - } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungModelAssemblerTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungModelAssemblerTest.java index 311ac44236a5c8c9c5a6d044231ee0bde6746e87..0314293d15b0532dc2e8d1e7106a4c8c48347bda 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungModelAssemblerTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungModelAssemblerTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; import org.springframework.web.util.UriTemplate; @@ -21,7 +22,6 @@ class LoeschAnforderungModelAssemblerTest { @InjectMocks private LoeschAnforderungModelAssembler modelAssembler; - @Mock private LoeschAnforderungService loeschAnforderungService; @@ -34,62 +34,72 @@ class LoeschAnforderungModelAssemblerTest { @DisplayName("Build resource") class TestToModel { - private static final UriTemplate EXPECTED_SELF_LINK_URI_TEMPLATE = new UriTemplate(LoeschAnforderungController.LOESCHANFORDERUNG_PATH); - private static final UriTemplate EXPECTED_LINK_COMMANDS_URI_TEMPLATE = new UriTemplate(LoeschAnforderungCommandController.COMMAND_PATH); + private static final UriTemplate LOESCH_ANFORDERUNG_COMMAND_URI_TEMPLATE = new UriTemplate(LoeschAnforderungCommandController.BASE_PATH); + + private final LoeschAnforderung loeschAnforderung = LoeschAnforderungTestFactory.create(); @Test void shouldBuildModel() { - var model = modelAssembler.toModel(LoeschAnforderungTestFactory.create()); + var model = toModel(); assertThat(model.getContent()).usingRecursiveComparison().isEqualTo(LoeschAnforderungTestFactory.create()); } @Test void shouldHaveSelfLink() { - var model = modelAssembler.toModel(LoeschAnforderungTestFactory.create()); + var model = toModel(); - var link = model.getLink(IanaLinkRelations.SELF); - assertThat(link).isPresent(); - assertThat(link.get().getHref()).isEqualTo(EXPECTED_SELF_LINK_URI_TEMPLATE.expand(LoeschAnforderungTestFactory.ID).toString()); + assertThat(model.getLink(IanaLinkRelations.SELF)).isPresent().get().extracting(Link::getHref) + .isEqualTo(LoeschAnforderungController.BASE_PATH + "/" + LoeschAnforderungTestFactory.ID); } @Test - void shouldAddExecuteLoeschenLink() { - when(loeschAnforderungService.isAllowedToVorgangLoeschen(any())).thenReturn(true); - - var model = modelAssembler.toModel(LoeschAnforderungTestFactory.create()); + void shouldCheckIfAllowedToVorgangLoeschen() { + toModel(); - assertThat(model.getLink(LoeschAnforderungModelAssembler.REL_EXECUTE_LOESCHEN)).isPresent() - .get() - .extracting(Link::getHref) - .isEqualTo(EXPECTED_LINK_COMMANDS_URI_TEMPLATE.expand(LoeschAnforderungTestFactory.ID).toString()); + verify(loeschAnforderungService).isAllowedToVorgangLoeschen(loeschAnforderung); } - @Test - void shouldNotAddExecuteLoeschenLink() { - when(loeschAnforderungService.isAllowedToVorgangLoeschen(any())).thenReturn(false); + @DisplayName("execute loeschen link") + @Nested + class TestExecuteLoeschenLink { - var model = modelAssembler.toModel(LoeschAnforderungTestFactory.create()); + @Test + void shouldBeAdded() { + when(loeschAnforderungService.isAllowedToVorgangLoeschen(any())).thenReturn(true); - assertThat(model.getLink(LoeschAnforderungModelAssembler.REL_EXECUTE_LOESCHEN)).isEmpty(); - } + var model = toModel(); - @Test - void shouldCheckIfAllowedToVorgangLoeschen() { - var loeschAnforderung = LoeschAnforderungTestFactory.create(); + assertThat(model.getLink(LoeschAnforderungModelAssembler.REL_EXECUTE_LOESCHEN)).isPresent().get().extracting(Link::getHref) + .isEqualTo(LOESCH_ANFORDERUNG_COMMAND_URI_TEMPLATE.expand(LoeschAnforderungTestFactory.ID).toString()); + } - modelAssembler.toModel(loeschAnforderung); + @Test + void shouldNotBeAdded() { + when(loeschAnforderungService.isAllowedToVorgangLoeschen(any())).thenReturn(false); - verify(loeschAnforderungService).isAllowedToVorgangLoeschen(loeschAnforderung); + var model = toModel(); + + assertThat(model.getLink(LoeschAnforderungModelAssembler.REL_EXECUTE_LOESCHEN)).isEmpty(); + } } - @Test - void shouldAddLoeschAnforderungZuruecknehmenLink() { - var model = modelAssembler.toModel(LoeschAnforderungTestFactory.create()); + @DisplayName("loeschAnforderung zuruecknehmen link") + @Nested + class TestLoeschAnforderungZuruecknehmen { + + @Test + void shouldBeAdded() { + var model = toModel(); + + var link = model.getLink(LoeschAnforderungModelAssembler.REL_LOESCH_ANFORDERUNG_ZURUECKNEHMEN); + assertThat(link).isPresent().map(Link::getHref) + .hasValue(LOESCH_ANFORDERUNG_COMMAND_URI_TEMPLATE.expand(LoeschAnforderungTestFactory.ID).toString()); + } + } - var link = model.getLink(LoeschAnforderungModelAssembler.REL_LOESCH_ANFORDERUNG_ZURUECKNEHMEN); - assertThat(link).isPresent().map(Link::getHref) - .hasValue(EXPECTED_LINK_COMMANDS_URI_TEMPLATE.expand(LoeschAnforderungTestFactory.ID).toString()); + private EntityModel<LoeschAnforderung> toModel() { + return modelAssembler.toModel(loeschAnforderung); } } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungServiceTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungServiceTest.java index 6ae4de5796995ac3c288bda8eff05ee83e673bbb..a89a638bcb949bad520c7bab63b46b8c54740a16 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungServiceTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungServiceTest.java @@ -5,8 +5,6 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.util.List; -import java.util.Map; -import java.util.Optional; import java.util.UUID; import java.util.stream.Stream; @@ -71,20 +69,16 @@ class LoeschAnforderungServiceTest { @Test void shouldCallCurrentUserService() { - service.createLoeschAnforderung( - CommandTestFactory.createCreateCommand(), - VorgangWithEingangTestFactory.create(), - CommandTestFactory.RELATION_VERSION); + service.createLoeschAnforderung(CommandTestFactory.createCreateCommand(), VorgangWithEingangTestFactory.create(), + VorgangHeaderTestFactory.VERSION); verify(currentUserService).getUserId(); } @Test void shouldCallVorgangAttachedItemService() { - service.createLoeschAnforderung( - CommandTestFactory.createCreateCommand(), - VorgangWithEingangTestFactory.create(), - CommandTestFactory.RELATION_VERSION); + service.createLoeschAnforderung(CommandTestFactory.createCreateCommand(), VorgangWithEingangTestFactory.create(), + VorgangHeaderTestFactory.VERSION); verify(vorgangAttachedItemService).createNewLoeschAnforderung(commandBodyArgumentCaptor.capture(), eq(VorgangHeaderTestFactory.ID)); @@ -92,7 +86,6 @@ class LoeschAnforderungServiceTest { .extracting(LoeschAnforderung::getPrevStatus, LoeschAnforderung::getRequestedBy) .containsExactly(VorgangHeaderTestFactory.STATUS, UserProfileTestFactory.ID); } - } @Nested @@ -104,7 +97,7 @@ class LoeschAnforderungServiceTest { @Test void shouldCallCommandService() { var createCommand = CreateCommand.builder().order(CommandOrder.VORGANG_ZUM_LOESCHEN_MARKIEREN).build(); - service.createCreateCommand(createCommand, VorgangWithEingangTestFactory.create(), CommandTestFactory.RELATION_VERSION); + service.createCreateCommand(createCommand, VorgangWithEingangTestFactory.create(), VorgangHeaderTestFactory.VERSION); verify(commandService).createCommand(createCommandArgumentCaptor.capture(), anyLong()); @@ -121,7 +114,7 @@ class LoeschAnforderungServiceTest { var result = service.createCreateCommand( CommandTestFactory.createCreateCommand(), VorgangWithEingangTestFactory.create(), - CommandTestFactory.RELATION_VERSION); + VorgangHeaderTestFactory.VERSION); assertThat(result).isEqualTo(command); } @@ -147,9 +140,9 @@ class LoeschAnforderungServiceTest { @Test void shouldCreateCreateCommand() { - service.createLoeschAnforderung(createCommand, vorgang, CommandTestFactory.RELATION_VERSION); + service.createLoeschAnforderung(createCommand, vorgang, VorgangHeaderTestFactory.VERSION); - verify(service).createCreateCommand(createCommand, vorgang, CommandTestFactory.RELATION_VERSION); + verify(service).createCreateCommand(createCommand, vorgang, VorgangHeaderTestFactory.VERSION); } } @@ -222,46 +215,39 @@ class LoeschAnforderungServiceTest { } @Nested - @DisplayName("Loesche Vorgang") - class TestExecuteLoeschen { + @DisplayName("Vorgang loeschen") + class TestVorgangLoeschen { - private LoeschAnforderung loeschAnforderung; + private LoeschAnforderung loeschAnforderung = LoeschAnforderungTestFactory.create(); + private Command created = CommandTestFactory.create(); @Captor private ArgumentCaptor<CreateCommand> createCommandArgumentCaptor; @BeforeEach void init() { - loeschAnforderung = LoeschAnforderungTestFactory.create(); doReturn(loeschAnforderung).when(service).getById(LoeschAnforderungTestFactory.ID); + when(commandService.createCommand(any())).thenReturn(created); } @Test void shouldCallCommandService() { - service.vorgangLoeschen( - CreateCommand.builder().order(CommandOrder.VORGANG_LOESCHEN).build(), - LoeschAnforderungTestFactory.ID); + service.vorgangLoeschen(CommandTestFactory.createCreateCommand(), LoeschAnforderungTestFactory.ID); - verify(commandService).createCommandDeprecated(createCommandArgumentCaptor.capture()); - assertThat(createCommandArgumentCaptor.getValue()).usingRecursiveComparison().isEqualTo( - CreateCommand.builder().vorgangId(LoeschAnforderungTestFactory.VORGANG_ID) - .relationId(LoeschAnforderungTestFactory.VORGANG_ID) - .order(CommandOrder.VORGANG_LOESCHEN) - .build()); + verify(commandService).createCommand(createCommandArgumentCaptor.capture()); + assertThat(createCommandArgumentCaptor.getValue()).usingRecursiveComparison() + .ignoringFields("vorgangId", "relationId").isEqualTo(CommandTestFactory.createCreateCommand()); + assertThat(createCommandArgumentCaptor.getValue().getVorgangId()).isEqualTo(VorgangHeaderTestFactory.ID); + assertThat(createCommandArgumentCaptor.getValue().getRelationId()).isEqualTo(VorgangHeaderTestFactory.ID); } @Test void shouldReturnCreatedCommand() { - var created = CommandTestFactory.create(); - when(commandService.createCommandDeprecated(any())).thenReturn(created); - var result = service.vorgangLoeschen( - CreateCommand.builder().order(CommandOrder.VORGANG_LOESCHEN).build(), - LoeschAnforderungTestFactory.ID); + CreateCommand.builder().order(CommandOrder.VORGANG_LOESCHEN).build(), LoeschAnforderungTestFactory.ID); assertThat(result).isEqualTo(created); } - } @Nested @@ -634,29 +620,23 @@ class LoeschAnforderungServiceTest { private final VorgangAttachedItem vorgangAttachedItem = VorgangAttachedItemTestFactory.create(); - @Test - void shouldFindLoeschAnforderung() { - doReturn(Optional.of(vorgangAttachedItem)).when(service).findLoeschAnforderung(anyString()); - - service.deleteLoeschAnforderung(VorgangHeaderTestFactory.ID); - - verify(service).findLoeschAnforderung(VorgangHeaderTestFactory.ID); + @BeforeEach + void mock() { + when(vorgangAttachedItemService.getById(anyString())).thenReturn(vorgangAttachedItem); } @Test - void shouldDeleteVorgangAttachedItemIfPresent() { - doReturn(Optional.of(vorgangAttachedItem)).when(service).findLoeschAnforderung(anyString()); + void shouldGetLoeschAnforderung() { + service.deleteLoeschAnforderung(LoeschAnforderungTestFactory.ID); - service.deleteLoeschAnforderung(VorgangHeaderTestFactory.ID); - - verify(vorgangAttachedItemService).deleteAttachedItem(vorgangAttachedItem); + verify(vorgangAttachedItemService).getById(LoeschAnforderungTestFactory.ID); } @Test - void shouldThrowExceptionIfNoLoeschAnforderungFoun() { - doReturn(Optional.empty()).when(service).findLoeschAnforderung(anyString()); + void shouldDeleteVorgangAttachedItem() { + service.deleteLoeschAnforderung(LoeschAnforderungTestFactory.ID); - assertThatThrownBy(() -> service.deleteLoeschAnforderung(VorgangHeaderTestFactory.ID)).isInstanceOf(TechnicalException.class); + verify(vorgangAttachedItemService).deleteAttachedItem(vorgangAttachedItem); } } @@ -668,43 +648,41 @@ class LoeschAnforderungServiceTest { @Nested class TestWorkflow { - private static final String DELETE_VORGANG_ATTACHED_ITEM_ID = UUID.randomUUID().toString(); private final Command zuruecknehmenCommand = CommandTestFactory.createBuilder() - .body(Map.of(DeleteLoeschAnforderung.DELETE_ATTACHED_ITEM_COMMAND_ID_FIELD, DELETE_VORGANG_ATTACHED_ITEM_ID)) + .body(LoeschAnforderungTestFactory.createDeleteLoeschAnforderungBodyMap()) .build(); private final Command deleteVorgangAttachedItemCommand = CommandTestFactory.create(); @BeforeEach void mock() { - when(commandService.getById(CommandTestFactory.ID)).thenReturn(zuruecknehmenCommand); - when(commandService.getById(DELETE_VORGANG_ATTACHED_ITEM_ID)).thenReturn(deleteVorgangAttachedItemCommand); + when(commandService.getById(anyString())).thenReturn(deleteVorgangAttachedItemCommand); when(mapper.fromCommand(any())).thenReturn(LoeschAnforderungTestFactory.create()); } @Test void shouldGetLoeschAnforderungZuruecknehmenCommand() { - service.reCreateLoeschAnforderung(CommandTestFactory.ID); + service.reCreateLoeschAnforderung(zuruecknehmenCommand); - verify(commandService).getById(CommandTestFactory.ID); + verify(commandService).getById(LoeschAnforderungTestFactory.DELETE_VORGANG_ATTACHED_ITEM_ID); } @Test void shouldGetDeleteLoeschAnforderungCommand() { - service.reCreateLoeschAnforderung(CommandTestFactory.ID); + service.reCreateLoeschAnforderung(zuruecknehmenCommand); - verify(commandService).getById(DELETE_VORGANG_ATTACHED_ITEM_ID); + verify(commandService).getById(LoeschAnforderungTestFactory.DELETE_VORGANG_ATTACHED_ITEM_ID); } @Test void shouldCallMapper() { - service.reCreateLoeschAnforderung(CommandTestFactory.ID); + service.reCreateLoeschAnforderung(zuruecknehmenCommand); verify(mapper).fromCommand(deleteVorgangAttachedItemCommand); } @Test void shouldCreateNewLoeschAnforderung() { - service.reCreateLoeschAnforderung(CommandTestFactory.ID); + service.reCreateLoeschAnforderung(zuruecknehmenCommand); verify(vorgangAttachedItemService).createNewLoeschAnforderung(any(), eq(VorgangHeaderTestFactory.ID)); } @@ -715,28 +693,15 @@ class LoeschAnforderungServiceTest { @Nested class TestGetChangedStatusCommandId { - private static final String CHANGE_STATUS_COMMAND_ID = UUID.randomUUID().toString(); private final Command zuruecknehmenCommand = CommandTestFactory.createBuilder() - .body(Map.of(DeleteLoeschAnforderung.CHANGE_STATUS_COMMAND_ID_FIELD, CHANGE_STATUS_COMMAND_ID)) + .body(LoeschAnforderungTestFactory.createDeleteLoeschAnforderungBodyMap()) .build(); - @BeforeEach - void mockCommandService() { - when(commandService.getById(anyString())).thenReturn(zuruecknehmenCommand); - } - - @Test - void shouldGetCommand() { - service.getChangeStatusCommandId(CommandTestFactory.ID); - - verify(commandService).getById(CommandTestFactory.ID); - } - @Test void shouldReturnChangeStatusCommandId() { - var commandId = service.getChangeStatusCommandId(CommandTestFactory.ID); + var commandId = service.getChangeStatusCommandId(zuruecknehmenCommand); - assertThat(commandId).isEqualTo(CHANGE_STATUS_COMMAND_ID); + assertThat(commandId).isEqualTo(LoeschAnforderungTestFactory.CHANGE_STATUS_COMMAND_ID); } } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungTestFactory.java b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungTestFactory.java index 2886316cf4d23c6b0a1c6c3f6cc15e8d18173da8..c30a66bd123b9a1399c7b430eb52cbcd2bbd9ade 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungTestFactory.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungTestFactory.java @@ -14,6 +14,9 @@ public class LoeschAnforderungTestFactory { public static final VorgangStatus PREV_STATUS = VorgangStatus.VERWORFEN; public static final String VORGANG_ID = VorgangHeaderTestFactory.ID; + static final String CHANGE_STATUS_COMMAND_ID = UUID.randomUUID().toString(); + static final String DELETE_VORGANG_ATTACHED_ITEM_ID = UUID.randomUUID().toString(); + public static LoeschAnforderung create() { return createBuilder().build(); } @@ -27,4 +30,9 @@ public class LoeschAnforderungTestFactory { LoeschAnforderung.REQUESTED_BY_FIELD, REQUESTED_BY.toString(), LoeschAnforderung.PREV_STATUS_FIELD, PREV_STATUS.name()); } + + public static Map<String, String> createDeleteLoeschAnforderungBodyMap() { + return Map.of(DeleteLoeschAnforderung.CHANGE_STATUS_COMMAND_ID_FIELD, CHANGE_STATUS_COMMAND_ID, + DeleteLoeschAnforderung.DELETE_ATTACHED_ITEM_COMMAND_ID_FIELD, DELETE_VORGANG_ATTACHED_ITEM_ID); + } } diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungVorgangProzessorTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungVorgangProzessorTest.java index 0c6110ded26665e77a05446d437e4c06c4c21373..00c3a2c225855b6d71149b1bfcc76a95818b795d 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungVorgangProzessorTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/loeschanforderung/LoeschAnforderungVorgangProzessorTest.java @@ -6,17 +6,12 @@ import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import java.util.Optional; -import java.util.stream.Stream; 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.api.extension.ExtensionContext; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.ArgumentsProvider; -import org.junit.jupiter.params.provider.ArgumentsSource; import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.EnumSource.Mode; import org.mockito.InjectMocks; @@ -24,13 +19,12 @@ import org.mockito.Mock; import org.mockito.Spy; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; -import org.springframework.web.util.UriTemplate; import de.ozgcloud.alfa.common.UserProfileUrlProvider; import de.ozgcloud.alfa.common.attacheditem.VorgangAttachedItemTestFactory; -import de.ozgcloud.alfa.common.command.CommandTestFactory; import de.ozgcloud.alfa.common.user.CurrentUserService; import de.ozgcloud.alfa.common.user.UserRole; +import de.ozgcloud.alfa.loeschanforderung.LoeschAnforderungController.LoeschAnforderungByVorgangController; import de.ozgcloud.alfa.vorgang.Vorgang; import de.ozgcloud.alfa.vorgang.Vorgang.VorgangStatus; import de.ozgcloud.alfa.vorgang.VorgangHeaderTestFactory; @@ -47,29 +41,22 @@ class LoeschAnforderungVorgangProzessorTest { @Mock private LoeschAnforderungService loeschAnforderungService; + @DisplayName("Prozess") @Nested class TestProcess { - private static final UriTemplate LOESCHEN_ANFORDERN_EXPECTED_LINK_URI_TEMPLATE = new UriTemplate( - LoeschAnforderungByVorgangController.CREATE_LOESCHANFORDERUNG_PATH); - private static final UriTemplate LOESCH_ANFORDERUNG_EXPECTED_LINK_URI_TEMPLATE = new UriTemplate( - LoeschAnforderungController.LOESCHANFORDERUNG_PATH); - - @DisplayName("Test add links") + @DisplayName("add links") @Nested class TestLinks { @BeforeEach - void mockVorgangAttachedItem() { + void mock() { + initUserProfileUrlProvider(new UserProfileUrlProvider()); + when(loeschAnforderungService.findLoeschAnforderung(VorgangHeaderTestFactory.ID)).thenReturn( Optional.of(VorgangAttachedItemTestFactory.create())); } - @BeforeEach - void mockUserProfileUrlProvider() { - initUserProfileUrlProvider(new UserProfileUrlProvider()); - } - @Test void shouldFindLoeschAnforderung() { prozessor.process(EntityModel.of(VorgangHeaderTestFactory.create())); @@ -85,9 +72,8 @@ class LoeschAnforderungVorgangProzessorTest { assertThat(model.getLink(LoeschAnforderungVorgangProzessor.REL_LOESCHEN_ANFORDERN)).isPresent() .map(Link::getHref) - .hasValue( - LOESCHEN_ANFORDERN_EXPECTED_LINK_URI_TEMPLATE.expand(VorgangHeaderTestFactory.ID, CommandTestFactory.RELATION_VERSION) - .toString()); + .hasValue(LoeschAnforderungByVorgangController.BASE_PATH.replace("{vorgangId}", VorgangHeaderTestFactory.ID) + .replace("{vorgangVersion}", String.valueOf(VorgangHeaderTestFactory.VERSION))); } @Test @@ -107,7 +93,7 @@ class LoeschAnforderungVorgangProzessorTest { var link = model.getLink(LoeschAnforderungVorgangProzessor.REL_LOESCH_ANFORDERUNG); assertThat(link).isPresent().map(Link::getHref) - .hasValue(LOESCH_ANFORDERUNG_EXPECTED_LINK_URI_TEMPLATE.expand(VorgangAttachedItemTestFactory.ID).toString()); + .hasValue(LoeschAnforderungController.BASE_PATH + "/" + VorgangAttachedItemTestFactory.ID); } @Test @@ -122,40 +108,64 @@ class LoeschAnforderungVorgangProzessorTest { } } + @DisplayName("Is loeschen anfordern allowed") @Nested class TestIsLoeschenAnfordernAllowed { - @ParameterizedTest - @ArgumentsSource(AllowedToLoeschenAnfordern.class) - void shouldReturnTrue(VorgangStatus vorgangStatus, String userRole) { - var vorgang = VorgangHeaderTestFactory.createBuilder().status(vorgangStatus).build(); - // TODO lenient ausbauen - lenient().when(currentUserService.hasRole(userRole)).thenReturn(true); + @DisplayName("on matching status") + @Nested + class TestOnMatchingStatus { - var isAllowed = prozessor.isLoeschenAnfordernAllowed(vorgang); + @DisplayName("with VERWALTUNG_USER role") + @Nested + class TestWithVerwaltungUserRole { + + @BeforeEach + void mock() { + when(currentUserService.hasRole(UserRole.VERWALTUNG_USER)).thenReturn(true); + } + + @ParameterizedTest + @EnumSource(names = { "VERWORFEN", "ABGESCHLOSSEN" }) + void shouldReturnTrue(VorgangStatus vorgangStatus) { + var vorgang = VorgangHeaderTestFactory.createBuilder().status(vorgangStatus).build(); - assertThat(isAllowed).isTrue(); + var isAllowed = prozessor.isLoeschenAnfordernAllowed(vorgang); + + assertThat(isAllowed).isTrue(); + } + } + + @DisplayName("with EINHEITLICHER_ANSPRECHPARTNER role") + @Nested + class TestWithEinheitlicherAnsprechpartnerRole { + + @BeforeEach + void mock() { + when(currentUserService.hasRole(UserRole.VERWALTUNG_USER)).thenReturn(false); + when(currentUserService.hasRole(UserRole.EINHEITLICHER_ANSPRECHPARTNER)).thenReturn(true); + } + + @ParameterizedTest + @EnumSource(names = { "VERWORFEN", "ABGESCHLOSSEN" }) + void shouldReturnTrue(VorgangStatus vorgangStatus) { + var vorgang = VorgangHeaderTestFactory.createBuilder().status(vorgangStatus).build(); + + var isAllowed = prozessor.isLoeschenAnfordernAllowed(vorgang); + + assertThat(isAllowed).isTrue(); + } + } } @ParameterizedTest @EnumSource(mode = Mode.EXCLUDE, names = { "VERWORFEN", "ABGESCHLOSSEN" }) - void shouldReturnFalseForVorgangStatus(VorgangStatus vorgangStatus) { + void shouldReturnFalseForNonMatchingVorgangStatus(VorgangStatus vorgangStatus) { var vorgang = VorgangHeaderTestFactory.createBuilder().status(vorgangStatus).build(); var isAllowed = prozessor.isLoeschenAnfordernAllowed(vorgang); assertThat(isAllowed).isFalse(); } - - private static class AllowedToLoeschenAnfordern implements ArgumentsProvider { - - @Override - public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) { - return Stream.of(Arguments.of(VorgangStatus.VERWORFEN, UserRole.VERWALTUNG_USER), - Arguments.of(VorgangStatus.VERWORFEN, UserRole.EINHEITLICHER_ANSPRECHPARTNER), - Arguments.of(VorgangStatus.ABGESCHLOSSEN, UserRole.VERWALTUNG_USER), - Arguments.of(VorgangStatus.ABGESCHLOSSEN, UserRole.EINHEITLICHER_ANSPRECHPARTNER)); - } - } } } \ No newline at end of file diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java b/goofy-server/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java index 6340a94f5064bc8005750ac0e1f6c57dc23cd011..d914ccfe173f8a2ee6c0da25e8006821482154e5 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/vorgang/VorgangControllerITCase.java @@ -26,7 +26,6 @@ package de.ozgcloud.alfa.vorgang; import static org.mockito.ArgumentMatchers.*; import static org.mockito.Mockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import java.util.List; @@ -120,7 +119,7 @@ class VorgangControllerITCase { @Test void shouldReturnResult() throws Exception { - doRequest().andDo(print()).andExpect(jsonPath("$._embedded.vorgangHeaderList[0].nextFrist").value(WiedervorlageTestFactory.FRIST_STR)); + doRequest().andExpect(jsonPath("$._embedded.vorgangHeaderList[0].nextFrist").value(WiedervorlageTestFactory.FRIST_STR)); } @Test diff --git a/goofy-server/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessorTest.java b/goofy-server/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessorTest.java index 0dd913200fcfa781511553652aeb374007fb6c60..275e8d60146a9bcb1544578e79bf6ab44e80790d 100644 --- a/goofy-server/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessorTest.java +++ b/goofy-server/src/test/java/de/ozgcloud/alfa/vorgang/command/VorgangWithEingangCommandProzessorTest.java @@ -43,7 +43,6 @@ import org.mockito.Spy; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.Link; import org.springframework.hateoas.LinkRelation; -import org.springframework.security.test.context.support.WithMockUser; import de.ozgcloud.alfa.common.FeatureToggleProperties; import de.ozgcloud.alfa.common.UserProfileUrlProvider; @@ -218,7 +217,6 @@ class VorgangWithEingangCommandProzessorTest { } @DisplayName("should have link with user role " + UserRole.EINHEITLICHER_ANSPRECHPARTNER) - @WithMockUser(roles = UserRole.EINHEITLICHER_ANSPRECHPARTNER) void shouldExistsByRoleEA() { when(commandController.existsPendingCommands(any())).thenReturn(false); diff --git a/goofy-server/src/test/resources/jsonTemplates/command/createVorgangCommand.json.tmpl b/goofy-server/src/test/resources/jsonTemplates/command/createVorgangCommand.json.tmpl index deddf3fb6e23dd58606ad0c0bb0a7501449eb70b..fc927a2bb2ff911d26199aac44aa39dd658f9d47 100644 --- a/goofy-server/src/test/resources/jsonTemplates/command/createVorgangCommand.json.tmpl +++ b/goofy-server/src/test/resources/jsonTemplates/command/createVorgangCommand.json.tmpl @@ -1,5 +1,4 @@ { "order": "%s", "body": null - } \ No newline at end of file diff --git a/goofy-server/src/test/resources/jsonTemplates/command/statusPatch.json.tmpl b/goofy-server/src/test/resources/jsonTemplates/command/statusPatch.json.tmpl index 4b381d81beb8eb20d8c3691a95c45d83a909159f..3710fc4af4d0c0c1071cf32e0d83e678177809f3 100644 --- a/goofy-server/src/test/resources/jsonTemplates/command/statusPatch.json.tmpl +++ b/goofy-server/src/test/resources/jsonTemplates/command/statusPatch.json.tmpl @@ -1,4 +1,3 @@ { - "status": "%s", - "order": "%s" + "status": "%s" } \ No newline at end of file diff --git a/pom.xml b/pom.xml index daf7f0d28b861930a9e5afb4d8574033de1c76ac..ce66cec71a872af4f38a791200ef99bfc761180e 100644 --- a/pom.xml +++ b/pom.xml @@ -41,9 +41,9 @@ </parent> <modules> - <module>goofy-client</module> + <module>goofy-client</module> <module>goofy-server</module> - <module>alfa-xdomea</module> + <module>alfa-xdomea</module> </modules> <properties>