From 51b3e88d17914d79a76668247e013043ed195aca Mon Sep 17 00:00:00 2001 From: Leonie Koch Date: Tue, 24 Dec 2024 12:54:53 +0100 Subject: [PATCH] Category import (#2448) * Refactor category import RISDEV-5888 * Add spacing for error modal RISDEV-5888 * Add active citations to category import RISDEV-5888 * Add tests RISDEV-5888 * Add tests for duplication RISDEV-5888 --- .../db-scripts/seed/R__seeding_testdata.sql | 34 +++ .../DocumentUnitContentRelatedIndexing.vue | 8 +- .../category-import/CategoryImport.vue | 182 ++++++++++++++-- .../category-import/ImportCategoryItem.vue | 58 ----- .../category-import/ImportListCategories.vue | 201 ------------------ .../category-import/SingleCategory.vue | 69 ++++++ .../FieldOfLawExpandableContainer.vue | 1 + .../importCategoryItem.spec.ts | 66 ------ .../category-import/importListCategories.ts | 118 ---------- .../category-import/singleCategory.spec.ts | 65 ++++++ .../test/e2e/caselaw/category-import.spec.ts | 48 ++++- 11 files changed, 386 insertions(+), 464 deletions(-) delete mode 100644 frontend/src/components/category-import/ImportCategoryItem.vue delete mode 100644 frontend/src/components/category-import/ImportListCategories.vue create mode 100644 frontend/src/components/category-import/SingleCategory.vue delete mode 100644 frontend/test/components/category-import/importCategoryItem.spec.ts delete mode 100644 frontend/test/components/category-import/importListCategories.ts create mode 100644 frontend/test/components/category-import/singleCategory.spec.ts diff --git a/backend/src/main/resources/db-scripts/seed/R__seeding_testdata.sql b/backend/src/main/resources/db-scripts/seed/R__seeding_testdata.sql index 803235cb0..be0f2996e 100644 --- a/backend/src/main/resources/db-scripts/seed/R__seeding_testdata.sql +++ b/backend/src/main/resources/db-scripts/seed/R__seeding_testdata.sql @@ -965,3 +965,37 @@ VALUES WHERE abbreviation = 'BGB' ) ); + +INSERT INTO + incremental_migration.related_documentation (id, dtype, document_number, documentation_unit_id, citation_type_id, referenced_documentation_unit_id, court_id, date) +VALUES + ( + gen_random_uuid (), + 'caselaw_active_citation', + 'YYTestDoc0013', + ( + SELECT id + FROM incremental_migration.documentation_unit + WHERE document_number = 'YYTestDoc0013' + ), + ( + SELECT id + FROM incremental_migration.citation_type + WHERE abbreviation = 'Änderung' + ), + ( + SELECT id + FROM incremental_migration.documentation_unit + WHERE document_number = 'YYTestDoc0012' + ), + ( + SELECT documentation_unit.court_id + FROM incremental_migration.documentation_unit + WHERE document_number = 'YYTestDoc0012' + ), + ( + SELECT documentation_unit.decision_date + FROM incremental_migration.documentation_unit + WHERE document_number = 'YYTestDoc0012' + ) + ); diff --git a/frontend/src/components/DocumentUnitContentRelatedIndexing.vue b/frontend/src/components/DocumentUnitContentRelatedIndexing.vue index 48adf86bb..7ce0bcc3a 100644 --- a/frontend/src/components/DocumentUnitContentRelatedIndexing.vue +++ b/frontend/src/components/DocumentUnitContentRelatedIndexing.vue @@ -28,11 +28,11 @@ const hasKeywords = computed( label="Schlagwörter" :should-show-button="!hasKeywords" > - + - - - + + + diff --git a/frontend/src/components/category-import/CategoryImport.vue b/frontend/src/components/category-import/CategoryImport.vue index 61aa63922..36bfc5e91 100644 --- a/frontend/src/components/category-import/CategoryImport.vue +++ b/frontend/src/components/category-import/CategoryImport.vue @@ -1,21 +1,26 @@ - - diff --git a/frontend/src/components/category-import/ImportListCategories.vue b/frontend/src/components/category-import/ImportListCategories.vue deleted file mode 100644 index d12e18b5f..000000000 --- a/frontend/src/components/category-import/ImportListCategories.vue +++ /dev/null @@ -1,201 +0,0 @@ - - - diff --git a/frontend/src/components/category-import/SingleCategory.vue b/frontend/src/components/category-import/SingleCategory.vue new file mode 100644 index 000000000..7f2b4bc75 --- /dev/null +++ b/frontend/src/components/category-import/SingleCategory.vue @@ -0,0 +1,69 @@ + + + diff --git a/frontend/src/components/field-of-law/FieldOfLawExpandableContainer.vue b/frontend/src/components/field-of-law/FieldOfLawExpandableContainer.vue index 8cccbf624..725f4fb41 100644 --- a/frontend/src/components/field-of-law/FieldOfLawExpandableContainer.vue +++ b/frontend/src/components/field-of-law/FieldOfLawExpandableContainer.vue @@ -76,6 +76,7 @@ export enum InputMethod { { - it("renders component initial state", async () => { - renderComponent("Importrubrik", true, false) - - expect(screen.getByText("Importrubrik")).toBeInTheDocument() - expect( - screen.getByRole("button", { name: "Importrubrik übernehmen" }), - ).toBeInTheDocument() - }) - - it("emits on button click", async () => { - const { emitted, user } = renderComponent("Importrubrik", true, false) - - await user.click( - screen.getByRole("button", { name: "Importrubrik übernehmen" }), - ) - - expect(emitted()["import"]).toBeTruthy() - }) - - it("displays success", async () => { - renderComponent("Importrubrik", true, true) - expect(screen.getByText("Übernommen")).toBeInTheDocument() - }) - - it("displays non importable", async () => { - renderComponent("Importrubrik", false, false) - expect(screen.getByText("Quellrubrik leer")).toBeInTheDocument() - }) - - it("displays error", async () => { - renderComponent("Importrubrik", true, false, "error message") - expect(screen.getByText("error message")).toBeInTheDocument() - }) -}) diff --git a/frontend/test/components/category-import/importListCategories.ts b/frontend/test/components/category-import/importListCategories.ts deleted file mode 100644 index 5ef8f5d66..000000000 --- a/frontend/test/components/category-import/importListCategories.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { createTestingPinia } from "@pinia/testing" -import { userEvent } from "@testing-library/user-event" -import { render, screen } from "@testing-library/vue" -import { setActivePinia } from "pinia" -import { beforeEach } from "vitest" -import { createRouter, createWebHistory } from "vue-router" -import ImportListCategories from "@/components/category-import/ImportListCategories.vue" -import { FieldOfLaw } from "@/domain/fieldOfLaw" -import NormReference from "@/domain/normReference" -import { useDocumentUnitStore } from "@/stores/documentUnitStore" -import routes from "~/test-helper/routes" - -function renderComponent( - keywords?: string[], - fieldsOfLaw?: FieldOfLaw[], - norms?: NormReference[], -) { - const user = userEvent.setup() - const router = createRouter({ - history: createWebHistory(), - routes: routes, - }) - return { - user, - ...render(ImportListCategories, { - props: { - importableKeywords: keywords, - importableFieldsOfLaw: fieldsOfLaw, - importableNorms: norms, - }, - global: { - plugins: [[router]], - }, - }), - } -} - -describe("ImportKeywords", () => { - beforeEach(() => { - setActivePinia(createTestingPinia()) - }) - it("renders component", () => { - renderComponent() - expect(screen.getByText("Schlagwörter")).toBeInTheDocument() - expect(screen.getByLabelText("Schlagwörter übernehmen")).toBeInTheDocument() - expect(screen.getByText("Sachgebiete")).toBeInTheDocument() - expect(screen.getByLabelText("Sachgebiete übernehmen")).toBeInTheDocument() - expect(screen.getByText("Normen")).toBeInTheDocument() - expect(screen.getByLabelText("Normen übernehmen")).toBeInTheDocument() - }) - - it("enables buttons with importable data", () => { - renderComponent( - ["one"], - [ - { - identifier: "AB-01", - text: "Sachgebiet 1-2-3", - norms: [], - children: [], - hasChildren: false, - }, - ], - [ - new NormReference({ - normAbbreviation: { - abbreviation: "abc", - }, - singleNorms: [], - normAbbreviationRawValue: "", - }), - ], - ) - expect(screen.getByLabelText("Schlagwörter übernehmen")).toBeEnabled() - expect(screen.getByLabelText("Sachgebiete übernehmen")).toBeEnabled() - expect(screen.getByLabelText("Normen übernehmen")).toBeEnabled() - }) - - it("disables buttons without importable data", () => { - renderComponent() - expect(screen.getByLabelText("Schlagwörter übernehmen")).toBeDisabled() - expect(screen.getByLabelText("Sachgebiete übernehmen")).toBeDisabled() - expect(screen.getByLabelText("Normen übernehmen")).toBeDisabled() - }) - - it("displays empty data badges without importable data", () => { - renderComponent() - expect(screen.getByTestId("Schlagwörter-empty")).toBeInTheDocument() - expect(screen.getByTestId("Sachgebiete-empty")).toBeInTheDocument() - expect(screen.getByTestId("Normen-empty")).toBeInTheDocument() - }) - - it("shows error modal if data could not be saved", async () => { - const mockedStore = useDocumentUnitStore() - vi.spyOn(mockedStore, "updateDocumentUnit").mockResolvedValue({ - status: 400, - error: { title: "error" }, - }) - const { user } = renderComponent(["one"]) - expect(screen.getByLabelText("Schlagwörter übernehmen")).toBeEnabled() - await user.click(screen.getByLabelText("Schlagwörter übernehmen")) - expect( - await screen.findByText("Fehler beim Speichern der Schlagwörter"), - ).toBeVisible() - }) - - it("shows success badge on successful import", async () => { - const mockedStore = useDocumentUnitStore() - vi.spyOn(mockedStore, "updateDocumentUnit").mockResolvedValue({ - status: 200, - data: { documentationUnitVersion: 1, patch: [], errorPaths: [] }, - }) - const { user } = renderComponent(["one"]) - expect(screen.getByLabelText("Schlagwörter übernehmen")).toBeEnabled() - await user.click(screen.getByLabelText("Schlagwörter übernehmen")) - expect(await screen.findByText("Übernommen")).toBeVisible() - }) -}) diff --git a/frontend/test/components/category-import/singleCategory.spec.ts b/frontend/test/components/category-import/singleCategory.spec.ts new file mode 100644 index 000000000..69c35d50f --- /dev/null +++ b/frontend/test/components/category-import/singleCategory.spec.ts @@ -0,0 +1,65 @@ +import { userEvent } from "@testing-library/user-event" +import { render, screen } from "@testing-library/vue" +import { createRouter, createWebHistory } from "vue-router" +import SingleCategory from "@/components/category-import/SingleCategory.vue" +import { ValidationError } from "@/components/input/types" +import routes from "~/test-helper/routes" + +function renderComponent(options?: { + label?: string + errorMessage?: ValidationError | undefined + hasContent?: boolean + handleImport?: () => void +}) { + const user = userEvent.setup() + const router = createRouter({ + history: createWebHistory(), + routes: routes, + }) + return { + user, + ...render(SingleCategory, { + props: { + label: options?.label ?? "Testrubrik", + errorMessage: options?.errorMessage ?? undefined, + hasContent: options?.hasContent ?? true, + handleImport: options?.handleImport ?? vi.fn(), + }, + global: { plugins: [[router]] }, + }), + } +} + +describe("SingleCategory", () => { + it("renders component initial state", async () => { + renderComponent() + + expect(screen.getByText("Testrubrik")).toBeInTheDocument() + expect( + screen.getByRole("button", { name: "Testrubrik übernehmen" }), + ).toBeInTheDocument() + }) + + it("button disabled, if no content", async () => { + renderComponent({ hasContent: false }) + + expect( + screen.getByRole("button", { name: "Testrubrik übernehmen" }), + ).toBeDisabled() + expect(screen.getByText("Quellrubrik leer")).toBeInTheDocument() + }) + + it("displays error message", async () => { + renderComponent({ errorMessage: { instance: "test", message: "Error" } }) + + expect(screen.getByText("Error")).toBeInTheDocument() + }) + + it("displays success", async () => { + const { user } = renderComponent() + await user.click( + screen.getByRole("button", { name: "Testrubrik übernehmen" }), + ) + expect(screen.getByText("Übernommen")).toBeInTheDocument() + }) +}) diff --git a/frontend/test/e2e/caselaw/category-import.spec.ts b/frontend/test/e2e/caselaw/category-import.spec.ts index 721bf0d2f..5aac46174 100644 --- a/frontend/test/e2e/caselaw/category-import.spec.ts +++ b/frontend/test/e2e/caselaw/category-import.spec.ts @@ -50,6 +50,12 @@ test.describe("category import", () => { await expect(page.getByText("Übernommen")).toBeVisible() await expect(page.getByText("keyword1")).toBeVisible() + + const keywordsContainer = page.getByTestId("keywords") + await expect(keywordsContainer.getByTestId("chip")).toHaveCount(1) + await page.getByLabel("Schlagwörter übernehmen").click() + // does not import duplicates + await expect(keywordsContainer.getByTestId("chip")).toHaveCount(1) }, ) @@ -69,6 +75,11 @@ test.describe("category import", () => { await expect(page.getByText("Übernommen")).toBeVisible() await expect(page.getByText("AR-01")).toBeVisible() + + await expect(page.getByTestId("field-of-law-summary")).toHaveCount(1) + await page.getByLabel("Sachgebiete übernehmen").click() + // does not import duplicates + await expect(page.getByTestId("field-of-law-summary")).toHaveCount(1) }, ) @@ -88,6 +99,38 @@ test.describe("category import", () => { await expect(page.getByText("Übernommen")).toBeVisible() await expect(page.getByText("BGB")).toBeVisible() + + const normContainer = page.getByTestId("norms") + await expect(normContainer.getByLabel("Listen Eintrag")).toHaveCount(2) + await page.getByLabel("Normen übernehmen").click() + // does not import duplicates + await expect(normContainer.getByLabel("Listen Eintrag")).toHaveCount(2) + }, + ) + + test( + "import active citations", + { tag: ["@RISDEV-5888"] }, + async ({ page, prefilledDocumentUnit }) => { + await navigateToCategoryImport(page, prefilledDocumentUnit.documentNumber) + await searchForDocumentUnitToImport(page, "YYTestDoc0013") + await expect(page.getByText("fileNumber5")).toBeVisible() + + await expect(page.getByLabel("Aktivzitierung übernehmen")).toBeVisible() + await page.getByLabel("Aktivzitierung übernehmen").click() + + await expect(page.getByText("Übernommen")).toBeVisible() + await expect(page.getByText("Änderung, BVerwG, 09.09.1987")).toBeVisible() + + const activeCitationsContainer = page.getByTestId("activeCitations") + await expect( + activeCitationsContainer.getByLabel("Listen Eintrag"), + ).toHaveCount(2) + await page.getByLabel("Aktivzitierung übernehmen").click() + // does not import duplicates + await expect( + activeCitationsContainer.getByLabel("Listen Eintrag"), + ).toHaveCount(2) }, ) @@ -106,9 +149,8 @@ test.describe("category import", () => { ) { await page .getByRole("textbox", { name: "Dokumentnummer Eingabefeld" }) - .fill("") - await page.getByLabel("Dokumentnummer Eingabefeld").click() - await page.keyboard.type(documentNumber) + .fill(documentNumber) + await expect( page.getByRole("button", { name: "Dokumentationseinheit laden" }), ).toBeEnabled()