177 lines
5.5 KiB
TypeScript
177 lines
5.5 KiB
TypeScript
import { render, screen } from "@testing-library/react";
|
|
import { ArtifactView } from "./ArtifactView";
|
|
|
|
vi.mock("./mermaid", () => ({
|
|
renderMermaid: vi.fn().mockResolvedValue('<svg data-testid="mm"></svg>'),
|
|
}));
|
|
|
|
vi.mock("./highlight", () => ({
|
|
highlightSql: vi.fn().mockResolvedValue('<pre data-testid="hl">SQL</pre>'),
|
|
}));
|
|
|
|
test("sql artifact renders the SQL text", async () => {
|
|
render(<ArtifactView artifact={{ kind: "sql", data: "SELECT 1" }} />);
|
|
expect(screen.getByText("SELECT 1")).toBeInTheDocument();
|
|
await screen.findByTestId("hl");
|
|
});
|
|
|
|
test("sql artifact accepts a { content } wrapper", async () => {
|
|
render(<ArtifactView artifact={{ kind: "sql", data: { content: "SELECT 7" } }} />);
|
|
expect(screen.getByText("SELECT 7")).toBeInTheDocument();
|
|
await screen.findByTestId("hl");
|
|
});
|
|
|
|
test("an empty artifact shows an explicit fallback instead of a blank panel", () => {
|
|
render(<ArtifactView artifact={{ kind: "sql", data: {} }} />);
|
|
expect(screen.getByText("No artifact content available.")).toBeInTheDocument();
|
|
});
|
|
|
|
test("cte_plan renders an ordered list of names", () => {
|
|
render(<ArtifactView artifact={{ kind: "cte_plan", data: { names: ["a_cte", "b_cte"] } }} />);
|
|
expect(screen.getByText("a_cte")).toBeInTheDocument();
|
|
expect(screen.getByText("b_cte")).toBeInTheDocument();
|
|
});
|
|
|
|
test("question renders markdown headings", () => {
|
|
render(<ArtifactView artifact={{ kind: "question", data: "## Domanda\nrevised" }} />);
|
|
expect(screen.getByText("Domanda")).toBeInTheDocument();
|
|
});
|
|
|
|
test("unknown object kind renders as formatted sections, never raw JSON", () => {
|
|
render(
|
|
<ArtifactView
|
|
artifact={{
|
|
kind: "phase",
|
|
data: {
|
|
recap: "Domanda: lista pazienti.",
|
|
chiarimenti_risolti: ["finestra_temporale — 5 anni", "tipo_evento — solo impianto"],
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
// Humanized section labels, values as text/bullets — and NO raw JSON braces.
|
|
expect(screen.getByText("Recap")).toBeInTheDocument();
|
|
expect(screen.getByText("Chiarimenti risolti")).toBeInTheDocument();
|
|
expect(screen.getByText("finestra_temporale — 5 anni")).toBeInTheDocument();
|
|
expect(screen.queryByText(/"recap"/)).not.toBeInTheDocument();
|
|
});
|
|
|
|
test("schema_linking renders the schema viewer", async () => {
|
|
render(
|
|
<ArtifactView
|
|
artifact={{
|
|
kind: "schema_linking",
|
|
data: { candidates: [{ kind: "table", name: "orders", decision: "promoted" }], joins: [] },
|
|
}}
|
|
/>,
|
|
);
|
|
expect(await screen.findByTestId("mm")).toBeInTheDocument();
|
|
});
|
|
|
|
test("cte_plan v2 dispatches to CtePlanViewer", () => {
|
|
render(
|
|
<ArtifactView
|
|
artifact={{
|
|
kind: "cte_plan",
|
|
data: {
|
|
schema_version: 2,
|
|
strategy: "Filtriamo prima i pazienti idonei.",
|
|
ctes: [{ name: "pazienti_idonei", index: 1, purpose: "Seleziona pazienti" }],
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
expect(screen.getByText("Filtriamo prima i pazienti idonei.")).toBeInTheDocument();
|
|
expect(screen.getByText("CTE 1/1")).toBeInTheDocument();
|
|
});
|
|
|
|
test("cte_plan v1 (legacy names list) still renders via the legacy path", () => {
|
|
render(<ArtifactView artifact={{ kind: "cte_plan", data: { names: ["a_cte", "b_cte"] } }} />);
|
|
expect(screen.getByText("a_cte")).toBeInTheDocument();
|
|
expect(screen.getByText("b_cte")).toBeInTheDocument();
|
|
});
|
|
|
|
test("cte_result v2 dispatches to CteResultViewer", async () => {
|
|
render(
|
|
<ArtifactView
|
|
artifact={{
|
|
kind: "cte_result",
|
|
data: {
|
|
schema_version: 2,
|
|
name: "pazienti_idonei",
|
|
index: 1,
|
|
total: 1,
|
|
sql: "SELECT 1",
|
|
status: "ok",
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.getByText("CTE 1/1")).toBeInTheDocument();
|
|
});
|
|
|
|
test("cte_result v1 (bare sql string) still renders via toSqlBlocks legacy path", async () => {
|
|
render(<ArtifactView artifact={{ kind: "cte_result", data: "SELECT 42" }} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.queryByText("CTE")).not.toBeInTheDocument();
|
|
});
|
|
|
|
test("phase v2 dispatches to PhaseSummaryViewer", () => {
|
|
render(
|
|
<ArtifactView
|
|
artifact={{
|
|
kind: "phase",
|
|
data: {
|
|
schema_version: 2,
|
|
phase: { id: "F5", num: 5, name: "sintesi" },
|
|
summary: "Riassunto della fase.",
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
expect(screen.getByText("F5 — sintesi")).toBeInTheDocument();
|
|
expect(screen.getByText("Riassunto della fase.")).toBeInTheDocument();
|
|
});
|
|
|
|
test("phase v2 tolerates the malformed open question from the latest session", () => {
|
|
render(
|
|
<ArtifactView
|
|
artifact={{
|
|
kind: "phase",
|
|
data: {
|
|
schema_version: 2,
|
|
phase: { id: "F6", num: 6, name: "Piano CTE" },
|
|
summary: "Piano completato.",
|
|
open_questions: [
|
|
{
|
|
label: "pazienti_finale restituisce 0 righe",
|
|
question: "Verificare se la condizione temporale è troppo restrittiva",
|
|
},
|
|
],
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
|
|
expect(
|
|
screen.getByText("Verificare se la condizione temporale è troppo restrittiva"),
|
|
).toBeInTheDocument();
|
|
});
|
|
|
|
test("phase v1 (no schema_version) still renders via legacy markdown/structured path", () => {
|
|
render(
|
|
<ArtifactView
|
|
artifact={{
|
|
kind: "phase",
|
|
data: {
|
|
recap: "Domanda: lista pazienti.",
|
|
chiarimenti_risolti: ["finestra_temporale — 5 anni"],
|
|
},
|
|
}}
|
|
/>,
|
|
);
|
|
expect(screen.getByText("Recap")).toBeInTheDocument();
|
|
expect(screen.getByText("Chiarimenti risolti")).toBeInTheDocument();
|
|
});
|