feat: bootstrap auto virtual tryon admin frontend
This commit is contained in:
75
tests/ui/dashboard-shell.test.tsx
Normal file
75
tests/ui/dashboard-shell.test.tsx
Normal file
@@ -0,0 +1,75 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
import HomePage from "../../app/page";
|
||||
import { DashboardShell } from "@/components/layout/dashboard-shell";
|
||||
|
||||
vi.mock("next/navigation", () => ({
|
||||
redirect: vi.fn(),
|
||||
}));
|
||||
|
||||
test("renders reusable dashboard landmarks for rail and content", () => {
|
||||
render(<DashboardShell>content</DashboardShell>);
|
||||
|
||||
expect(
|
||||
screen.getByRole("complementary", { name: "Dashboard rail" }),
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByRole("main", { name: "Dashboard content" }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("renders its children in the main content area", () => {
|
||||
render(<DashboardShell>dashboard body</DashboardShell>);
|
||||
|
||||
expect(
|
||||
screen.getByRole("main", { name: "Dashboard content" }),
|
||||
).toHaveTextContent("dashboard body");
|
||||
});
|
||||
|
||||
test("renders the primary navigation as shell framing with route links", () => {
|
||||
const { container } = render(<DashboardShell>content</DashboardShell>);
|
||||
const navigation = screen.getByRole("navigation", {
|
||||
name: "Primary Navigation",
|
||||
});
|
||||
|
||||
expect(navigation).toContainElement(screen.getByRole("link", { name: "订单总览" }));
|
||||
expect(navigation).toContainElement(
|
||||
screen.getByRole("link", { name: "审核工作台" }),
|
||||
);
|
||||
expect(container.querySelectorAll('nav[aria-label="Primary Navigation"] a')).toHaveLength(6);
|
||||
expect(screen.getByRole("link", { name: "订单总览" })).toHaveAttribute(
|
||||
"href",
|
||||
"/orders",
|
||||
);
|
||||
expect(screen.getByRole("link", { name: "审核工作台" })).toHaveAttribute(
|
||||
"href",
|
||||
"/reviews/workbench",
|
||||
);
|
||||
});
|
||||
|
||||
test("does not inject page-level content chrome into the main region", () => {
|
||||
render(<DashboardShell>dashboard body</DashboardShell>);
|
||||
|
||||
const main = screen.getByRole("main", { name: "Dashboard content" });
|
||||
|
||||
expect(main).not.toHaveTextContent("Gallery-First Warm Console");
|
||||
expect(main).not.toHaveTextContent("Shared layout frame");
|
||||
});
|
||||
|
||||
test("locks the rail to the viewport and makes the content pane independently scrollable on desktop", () => {
|
||||
const { container } = render(<DashboardShell>dashboard body</DashboardShell>);
|
||||
const shellFrame = container.firstElementChild;
|
||||
const rail = screen.getByRole("complementary", { name: "Dashboard rail" });
|
||||
const main = screen.getByRole("main", { name: "Dashboard content" });
|
||||
|
||||
expect(shellFrame).toHaveClass("md:h-screen", "md:overflow-hidden");
|
||||
expect(rail).toHaveClass("md:h-full");
|
||||
expect(main).toHaveClass("md:h-full", "md:overflow-y-auto");
|
||||
});
|
||||
|
||||
test("redirects the root page to orders", () => {
|
||||
HomePage();
|
||||
|
||||
expect(redirect).toHaveBeenCalledWith("/orders");
|
||||
});
|
||||
48
tests/ui/status-badge.test.tsx
Normal file
48
tests/ui/status-badge.test.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import type { ComponentProps } from "react";
|
||||
|
||||
import { StatusBadge } from "@/components/ui/status-badge";
|
||||
|
||||
// @ts-expect-error "running" is a step status, not a review decision.
|
||||
const invalidReviewDecisionProps: ComponentProps<typeof StatusBadge> = {
|
||||
variant: "reviewDecision",
|
||||
status: "running",
|
||||
};
|
||||
|
||||
test("renders the waiting review label", () => {
|
||||
render(<StatusBadge status="waiting_review" />);
|
||||
|
||||
expect(screen.getByText("待审核")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("uses order status metadata for the rendered tone", () => {
|
||||
render(<StatusBadge status="failed" />);
|
||||
|
||||
expect(screen.getByText("失败")).toHaveAttribute("data-tone", "danger");
|
||||
});
|
||||
|
||||
test("can render review decision metadata when a variant is provided", () => {
|
||||
render(<StatusBadge status="reject" variant="reviewDecision" />);
|
||||
|
||||
expect(screen.getByText("驳回")).toHaveAttribute("data-tone", "danger");
|
||||
});
|
||||
|
||||
test("renders step status metadata for the stepStatus variant", () => {
|
||||
render(<StatusBadge status="running" variant="stepStatus" />);
|
||||
|
||||
expect(screen.getByText("执行中")).toHaveAttribute("data-tone", "info");
|
||||
});
|
||||
|
||||
test("renders workflow step metadata for the workflowStep variant", () => {
|
||||
render(<StatusBadge status="review" variant="workflowStep" />);
|
||||
|
||||
expect(screen.getByText("人工审核")).toHaveAttribute("data-tone", "warning");
|
||||
});
|
||||
|
||||
test("throws a descriptive error for invalid runtime status and variant pairings", () => {
|
||||
expect(() =>
|
||||
render(<StatusBadge status={"reject" as never} variant="order" />),
|
||||
).toThrow('Invalid status "reject" for variant "order".');
|
||||
|
||||
expect(invalidReviewDecisionProps.variant).toBe("reviewDecision");
|
||||
});
|
||||
Reference in New Issue
Block a user