From c063145daa11f8b9181c29b451c30a1ade8a8c9d Mon Sep 17 00:00:00 2001 From: Anne <158598611+anne-ds@users.noreply.github.com> Date: Tue, 26 Nov 2024 10:24:23 +0100 Subject: [PATCH] Refactor and add e2e-tests (#2392) RISDEV-5234 * Move data from CoreData to ManagementData * Add e2e for scheduled publication * Add scheduling searches to query test --------- Co-authored-by: Kim Kern --- .../DocumentationUnitTransformer.java | 21 +- .../ris/caselaw/domain/CoreData.java | 4 - .../ris/caselaw/domain/DocumentationUnit.java | 2 +- .../ris/caselaw/domain/ManagementData.java | 13 + .../DocumentationUnitTransformerTest.java | 71 ++++- frontend/src/components/DocumentUnitList.vue | 12 +- .../HandoverDocumentationUnitView.vue | 2 +- .../ScheduledPublishingDateTime.vue | 31 +- .../preview/DocumentUnitPreview.vue | 2 +- .../texts/DocumentUnitAdditionalTexts.vue | 6 +- .../texts/DocumentUnitLongTexts.vue | 8 +- .../texts/DocumentUnitShortTexts.vue | 8 +- frontend/src/domain/documentUnit.ts | 17 +- .../documentUnit/documentUnitList.spec.ts | 2 +- .../documentUnit/documentUnitSearch.spec.ts | 16 +- .../test/components/handoverDocument.spec.ts | 5 +- .../scheduledpublishingDateTime.spec.ts | 10 +- .../docunit-creation-from-evaluation.spec.ts | 20 +- frontend/test/e2e/caselaw/e2e-utils.ts | 14 +- .../handover/scheduled-publication.spec.ts | 268 ++++++++++++++++++ .../test/queries/document_unit_search.spec.ts | 18 ++ 21 files changed, 473 insertions(+), 77 deletions(-) create mode 100644 backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/ManagementData.java create mode 100644 frontend/test/e2e/caselaw/handover/scheduled-publication.spec.ts diff --git a/backend/src/main/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/DocumentationUnitTransformer.java b/backend/src/main/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/DocumentationUnitTransformer.java index 668a8fa83..f7feb90d5 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/DocumentationUnitTransformer.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/DocumentationUnitTransformer.java @@ -26,6 +26,7 @@ import de.bund.digitalservice.ris.caselaw.domain.EnsuingDecision; import de.bund.digitalservice.ris.caselaw.domain.LegalEffect; import de.bund.digitalservice.ris.caselaw.domain.LongTexts; +import de.bund.digitalservice.ris.caselaw.domain.ManagementData; import de.bund.digitalservice.ris.caselaw.domain.NormReference; import de.bund.digitalservice.ris.caselaw.domain.PreviousDecision; import de.bund.digitalservice.ris.caselaw.domain.ShortTexts; @@ -83,7 +84,6 @@ public static DocumentationUnitDTO transformToDTO( .ecli(StringUtils.normalizeSpace(coreData.ecli())) .judicialBody(StringUtils.normalizeSpace(coreData.appraisalBody())) .decisionDate(coreData.decisionDate()) - .scheduledPublicationDateTime(coreData.scheduledPublicationDateTime()) .documentType( coreData.documentType() != null ? DocumentTypeTransformer.transformToDTO(coreData.documentType()) @@ -145,6 +145,12 @@ public static DocumentationUnitDTO transformToDTO( .outline(null); } + if (updatedDomainObject.managementData() != null) { + var managementData = updatedDomainObject.managementData(); + + builder.scheduledPublicationDateTime(managementData.scheduledPublicationDateTime()); + } + addReferences(updatedDomainObject, builder); return builder.build(); @@ -582,8 +588,6 @@ public static DocumentationUnit transformToDomain(DocumentationUnitDTO documenta : documentationUnitDTO.getRegions().get(0).getCode()) .ecli(documentationUnitDTO.getEcli()) .decisionDate(documentationUnitDTO.getDecisionDate()) - .lastPublicationDateTime(documentationUnitDTO.getLastPublicationDateTime()) - .scheduledPublicationDateTime(documentationUnitDTO.getScheduledPublicationDateTime()) .appraisalBody(documentationUnitDTO.getJudicialBody()) .legalEffect(legalEffect == null ? null : legalEffect.getLabel()); @@ -711,6 +715,13 @@ public static DocumentationUnit transformToDomain(DocumentationUnitDTO documenta documentationUnitDTO.getOtherLongText(), documentationUnitDTO.getDissentingOpinion()); + ManagementData managementData = + ManagementData.builder() + .lastPublicationDateTime(documentationUnitDTO.getLastPublicationDateTime()) + .scheduledPublicationDateTime(documentationUnitDTO.getScheduledPublicationDateTime()) + .borderNumbers(borderNumbers) + .build(); + addOriginalFileDocuments(documentationUnitDTO, builder); addPreviousDecisionsToDomain(documentationUnitDTO, builder); addEnsuingDecisionsToDomain(documentationUnitDTO, builder); @@ -721,8 +732,8 @@ public static DocumentationUnit transformToDomain(DocumentationUnitDTO documenta .coreData(coreData) .shortTexts(shortTexts) .longTexts(longTexts) - .borderNumbers(borderNumbers) - .contentRelatedIndexing(contentRelatedIndexing); + .contentRelatedIndexing(contentRelatedIndexing) + .managementData(managementData); addStatusToDomain(documentationUnitDTO, builder); addReferencesToDomain(documentationUnitDTO, builder); diff --git a/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/CoreData.java b/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/CoreData.java index 3220c2c90..acff025ed 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/CoreData.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/CoreData.java @@ -2,10 +2,8 @@ import de.bund.digitalservice.ris.caselaw.domain.court.Court; import de.bund.digitalservice.ris.caselaw.domain.lookuptable.documenttype.DocumentType; -import jakarta.validation.constraints.Future; import jakarta.validation.constraints.PastOrPresent; import java.time.LocalDate; -import java.time.LocalDateTime; import java.time.Year; import java.util.List; import lombok.Builder; @@ -24,8 +22,6 @@ public record CoreData( @UniqueElements List deviatingEclis, String appraisalBody, @PastOrPresent LocalDate decisionDate, - @PastOrPresent LocalDateTime lastPublicationDateTime, - @Future LocalDateTime scheduledPublicationDateTime, @UniqueElements List deviatingDecisionDates, String legalEffect, List inputTypes, diff --git a/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/DocumentationUnit.java b/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/DocumentationUnit.java index 2a1426647..3cdc365d9 100644 --- a/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/DocumentationUnit.java +++ b/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/DocumentationUnit.java @@ -38,7 +38,7 @@ public record DocumentationUnit( List ensuingDecisions, ShortTexts shortTexts, LongTexts longTexts, - List borderNumbers, + @Valid ManagementData managementData, Status status, String note, ContentRelatedIndexing contentRelatedIndexing, diff --git a/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/ManagementData.java b/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/ManagementData.java new file mode 100644 index 000000000..7c2689257 --- /dev/null +++ b/backend/src/main/java/de/bund/digitalservice/ris/caselaw/domain/ManagementData.java @@ -0,0 +1,13 @@ +package de.bund.digitalservice.ris.caselaw.domain; + +import jakarta.validation.constraints.Future; +import jakarta.validation.constraints.PastOrPresent; +import java.time.LocalDateTime; +import java.util.List; +import lombok.Builder; + +@Builder(toBuilder = true) +public record ManagementData( + @PastOrPresent LocalDateTime lastPublicationDateTime, + @Future LocalDateTime scheduledPublicationDateTime, + List borderNumbers) {} diff --git a/backend/src/test/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/DocumentationUnitTransformerTest.java b/backend/src/test/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/DocumentationUnitTransformerTest.java index 59027cc55..6ef4e79b4 100644 --- a/backend/src/test/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/DocumentationUnitTransformerTest.java +++ b/backend/src/test/java/de/bund/digitalservice/ris/caselaw/adapter/transformer/DocumentationUnitTransformerTest.java @@ -39,6 +39,7 @@ import de.bund.digitalservice.ris.caselaw.domain.EnsuingDecision; import de.bund.digitalservice.ris.caselaw.domain.LegalForce; import de.bund.digitalservice.ris.caselaw.domain.LongTexts; +import de.bund.digitalservice.ris.caselaw.domain.ManagementData; import de.bund.digitalservice.ris.caselaw.domain.NormReference; import de.bund.digitalservice.ris.caselaw.domain.PreviousDecision; import de.bund.digitalservice.ris.caselaw.domain.PublicationStatus; @@ -50,6 +51,7 @@ import de.bund.digitalservice.ris.caselaw.domain.lookuptable.ParticipatingJudge; import de.bund.digitalservice.ris.caselaw.domain.lookuptable.Region; import java.time.Instant; +import java.time.LocalDateTime; import java.time.Year; import java.util.Collections; import java.util.List; @@ -897,7 +899,59 @@ void testTransformToDomain_textWithMultipleBorderNumberElements_shouldAddAllBord DocumentationUnit documentationUnit = DocumentationUnitTransformer.transformToDomain(documentationUnitDTO); - assertThat(documentationUnit.borderNumbers()).hasSize(2).containsExactly("1", "2"); + assertThat(documentationUnit.managementData().borderNumbers()) + .hasSize(2) + .containsExactly("1", "2"); + } + + @Test + void testTransformScheduledPublicationDate_withDate_shouldAddScheduledPublicationDate() { + DocumentationUnitDTO documentationUnitDTO = + generateSimpleDTOBuilder() + .scheduledPublicationDateTime(LocalDateTime.parse("2022-01-23T18:25:14")) + .build(); + + DocumentationUnit documentationUnit = + DocumentationUnitTransformer.transformToDomain(documentationUnitDTO); + + assertThat(documentationUnit.managementData().scheduledPublicationDateTime()) + .isEqualTo("2022-01-23T18:25:14"); + } + + @Test + void testTransformScheduledPublicationDate_withoutDate_shouldNotAddScheduledPublicationDate() { + DocumentationUnitDTO documentationUnitDTO = + generateSimpleDTOBuilder().scheduledPublicationDateTime(null).build(); + + DocumentationUnit documentationUnit = + DocumentationUnitTransformer.transformToDomain(documentationUnitDTO); + + assertThat(documentationUnit.managementData().scheduledPublicationDateTime()).isNull(); + } + + @Test + void testTransformLastPublicationDate_withDate_shouldAddLastPublicationDate() { + DocumentationUnitDTO documentationUnitDTO = + generateSimpleDTOBuilder() + .lastPublicationDateTime(LocalDateTime.parse("2022-01-23T18:25:14")) + .build(); + + DocumentationUnit documentationUnit = + DocumentationUnitTransformer.transformToDomain(documentationUnitDTO); + + assertThat(documentationUnit.managementData().lastPublicationDateTime()) + .isEqualTo("2022-01-23T18:25:14"); + } + + @Test + void testTransformLastPublicationDate_withoutDate_shouldNotAddLastPublicationDate() { + DocumentationUnitDTO documentationUnitDTO = + generateSimpleDTOBuilder().lastPublicationDateTime(null).build(); + + DocumentationUnit documentationUnit = + DocumentationUnitTransformer.transformToDomain(documentationUnitDTO); + + assertThat(documentationUnit.managementData().lastPublicationDateTime()).isNull(); } @Test @@ -917,7 +971,9 @@ void testTransformToDomain_multipleTextsWithBorderNumberElements_shouldAddAllBor DocumentationUnit documentationUnit = DocumentationUnitTransformer.transformToDomain(documentationUnitDTO); - assertThat(documentationUnit.borderNumbers()).hasSize(4).containsExactly("1", "2", "3", "4"); + assertThat(documentationUnit.managementData().borderNumbers()) + .hasSize(4) + .containsExactly("1", "2", "3", "4"); } @Test @@ -928,7 +984,7 @@ void testTransformToDomain_textWithoutBorderNumberElements_shouldNotAddBorderNum DocumentationUnit documentationUnit = DocumentationUnitTransformer.transformToDomain(documentationUnitDTO); - assertThat(documentationUnit.borderNumbers()).isEmpty(); + assertThat(documentationUnit.managementData().borderNumbers()).isEmpty(); } @Test @@ -943,7 +999,7 @@ void testTransformToDomain_textWithoutBorderNumberElements_shouldNotAddBorderNum DocumentationUnit documentationUnit = DocumentationUnitTransformer.transformToDomain(documentationUnitDTO); - assertThat(documentationUnit.borderNumbers()).hasSize(1).containsExactly("2"); + assertThat(documentationUnit.managementData().borderNumbers()).hasSize(1).containsExactly("2"); } @Test @@ -1276,7 +1332,12 @@ private DocumentationUnit.DocumentationUnitBuilder generateSimpleDocumentationUn .ensuingDecisions(Collections.emptyList()) .shortTexts(ShortTexts.builder().build()) .longTexts(LongTexts.builder().build()) - .borderNumbers(Collections.emptyList()) + .managementData( + ManagementData.builder() + .scheduledPublicationDateTime(null) + .lastPublicationDateTime(null) + .borderNumbers(Collections.emptyList()) + .build()) .attachments(Collections.emptyList()) .contentRelatedIndexing( ContentRelatedIndexing.builder() diff --git a/frontend/src/components/DocumentUnitList.vue b/frontend/src/components/DocumentUnitList.vue index 8de166d4f..5619bbeca 100644 --- a/frontend/src/components/DocumentUnitList.vue +++ b/frontend/src/components/DocumentUnitList.vue @@ -147,7 +147,10 @@ function onDelete() { @close-modal="toggleModal" @confirm-action="onDelete" /> - + Dokumentnummer Gerichtstyp @@ -174,7 +177,7 @@ function onDelete() { @@ -291,7 +294,10 @@ function onDelete() { /> - - + {{ publicationDate(listEntry) }} diff --git a/frontend/src/components/HandoverDocumentationUnitView.vue b/frontend/src/components/HandoverDocumentationUnitView.vue index 6714b4400..6b95efdbe 100644 --- a/frontend/src/components/HandoverDocumentationUnitView.vue +++ b/frontend/src/components/HandoverDocumentationUnitView.vue @@ -304,7 +304,7 @@ const isDecisionReasonsInvalid = computed( const schedulingFeatureToggle = useFeatureToggle("neuris.scheduledPublishing") const isScheduled = computed( - () => !!store.documentUnit!.coreData.scheduledPublicationDateTime, + () => !!store.documentUnit!.managementData.scheduledPublicationDateTime, ) const isPublishable = computed( diff --git a/frontend/src/components/ScheduledPublishingDateTime.vue b/frontend/src/components/ScheduledPublishingDateTime.vue index c41a84428..9106b1d60 100644 --- a/frontend/src/components/ScheduledPublishingDateTime.vue +++ b/frontend/src/components/ScheduledPublishingDateTime.vue @@ -22,21 +22,30 @@ dayjs.extend(customParseFormat) const store = useDocumentUnitStore() +const storedScheduledPublicationDateTime = computed({ + get: () => store.documentUnit!.managementData.scheduledPublicationDateTime, + set: (newDate?: string) => + (store.documentUnit!.managementData.scheduledPublicationDateTime = newDate), +}) + +// initialize local values with stored date-time +/* eslint-disable vue/no-ref-object-destructure */ const scheduledPublishingDate = ref( - store.documentUnit!.coreData.scheduledPublicationDateTime && + storedScheduledPublicationDateTime.value && dayjs - .utc(store.documentUnit!.coreData.scheduledPublicationDateTime) + .utc(storedScheduledPublicationDateTime.value) .tz("Europe/Berlin") .format("YYYY-MM-DD"), ) const scheduledPublishingTime = ref( - (store.documentUnit!.coreData.scheduledPublicationDateTime && + (storedScheduledPublicationDateTime.value && dayjs - .utc(store.documentUnit!.coreData.scheduledPublicationDateTime) + .utc(storedScheduledPublicationDateTime.value) .tz("Europe/Berlin") .format("HH:mm")) || "05:00", ) +/* eslint-enable vue/no-ref-object-destructure */ const scheduledDateTimeInput = computed(() => dayjs.tz( @@ -46,7 +55,7 @@ const scheduledDateTimeInput = computed(() => ) const isScheduled = computed( - () => !!store.documentUnit!.coreData.scheduledPublicationDateTime, + () => !!storedScheduledPublicationDateTime.value, ) const isDateInFuture = computed( @@ -82,17 +91,17 @@ const saveScheduling = async () => { return } - store.documentUnit!.coreData.scheduledPublicationDateTime = + storedScheduledPublicationDateTime.value = scheduledDateTimeInput.value.toISOString() const { error } = await store.updateDocumentUnit() if (error) { - store.documentUnit!.coreData.scheduledPublicationDateTime = undefined + storedScheduledPublicationDateTime.value = undefined docUnitSaveError.value = error } else { scheduledPublishingDate.value = dayjs( - store.documentUnit!.coreData.scheduledPublicationDateTime, + storedScheduledPublicationDateTime.value, ) .tz("Europe/Berlin") .format("YYYY-MM-DD") @@ -101,13 +110,13 @@ const saveScheduling = async () => { const removeScheduling = async () => { docUnitSaveError.value = null - const previousDate = store.documentUnit!.coreData.scheduledPublicationDateTime - store.documentUnit!.coreData.scheduledPublicationDateTime = undefined + const previousDate = storedScheduledPublicationDateTime.value + storedScheduledPublicationDateTime.value = undefined const { error } = await store.updateDocumentUnit() if (error) { - store.documentUnit!.coreData.scheduledPublicationDateTime = previousDate + storedScheduledPublicationDateTime.value = previousDate docUnitSaveError.value = error } else { scheduledPublishingDate.value = undefined diff --git a/frontend/src/components/preview/DocumentUnitPreview.vue b/frontend/src/components/preview/DocumentUnitPreview.vue index 2fc6c23f0..4da066327 100644 --- a/frontend/src/components/preview/DocumentUnitPreview.vue +++ b/frontend/src/components/preview/DocumentUnitPreview.vue @@ -48,7 +48,7 @@ provide(previewLayoutInjectionKey, props.layout || "wide") diff --git a/frontend/src/components/texts/DocumentUnitAdditionalTexts.vue b/frontend/src/components/texts/DocumentUnitAdditionalTexts.vue index 68ee4bcc7..fe534620b 100644 --- a/frontend/src/components/texts/DocumentUnitAdditionalTexts.vue +++ b/frontend/src/components/texts/DocumentUnitAdditionalTexts.vue @@ -17,7 +17,7 @@ const otherLongText = computed({ store.documentUnit?.longTexts.otherLongText ? useValidBorderNumberLinks( store.documentUnit?.longTexts.otherLongText, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { @@ -31,7 +31,7 @@ const dissentingOpinion = computed({ store.documentUnit?.longTexts.dissentingOpinion ? useValidBorderNumberLinks( store.documentUnit?.longTexts.dissentingOpinion, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { @@ -45,7 +45,7 @@ const outline = computed({ store.documentUnit?.longTexts.outline ? useValidBorderNumberLinks( store.documentUnit?.longTexts.outline, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { diff --git a/frontend/src/components/texts/DocumentUnitLongTexts.vue b/frontend/src/components/texts/DocumentUnitLongTexts.vue index d2c127882..7e37b3872 100644 --- a/frontend/src/components/texts/DocumentUnitLongTexts.vue +++ b/frontend/src/components/texts/DocumentUnitLongTexts.vue @@ -13,7 +13,7 @@ const tenor = computed({ store.documentUnit?.longTexts.tenor ? useValidBorderNumberLinks( store.documentUnit?.longTexts.tenor, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { @@ -27,7 +27,7 @@ const reasons = computed({ store.documentUnit?.longTexts.reasons ? useValidBorderNumberLinks( store.documentUnit?.longTexts.reasons, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { @@ -41,7 +41,7 @@ const caseFacts = computed({ store.documentUnit?.longTexts.caseFacts ? useValidBorderNumberLinks( store.documentUnit?.longTexts.caseFacts, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { @@ -55,7 +55,7 @@ const decisionReasons = computed({ store.documentUnit?.longTexts.decisionReasons ? useValidBorderNumberLinks( store.documentUnit?.longTexts.decisionReasons, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { diff --git a/frontend/src/components/texts/DocumentUnitShortTexts.vue b/frontend/src/components/texts/DocumentUnitShortTexts.vue index 3f5bceefe..0226bf473 100644 --- a/frontend/src/components/texts/DocumentUnitShortTexts.vue +++ b/frontend/src/components/texts/DocumentUnitShortTexts.vue @@ -22,7 +22,7 @@ const headline = computed({ store.documentUnit?.shortTexts.headline ? useValidBorderNumberLinks( store.documentUnit.shortTexts.headline, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { @@ -36,7 +36,7 @@ const guidingPrinciple = computed({ store.documentUnit?.shortTexts.guidingPrinciple ? useValidBorderNumberLinks( store.documentUnit?.shortTexts.guidingPrinciple, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { @@ -50,7 +50,7 @@ const headnote = computed({ store.documentUnit?.shortTexts.headnote ? useValidBorderNumberLinks( store.documentUnit?.shortTexts.headnote, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { @@ -64,7 +64,7 @@ const otherHeadnote = computed({ store.documentUnit?.shortTexts.otherHeadnote ? useValidBorderNumberLinks( store.documentUnit?.shortTexts.otherHeadnote, - store.documentUnit.borderNumbers, + store.documentUnit.managementData.borderNumbers, ) : undefined, set: (newValue) => { diff --git a/frontend/src/domain/documentUnit.ts b/frontend/src/domain/documentUnit.ts index 15de547f7..fa38b9e32 100644 --- a/frontend/src/domain/documentUnit.ts +++ b/frontend/src/domain/documentUnit.ts @@ -20,7 +20,6 @@ export type CoreData = { documentType?: DocumentType procedure?: Procedure previousProcedures?: string[] - scheduledPublicationDateTime?: string ecli?: string deviatingEclis?: string[] appraisalBody?: string @@ -110,6 +109,11 @@ export const longTextLabels: { outline: "Gliederung", } +export type ManagementData = { + scheduledPublicationDateTime?: string + borderNumbers: string[] +} + export type DocumentationUnitParameters = { documentationOffice?: DocumentationOffice documentType?: DocumentType @@ -132,10 +136,10 @@ export default class DocumentUnit { public previousDecisions?: PreviousDecision[] public ensuingDecisions?: EnsuingDecision[] public contentRelatedIndexing: ContentRelatedIndexing = {} - public borderNumbers: string[] = [] public note: string = "" public references?: Reference[] public isEditable: boolean = false + public managementData: ManagementData = { borderNumbers: [] } static readonly requiredFields = [ "fileNumbers", @@ -169,6 +173,15 @@ export default class DocumentUnit { delete data.longTexts[longTextsField] } + let managementDataField: keyof ManagementData + for (managementDataField in data.managementData) { + if ( + data.managementData && + data.managementData[managementDataField] === null + ) + delete data.managementData[managementDataField] + } + if (data.longTexts?.participatingJudges) data.longTexts.participatingJudges = data.longTexts.participatingJudges.map( diff --git a/frontend/test/components/documentUnit/documentUnitList.spec.ts b/frontend/test/components/documentUnit/documentUnitList.spec.ts index 6900a21e1..79e562069 100644 --- a/frontend/test/components/documentUnit/documentUnitList.spec.ts +++ b/frontend/test/components/documentUnit/documentUnitList.spec.ts @@ -174,7 +174,7 @@ describe("documentUnit list", () => { screen.getByRole("link", { name: "Dokumentationseinheit bearbeiten" }), ).toBeInTheDocument() - expect(screen.getAllByTestId("listEntry").length).toBe(3) + expect(screen.getAllByRole("row").length).toBe(3) //Spruchkörper visible expect(screen.getByText("cba")).toBeVisible() diff --git a/frontend/test/components/documentUnit/documentUnitSearch.spec.ts b/frontend/test/components/documentUnit/documentUnitSearch.spec.ts index 6abf80069..3738a6e0a 100644 --- a/frontend/test/components/documentUnit/documentUnitSearch.spec.ts +++ b/frontend/test/components/documentUnit/documentUnitSearch.spec.ts @@ -73,7 +73,7 @@ describe("Documentunit Search", () => { "Starten Sie die Suche oder erstellen Sie eine neue Dokumentationseinheit.", ), ).toBeVisible() - expect(screen.queryAllByTestId("listEntry").length).toBe(0) + expect(screen.queryAllByRole("row").length).toBe(0) }) test("External user cannot create new doc unit", async () => { @@ -83,7 +83,7 @@ describe("Documentunit Search", () => { screen.queryByLabelText("Neue Dokumentationseinheit erstellen"), ).not.toBeInTheDocument() expect(screen.getByText("Starten Sie die Suche.")).toBeVisible() - expect(screen.queryAllByTestId("listEntry").length).toBe(0) + expect(screen.queryAllByRole("row").length).toBe(0) }) test("search for scheduled publicationDate should display one result", async () => { @@ -123,7 +123,7 @@ describe("Documentunit Search", () => { screen.getByLabelText("Nach Dokumentationseinheiten suchen"), ) expect(screen.getByRole("cell", { name: "jDV Übergabe" })).toBeVisible() - expect(screen.queryAllByTestId("listEntry").length).toBe(1) + expect(screen.queryAllByRole("row").length).toBe(1) }) test("search with scheduled only should display one result", async () => { @@ -159,7 +159,7 @@ describe("Documentunit Search", () => { screen.getByLabelText("Nach Dokumentationseinheiten suchen"), ) expect(screen.getByRole("cell", { name: "jDV Übergabe" })).toBeVisible() - expect(screen.queryAllByTestId("listEntry").length).toBe(1) + expect(screen.queryAllByRole("row").length).toBe(1) }) test("search for publicationDate should display one result", async () => { @@ -198,7 +198,7 @@ describe("Documentunit Search", () => { screen.getByLabelText("Nach Dokumentationseinheiten suchen"), ) expect(screen.getByRole("cell", { name: "jDV Übergabe" })).toBeVisible() - expect(screen.queryAllByTestId("listEntry").length).toBe(1) + expect(screen.queryAllByRole("row").length).toBe(1) }) test("click on 'Ergebnisse anzeigen' with search input renders results", async () => { @@ -245,7 +245,7 @@ describe("Documentunit Search", () => { screen.getByLabelText("Nach Dokumentationseinheiten suchen"), ) - expect(screen.getAllByTestId("listEntry").length).toBe(1) + expect(screen.getAllByRole("row").length).toBe(1) expect(screen.getAllByText(/documentNumber/).length).toBe(1) }) @@ -279,7 +279,7 @@ describe("Documentunit Search", () => { await new Promise((resolve) => setTimeout(resolve, 100)) - expect(screen.queryAllByTestId("listEntry").length).toBe(0) + expect(screen.queryAllByRole("row").length).toBe(0) expect(screen.getByText("Übernehmen und fortfahren")).toBeVisible() }) @@ -314,7 +314,7 @@ describe("Documentunit Search", () => { await new Promise((resolve) => setTimeout(resolve, 100)) - expect(screen.queryAllByTestId("listEntry").length).toBe(0) + expect(screen.queryAllByRole("row").length).toBe(0) expect( screen.queryByText("Übernehmen und fortfahren"), diff --git a/frontend/test/components/handoverDocument.spec.ts b/frontend/test/components/handoverDocument.spec.ts index 8087cdbda..38e1c5f6b 100644 --- a/frontend/test/components/handoverDocument.spec.ts +++ b/frontend/test/components/handoverDocument.spec.ts @@ -461,9 +461,12 @@ describe("HandoverDocumentationUnitView:", () => { it("should not allow to publish when publication is scheduled", async () => { renderComponent({ documentUnit: new DocumentUnit("123", { + managementData: { + borderNumbers: [], + scheduledPublicationDateTime: "2050-01-01T04:00:00.000Z", + }, coreData: { fileNumbers: ["foo"], - scheduledPublicationDateTime: "2050-01-01T04:00:00.000Z", court: { type: "type", location: "location", label: "label" }, decisionDate: "2022-02-01", legalEffect: "legalEffect", diff --git a/frontend/test/components/scheduledpublishingDateTime.spec.ts b/frontend/test/components/scheduledpublishingDateTime.spec.ts index f3c0e7d24..ea363460f 100644 --- a/frontend/test/components/scheduledpublishingDateTime.spec.ts +++ b/frontend/test/components/scheduledpublishingDateTime.spec.ts @@ -16,7 +16,7 @@ function mockDocUnitStore({ } = {}) { const mockedSessionStore = useDocumentUnitStore() mockedSessionStore.documentUnit = new DocumentUnit("q834", { - coreData: { scheduledPublicationDateTime }, + managementData: { scheduledPublicationDateTime, borderNumbers: [] }, }) const response = errorTitle ? { error: { title: errorTitle } } : {} @@ -110,9 +110,9 @@ describe("ScheduledPublishingDateTime", () => { await fireEvent.click(screen.getByLabelText("Termin setzen")) - expect(store.documentUnit?.coreData.scheduledPublicationDateTime).toEqual( - "2050-01-01T04:00:00.000Z", - ) + expect( + store.documentUnit?.managementData.scheduledPublicationDateTime, + ).toEqual("2050-01-01T04:00:00.000Z") expect(dateField).toHaveValue("01.01.2050") expect(screen.getByLabelText("Terminierte Uhrzeit")).toHaveValue("05:00") @@ -134,7 +134,7 @@ describe("ScheduledPublishingDateTime", () => { await fireEvent.click(screen.getByLabelText("Termin löschen")) expect( - store.documentUnit?.coreData.scheduledPublicationDateTime, + store.documentUnit?.managementData.scheduledPublicationDateTime, ).toBeUndefined() const dateField = screen.getByLabelText("Terminiertes Datum") diff --git a/frontend/test/e2e/caselaw/docunit-creation-from-evaluation.spec.ts b/frontend/test/e2e/caselaw/docunit-creation-from-evaluation.spec.ts index 04c4535cc..bb83cd198 100644 --- a/frontend/test/e2e/caselaw/docunit-creation-from-evaluation.spec.ts +++ b/frontend/test/e2e/caselaw/docunit-creation-from-evaluation.spec.ts @@ -383,7 +383,7 @@ test.describe( await newTab.getByLabel("Dokumentnummer Suche").fill(documentNumber) await newTab.getByLabel("Nach Dokumentationseinheiten suchen").click() - const listEntry = newTab.getByTestId("listEntry") + const listEntry = newTab.getByRole("row") await expect(listEntry).toHaveCount(1) await expect(listEntry).toContainText(documentNumber) @@ -412,7 +412,7 @@ test.describe( ).toBeHidden() await newTab.reload() - const listEntry = newTab.getByTestId("listEntry") + const listEntry = newTab.getByRole("row") await expect(listEntry).toHaveCount(0) }) }, @@ -533,7 +533,7 @@ test.describe( const select = newTab.locator(`select[id="status"]`) await select.selectOption("Fremdanlage") await newTab.getByLabel("Nach Dokumentationseinheiten suchen").click() - const listEntry = newTab.getByTestId("listEntry") + const listEntry = newTab.getByRole("row") await expect(listEntry).toHaveCount(0) }) @@ -549,7 +549,7 @@ test.describe( await pageWithBghUser .getByLabel("Nach Dokumentationseinheiten suchen") .click() - const listEntry = pageWithBghUser.getByTestId("listEntry") + const listEntry = pageWithBghUser.getByRole("row") await expect(listEntry).toHaveCount(1) await expect(listEntry).toContainText( `Fremdanlage aus MMG ${edition.prefix}12${edition.suffix} (DS)`, @@ -679,7 +679,7 @@ test.describe( await pageWithBghUser .getByLabel("Nach Dokumentationseinheiten suchen") .click() - const listEntry = pageWithBghUser.getByTestId("listEntry") + const listEntry = pageWithBghUser.getByRole("row") await expect(listEntry).toHaveCount(1) await expect( @@ -708,7 +708,7 @@ test.describe( await pageWithBghUser .getByLabel("Nach Dokumentationseinheiten suchen") .click() - const listEntry = pageWithBghUser.getByTestId("listEntry") + const listEntry = pageWithBghUser.getByRole("row") await expect(listEntry).toHaveCount(1) await expect(listEntry).toContainText( `Fremdanlage aus MMG ${edition.prefix}12${edition.suffix} (DS)`, @@ -746,7 +746,7 @@ test.describe( // await page // .getByLabel("Nach Dokumentationseinheiten suchen") // .click() - // const listEntry = pageWithBghUser.getByTestId("listEntry") + // const listEntry = pageWithBghUser.getByRole("row") // await expect(listEntry).toHaveCount(1) // await expect(listEntry).toContainText(`Unveröffentlicht`) @@ -767,7 +767,7 @@ test.describe( await pageWithBghUser .getByLabel("Nach Dokumentationseinheiten suchen") .click() - const listEntry = pageWithBghUser.getByTestId("listEntry") + const listEntry = pageWithBghUser.getByRole("row") await expect(listEntry).toHaveCount(1) await expect(listEntry).toContainText( `Fremdanlage aus MMG ${edition.prefix}12${edition.suffix} (DS)`, @@ -786,9 +786,7 @@ test.describe( await pageWithBghUser.locator('button:has-text("Löschen")').click() - await expect(pageWithBghUser.getByTestId("listEntry")).toHaveCount( - 0, - ) + await expect(pageWithBghUser.getByRole("row")).toHaveCount(0) await page.reload() await expect(page.getByText(documentNumber2)).toBeHidden() diff --git a/frontend/test/e2e/caselaw/e2e-utils.ts b/frontend/test/e2e/caselaw/e2e-utils.ts index 1f529ce51..bbba1ed8b 100644 --- a/frontend/test/e2e/caselaw/e2e-utils.ts +++ b/frontend/test/e2e/caselaw/e2e-utils.ts @@ -177,14 +177,14 @@ export const handoverDocumentationUnit = async ( page: Page, documentNumber: string, ) => { - await navigateToHandover(page, documentNumber) - await expect(page.getByText("XML Vorschau")).toBeVisible() - await page - .locator("[aria-label='Dokumentationseinheit an jDV übergeben']") - .click() - await expect(page.getByText("Email wurde versendet")).toBeVisible() + await test.step(`Übergebe Dokumentationseinheit ${documentNumber}`, async () => { + await navigateToHandover(page, documentNumber) + await expect(page.getByText("XML Vorschau")).toBeVisible() + await page.getByLabel("Dokumentationseinheit an jDV übergeben").click() + await expect(page.getByText("Email wurde versendet")).toBeVisible() - await expect(page.getByText("Xml Email Abgabe -")).toBeVisible() + await expect(page.getByText("Xml Email Abgabe -")).toBeVisible() + }) } export const uploadTestfile = async ( diff --git a/frontend/test/e2e/caselaw/handover/scheduled-publication.spec.ts b/frontend/test/e2e/caselaw/handover/scheduled-publication.spec.ts new file mode 100644 index 000000000..222ca52d0 --- /dev/null +++ b/frontend/test/e2e/caselaw/handover/scheduled-publication.spec.ts @@ -0,0 +1,268 @@ +import { expect, Page } from "@playwright/test" +import dayjs from "dayjs" +import { + handoverDocumentationUnit, + navigateToHandover, + navigateToSearch, +} from "~/e2e/caselaw/e2e-utils" +import { caselawTest as test } from "~/e2e/caselaw/fixtures" + +test.describe( + "Scheduled publication (Terminierte Abgabe)", + { + annotation: { + description: + "https://digitalservicebund.atlassian.net/browse/RISDEV-5234", + type: "epic", + }, + tag: ["@RISDEV-5234"], + }, + () => { + test( + "Terminierte Abgabe kann erstellt werden", + { + annotation: { + description: + "https://digitalservicebund.atlassian.net/browse/RISDEV-5419", + type: "story", + }, + tag: ["@RISDEV-5419"], + }, + async ({ page, prefilledDocumentUnit }) => { + await navigateToHandover(page, prefilledDocumentUnit.documentNumber) + + await test.step("Terminierte Abgabe kann befüllt werden", async () => { + // Datum will be enabled once XML preview is loaded + await expect(page.getByLabel("Terminiertes Datum")).toBeEditable() + await expect(page.getByLabel("Terminiertes Datum")).toBeEmpty() + await expect(page.getByLabel("Terminierte Uhrzeit")).toBeEditable() + await expect(page.getByLabel("Terminierte Uhrzeit")).toHaveValue( + "05:00", + ) + await expect(page.getByLabel("Termin setzen")).toBeDisabled() + }) + + await test.step("Terminierte Abgabe in der Vergangenheit ist nicht möglich", async () => { + await page.getByLabel("Terminiertes Datum").fill("01.01.2020") + await expect( + page.getByTestId("scheduledPublishingDate_errors"), + ).toHaveText("Der Terminierungszeitpunkt muss in der Zukunft liegen.") + await expect(page.getByLabel("Termin setzen")).toBeDisabled() + }) + + await test.step("Setze terminierte Abgabe in der Zukunft", async () => { + await page.getByLabel("Terminiertes Datum").fill("31.12.2080") + await page.getByLabel("Terminierte Uhrzeit").fill("13:14") + await expect( + page.getByTestId("scheduledPublishingDate_errors"), + ).toBeHidden() + await expect(page.getByLabel("Termin setzen")).toBeEnabled() + await page.getByLabel("Termin setzen").click() + + await expect(page.getByLabel("Terminiertes Datum")).not.toBeEditable() + await expect( + page.getByLabel("Terminierte Uhrzeit"), + ).not.toBeEditable() + await expect( + page.getByLabel("Dokumentationseinheit an jDV übergeben"), + ).toBeDisabled() + }) + + await test.step("Terminierte Abgabe hat korrekte Daten nach Reload", async () => { + await page.reload() + await expect(page.getByLabel("Terminiertes Datum")).toHaveValue( + "31.12.2080", + ) + await expect(page.getByLabel("Terminierte Uhrzeit")).toHaveValue( + "13:14", + ) + await expect( + page.getByTestId("scheduledPublishingDate_errors"), + ).toBeHidden() + }) + + await test.step("Lösche terminierte Abgabe", async () => { + await expect(page.getByLabel("Termin löschen")).toBeEnabled() + await page.getByLabel("Termin löschen").click() + await expect( + page.getByLabel("Dokumentationseinheit an jDV übergeben"), + ).toBeEnabled() + + await expect(page.getByLabel("Terminiertes Datum")).toBeEditable() + await expect(page.getByLabel("Terminiertes Datum")).toBeEmpty() + await expect(page.getByLabel("Terminierte Uhrzeit")).toBeEditable() + await expect(page.getByLabel("Terminierte Uhrzeit")).toHaveValue( + "05:00", + ) + }) + }, + ) + + test( + "Terminierte Abgabe ist nicht möglich, wenn Plausibilitätsprüfung fehlschlägt", + { + annotation: { + description: + "https://digitalservicebund.atlassian.net/browse/RISDEV-5419", + type: "story", + }, + tag: ["@RISDEV-5419"], + }, + async ({ page, documentNumber }) => { + await navigateToHandover(page, documentNumber) + + await test.step("Terminierte Abgabe ist nicht möglich", async () => { + await expect(page.getByLabel("Plausibilitätsprüfung")).toHaveText( + /Die folgenden Rubriken-Pflichtfelder sind nicht befüllt/, + ) + + await expect(page.getByLabel("Terminiertes Datum")).toBeDisabled() + await expect(page.getByLabel("Terminierte Uhrzeit")).toBeDisabled() + await expect(page.getByLabel("Termin setzen")).toBeDisabled() + }) + }, + ) + + test( + "Terminierte Dok-Einheiten können in Suche gefunden werden", + { + annotation: { + description: + "https://digitalservicebund.atlassian.net/browse/RISDEV-5419", + type: "story", + }, + tag: ["@RISDEV-5419"], + }, + async ({ page, prefilledDocumentUnit }) => { + await navigateToHandover(page, prefilledDocumentUnit.documentNumber) + + await test.step("Setze terminierte Abgabe in der Zukunft", async () => { + await page.getByLabel("Terminiertes Datum").fill("31.12.2080") + await page.getByLabel("Terminierte Uhrzeit").fill("13:14") + await page.getByLabel("Termin setzen").click() + }) + + await navigateToSearch(page) + + await test.step("Suchfilter für Terminierte Abgabe nur mit 'Nur meine Dokstelle' sichtbar", async () => { + await expect(page.getByLabel("Terminiert Filter")).toBeHidden() + await page.getByLabel("Nur meine Dokstelle Filter").check() + await expect(page.getByLabel("Terminiert Filter")).toBeVisible() + // jdv Übergabe column is not visible by default + await expect( + page.getByRole("cell", { name: "jDV Übergabe", exact: true }), + ).toBeHidden() + }) + + await test.step("Suche nach terminierten Dok-Einheiten zeigt neue Terminierung", async () => { + await page.getByLabel("Terminiert Filter").check() + await page.getByLabel("Nach Dokumentationseinheiten suchen").click() + const resultRow = page.getByTestId( + `listEntry_${prefilledDocumentUnit.documentNumber}`, + ) + // jDV Übergabe date column is visible when filter is active + await expect( + page.getByRole("cell", { name: "jDV Übergabe", exact: true }), + ).toBeVisible() + await expect(resultRow).toBeVisible() + await expect( + resultRow.getByLabel("Terminierte Übergabe am 31.12.2080 13:14"), + ).toBeVisible() + await expect(resultRow.getByTestId("publicationDate")).toHaveText( + "31.12.2080 13:14", + ) + }) + + await checkPublicationDateSorting(page) + }, + ) + + test( + "Abgegebene Dok-Einheiten können in Suche nach Abgabedatum gefiltert werden", + { + annotation: { + description: + "https://digitalservicebund.atlassian.net/browse/RISDEV-5419", + type: "story", + }, + tag: ["@RISDEV-5419"], + }, + async ({ page, prefilledDocumentUnit, secondPrefilledDocumentUnit }) => { + await handoverDocumentationUnit( + page, + prefilledDocumentUnit.documentNumber, + ) + await handoverDocumentationUnit( + page, + secondPrefilledDocumentUnit.documentNumber, + ) + + await navigateToSearch(page) + + await test.step("Suchfilter für Abgabedatum nur mit 'Nur meine Dokstelle' sichtbar", async () => { + await expect(page.getByLabel("jDV Übergabedatum Suche")).toBeHidden() + await page.getByLabel("Nur meine Dokstelle Filter").check() + await expect(page.getByLabel("jDV Übergabedatum Suche")).toBeVisible() + // jdv Übergabe column is not visible by default + await expect( + page.getByRole("cell", { name: "jDV Übergabe", exact: true }), + ).toBeHidden() + }) + + await test.step("Suche nach Übergabedatum", async () => { + await page + .getByLabel("jDV Übergabedatum Suche") + .fill(dayjs().format("DD.MM.YYYY")) + + await page.getByLabel("Nach Dokumentationseinheiten suchen").click() + // jDV Übergabe date column is visible when filter is active + await expect( + page.getByRole("cell", { name: "jDV Übergabe", exact: true }), + ).toBeVisible() + }) + + await checkResultListForPublishedDocUnit( + page, + prefilledDocumentUnit.documentNumber, + ) + await checkResultListForPublishedDocUnit( + page, + secondPrefilledDocumentUnit.documentNumber, + ) + + await checkPublicationDateSorting(page) + }, + ) + }, +) + +async function checkPublicationDateSorting(page: Page) { + await test.step("Dok-Einheiten sind nach jDV-Übergabe sortiert", async () => { + const publicationDateCells = await page.getByTestId("publicationDate").all() + const publicationDates = await Promise.all( + publicationDateCells.map((date) => date.textContent()), + ).then((dates) => dates.map((date) => dayjs(date, "DD.MM.YYYY HH:mm"))) + + const areDatesSortedDesc = publicationDates.every( + (date, i) => + date && (i === 0 || !publicationDates[i - 1]!.isBefore(date)), + ) + expect(areDatesSortedDesc).toBe(true) + }) +} + +async function checkResultListForPublishedDocUnit( + page: Page, + documentNumber: string, +) { + await test.step(`Ergebnisliste enthält abgegebene Dok-Einheit ${documentNumber}`, async () => { + const resultRow = page.getByTestId(`listEntry_${documentNumber}`) + await expect(resultRow).toBeVisible() + await expect( + resultRow.getByLabel("Keine Übergabe terminiert"), + ).toBeVisible() + await expect(resultRow.getByTestId("publicationDate")).toContainText( + dayjs().format("DD.MM.YYYY"), + ) + }) +} diff --git a/frontend/test/queries/document_unit_search.spec.ts b/frontend/test/queries/document_unit_search.spec.ts index 4358da9cc..d03761fb9 100644 --- a/frontend/test/queries/document_unit_search.spec.ts +++ b/frontend/test/queries/document_unit_search.spec.ts @@ -100,6 +100,24 @@ test.describe("document unit search queries", () => { maxDuration: 450, // last max 556, average 304, min 241 minResults: 5, }, + { + title: "scheduled only", + parameter: { + myDocOfficeOnly: "true", + scheduledOnly: "true", + }, + maxDuration: 500, + minResults: 3, + }, + { + title: "publication date", + parameter: { + myDocOfficeOnly: "true", + publicationDate: "2100-11-21", + }, + maxDuration: 500, + minResults: 3, + }, ] testConfigurations.forEach((search) =>