135 lines
5.1 KiB
TypeScript
135 lines
5.1 KiB
TypeScript
import { render, screen } from "@testing-library/react";
|
|
import { CteResultViewer } from "./CteResultViewer";
|
|
import type { CteResultV2 } from "./artifactV2";
|
|
|
|
vi.mock("./highlight", () => ({
|
|
highlightSql: vi.fn().mockResolvedValue('<pre data-testid="hl">SQL</pre>'),
|
|
}));
|
|
|
|
const okResult: CteResultV2 = {
|
|
schema_version: 2,
|
|
name: "pazienti_idonei",
|
|
index: 1,
|
|
total: 2,
|
|
purpose: "Seleziona i pazienti con follow-up attivo",
|
|
rationale: "Base della catena",
|
|
depends_on: [],
|
|
sql: "WITH pazienti_idonei AS (SELECT 1)",
|
|
status: "ok",
|
|
execution_ms: 142,
|
|
row_sample: 10,
|
|
warnings: [],
|
|
columns: [{ name: "paziente_id", description: "Identificativo paziente" }],
|
|
preview: { columns: ["paziente_id"], rows: [[1], [2]] },
|
|
note: "Nota del modello",
|
|
};
|
|
|
|
test("renders header meta: index/total badge, mono name, status badge, execution_ms, row_sample", async () => {
|
|
render(<CteResultViewer result={okResult} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.getByText("CTE 1/2")).toBeInTheDocument();
|
|
expect(screen.getAllByText("pazienti_idonei").length).toBeGreaterThan(0);
|
|
expect(screen.getByText(/success|ok/i)).toBeInTheDocument();
|
|
expect(screen.getByText(/142 ms/)).toBeInTheDocument();
|
|
expect(screen.getByText(/10 rows/)).toBeInTheDocument();
|
|
});
|
|
|
|
test("renders warnings as badges", async () => {
|
|
const withWarnings: CteResultV2 = { ...okResult, warnings: ["colonna troncata"] };
|
|
render(<CteResultViewer result={withWarnings} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.getByText("colonna troncata")).toBeInTheDocument();
|
|
});
|
|
|
|
test("passes sql to SqlViewer with mapped test status", async () => {
|
|
render(<CteResultViewer result={okResult} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.getByText(/passed/i)).toBeInTheDocument();
|
|
expect(screen.queryByRole("button", { name: /horizontal|vertical/i })).not.toBeInTheDocument();
|
|
});
|
|
|
|
test("error status maps to failed test status and destructive badge", async () => {
|
|
const errored: CteResultV2 = { ...okResult, status: "error" };
|
|
render(<CteResultViewer result={errored} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.getByText(/failed/i)).toBeInTheDocument();
|
|
});
|
|
|
|
test("renders PreviewGrid rows when preview is present", async () => {
|
|
render(<CteResultViewer result={okResult} />);
|
|
await screen.findByTestId("hl");
|
|
const cells = screen.getAllByRole("gridcell").map((c) => c.textContent);
|
|
expect(cells).toContain("1");
|
|
expect(cells).toContain("2");
|
|
});
|
|
|
|
test("shows a discreet empty-state when preview is absent", async () => {
|
|
const noPreview: CteResultV2 = { ...okResult, preview: undefined };
|
|
render(<CteResultViewer result={noPreview} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.getByText(/no preview rows/i)).toBeInTheDocument();
|
|
});
|
|
|
|
test("shows empty-state when preview has no rows", async () => {
|
|
const emptyPreview: CteResultV2 = { ...okResult, preview: { columns: ["paziente_id"], rows: [] } };
|
|
render(<CteResultViewer result={emptyPreview} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.getByText(/no preview rows/i)).toBeInTheDocument();
|
|
});
|
|
|
|
test("shows empty-state, no crash, when preview.rows is null (pre-upgrade records)", async () => {
|
|
const nullRows = {
|
|
...okResult,
|
|
preview: { columns: ["paziente_id"], rows: null as unknown as (string | number)[][] },
|
|
};
|
|
render(<CteResultViewer result={nullRows} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.getByText(/no preview rows/i)).toBeInTheDocument();
|
|
});
|
|
|
|
test("renders columns definition list with descriptions", async () => {
|
|
const { container } = render(<CteResultViewer result={okResult} />);
|
|
await screen.findByTestId("hl");
|
|
const dt = container.querySelector("dl dt");
|
|
expect(dt).toHaveTextContent("paziente_id");
|
|
expect(screen.getByText("Identificativo paziente")).toBeInTheDocument();
|
|
});
|
|
|
|
test("omits the columns definition list when all descriptions are empty", async () => {
|
|
const noDescriptions: CteResultV2 = {
|
|
...okResult,
|
|
columns: [{ name: "paziente_id", description: "" }],
|
|
};
|
|
const { container } = render(<CteResultViewer result={noDescriptions} />);
|
|
await screen.findByTestId("hl");
|
|
// No <dl> definition list should render when all descriptions are empty.
|
|
expect(container.querySelector("dl")).not.toBeInTheDocument();
|
|
});
|
|
|
|
test("renders note at the end", async () => {
|
|
render(<CteResultViewer result={okResult} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.getByText("Nota del modello")).toBeInTheDocument();
|
|
});
|
|
|
|
test("renders depends_on chips when present", async () => {
|
|
const withDeps: CteResultV2 = { ...okResult, depends_on: ["cte_base"] };
|
|
render(<CteResultViewer result={withDeps} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.getByText("cte_base")).toBeInTheDocument();
|
|
});
|
|
|
|
test("does not render 'undefined' strings for missing optional fields", async () => {
|
|
const minimal: CteResultV2 = {
|
|
schema_version: 2,
|
|
name: "final",
|
|
index: 2,
|
|
total: 2,
|
|
sql: "SELECT 1",
|
|
status: "ok",
|
|
};
|
|
render(<CteResultViewer result={minimal} />);
|
|
await screen.findByTestId("hl");
|
|
expect(screen.queryByText(/undefined/i)).not.toBeInTheDocument();
|
|
});
|