146 lines
3.5 KiB
TypeScript
146 lines
3.5 KiB
TypeScript
|
|
import { render, screen } from "@testing-library/react";
|
||
|
|
import userEvent from "@testing-library/user-event";
|
||
|
|
import { describe, expect, it, vi } from "vitest";
|
||
|
|
import { GatePanel } from "./GatePanel";
|
||
|
|
|
||
|
|
const baseProps = {
|
||
|
|
gateState: null,
|
||
|
|
gateStatusLabel: "Unknown",
|
||
|
|
gateStatusColor: "#aaa",
|
||
|
|
isGateLoading: false,
|
||
|
|
gateError: null,
|
||
|
|
lastGateRefresh: null,
|
||
|
|
onRefresh: vi.fn(),
|
||
|
|
};
|
||
|
|
|
||
|
|
describe("GatePanel", () => {
|
||
|
|
it("shows 'no workflow data' when gateState is null", () => {
|
||
|
|
render(<GatePanel {...baseProps} />);
|
||
|
|
expect(screen.getByText("No workflow data yet.")).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows loading message when isGateLoading is true", () => {
|
||
|
|
render(<GatePanel {...baseProps} isGateLoading={true} />);
|
||
|
|
expect(
|
||
|
|
screen.getByText("Loading workflow gates..."),
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows error with retry button", async () => {
|
||
|
|
const onRefresh = vi.fn();
|
||
|
|
render(
|
||
|
|
<GatePanel
|
||
|
|
{...baseProps}
|
||
|
|
gateError="Connection failed"
|
||
|
|
onRefresh={onRefresh}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
|
||
|
|
expect(screen.getByText("Connection failed")).toBeInTheDocument();
|
||
|
|
|
||
|
|
const retryButton = screen.getByRole("button", { name: "Retry" });
|
||
|
|
await userEvent.click(retryButton);
|
||
|
|
expect(onRefresh).toHaveBeenCalledOnce();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows gate status label and color", () => {
|
||
|
|
render(
|
||
|
|
<GatePanel
|
||
|
|
{...baseProps}
|
||
|
|
gateStatusLabel="Blocked"
|
||
|
|
gateStatusColor="#ff7b72"
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
expect(screen.getByText("Blocked")).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows test summary when gateState is provided", () => {
|
||
|
|
render(
|
||
|
|
<GatePanel
|
||
|
|
{...baseProps}
|
||
|
|
gateState={{
|
||
|
|
canAccept: true,
|
||
|
|
reasons: [],
|
||
|
|
warning: null,
|
||
|
|
summary: { total: 5, passed: 5, failed: 0 },
|
||
|
|
missingCategories: [],
|
||
|
|
}}
|
||
|
|
gateStatusLabel="Ready to accept"
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
expect(
|
||
|
|
screen.getByText(/5\/5 passing, 0 failing/),
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows missing categories", () => {
|
||
|
|
render(
|
||
|
|
<GatePanel
|
||
|
|
{...baseProps}
|
||
|
|
gateState={{
|
||
|
|
canAccept: false,
|
||
|
|
reasons: [],
|
||
|
|
warning: null,
|
||
|
|
summary: { total: 0, passed: 0, failed: 0 },
|
||
|
|
missingCategories: ["unit", "integration"],
|
||
|
|
}}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
expect(
|
||
|
|
screen.getByText("Missing: unit, integration"),
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows warning text", () => {
|
||
|
|
render(
|
||
|
|
<GatePanel
|
||
|
|
{...baseProps}
|
||
|
|
gateState={{
|
||
|
|
canAccept: false,
|
||
|
|
reasons: [],
|
||
|
|
warning: "Multiple tests failing — fix one at a time.",
|
||
|
|
summary: { total: 4, passed: 2, failed: 2 },
|
||
|
|
missingCategories: [],
|
||
|
|
}}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
expect(
|
||
|
|
screen.getByText("Multiple tests failing — fix one at a time."),
|
||
|
|
).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("shows reasons as list items", () => {
|
||
|
|
render(
|
||
|
|
<GatePanel
|
||
|
|
{...baseProps}
|
||
|
|
gateState={{
|
||
|
|
canAccept: false,
|
||
|
|
reasons: ["No approved test plan.", "Tests are failing."],
|
||
|
|
warning: null,
|
||
|
|
summary: { total: 2, passed: 1, failed: 1 },
|
||
|
|
missingCategories: [],
|
||
|
|
}}
|
||
|
|
/>,
|
||
|
|
);
|
||
|
|
expect(
|
||
|
|
screen.getByText("No approved test plan."),
|
||
|
|
).toBeInTheDocument();
|
||
|
|
expect(screen.getByText("Tests are failing.")).toBeInTheDocument();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("calls onRefresh when Refresh button is clicked", async () => {
|
||
|
|
const onRefresh = vi.fn();
|
||
|
|
render(<GatePanel {...baseProps} onRefresh={onRefresh} />);
|
||
|
|
|
||
|
|
await userEvent.click(
|
||
|
|
screen.getByRole("button", { name: "Refresh" }),
|
||
|
|
);
|
||
|
|
expect(onRefresh).toHaveBeenCalledOnce();
|
||
|
|
});
|
||
|
|
|
||
|
|
it("disables Refresh button when loading", () => {
|
||
|
|
render(<GatePanel {...baseProps} isGateLoading={true} />);
|
||
|
|
expect(screen.getByRole("button", { name: "Refresh" })).toBeDisabled();
|
||
|
|
});
|
||
|
|
});
|