import { render, screen } from "@testing-library/react"; import { PhaseSummaryViewer } from "./PhaseSummaryViewer"; import type { PhaseSummaryV2 } from "./artifactV2"; const phase: PhaseSummaryV2 = { schema_version: 2, phase: { id: "F5", num: 5, name: "sintesi" }, summary: "## Recap\nLa catena copre pazienti e impianti.", checks: [ { label: "Schema linking completo", status: "ok" }, { label: "Join validati", status: "warn", detail: "Un join manuale non testato" }, { label: "SQL eseguibile", status: "fail", detail: "Errore di sintassi" }, ], sections: [ { title: "Criteri di selezione", items: [ { label: "Pazienti attivi", table: "pazienti", column: "stato", value: "IS TRUE", kind: "filter", description: "Flag di stato attivo", rationale: "Solo pazienti in follow-up", }, ], }, ], tables: [ { name: "pazienti", role: "promoted", description: "Anagrafica pazienti", columns: [{ name: "stato", description: "Flag attivo", value_filter: "IS TRUE" }], }, { name: "log_accessi", role: "excluded", description: "Non pertinente" }, ], open_questions: ["Serve confermare la finestra temporale?"], }; test("renders phase id/name header and markdown summary", () => { render(); expect(screen.getByText(/F5/)).toBeInTheDocument(); expect(screen.getByText(/sintesi/)).toBeInTheDocument(); expect(screen.getByText("Recap")).toBeInTheDocument(); expect(screen.getByText(/La catena copre pazienti e impianti/)).toBeInTheDocument(); }); test("renders checks with status label and detail", () => { render(); expect(screen.getByText("Schema linking completo")).toBeInTheDocument(); expect(screen.getByText("Join validati")).toBeInTheDocument(); expect(screen.getByText("Un join manuale non testato")).toBeInTheDocument(); expect(screen.getByText("SQL eseguibile")).toBeInTheDocument(); expect(screen.getByText("Errore di sintassi")).toBeInTheDocument(); }); test("renders sections with item label, table.column code-chip, and value badge", () => { render(); expect(screen.getByText("Criteri di selezione")).toBeInTheDocument(); expect(screen.getByText("Pazienti attivi")).toBeInTheDocument(); expect(screen.getByText("pazienti.stato")).toBeInTheDocument(); expect(screen.getAllByText("IS TRUE").length).toBeGreaterThan(0); expect(screen.getByText("Flag di stato attivo")).toBeInTheDocument(); expect(screen.getByText("Solo pazienti in follow-up")).toBeInTheDocument(); }); test("renders tables recap with promoted/excluded roles and columns", () => { render(); expect(screen.getByText("pazienti")).toBeInTheDocument(); expect(screen.getByText(/promoted/i)).toBeInTheDocument(); expect(screen.getByText("log_accessi")).toBeInTheDocument(); expect(screen.getByText(/excluded/i)).toBeInTheDocument(); expect(screen.getByText("stato")).toBeInTheDocument(); expect(screen.getAllByText("IS TRUE").length).toBeGreaterThan(0); }); test("renders open_questions as a bullet list", () => { render(); expect(screen.getByText("Serve confermare la finestra temporale?")).toBeInTheDocument(); }); test("renders a legacy structured open question safely", () => { const malformed = { ...phase, open_questions: [ { label: "pazienti_finale restituisce 0 righe", question: "Verificare se i filtri sono troppo restrittivi", }, ], } as unknown as PhaseSummaryV2; render(); expect(screen.getByText("Verificare se i filtri sono troppo restrittivi")).toBeInTheDocument(); }); test("renders a section with title only (no items key) without crashing", () => { const proseOnly: PhaseSummaryV2 = { schema_version: 2, phase: { id: "F5", num: 5, name: "sintesi" }, sections: [{ title: "Note libere" }], }; render(); expect(screen.getByText("Note libere")).toBeInTheDocument(); }); test("omits open_questions section when empty and shows no 'undefined' text", () => { const minimal: PhaseSummaryV2 = { schema_version: 2, phase: { id: "F1", num: 1, name: "domanda" }, }; render(); expect(screen.queryByText(/undefined/i)).not.toBeInTheDocument(); expect(screen.getByText(/F1/)).toBeInTheDocument(); });