// frontend/tests/dashboard/cards.test.tsx import { render, screen } from "@testing-library/react"; import { describe, expect, it, vi } from "vitest"; // HeroBriefing 는 CommandInput(useRouter) 을 포함 → next/navigation 모킹 vi.mock("next/navigation", () => ({ useRouter: () => ({ push: vi.fn() }) })); import { ApprovalSummaryCard } from "@/components/dashboard/ApprovalSummaryCard"; import { GoalsCard } from "@/components/dashboard/GoalsCard"; import { HeroBriefing } from "@/components/dashboard/HeroBriefing"; import { InboxSummaryCard } from "@/components/dashboard/InboxSummaryCard"; import type { ApprovalSummary, DashBriefing, DashGoal, InboxRecent } from "@/lib/types"; const briefing: DashBriefing = { today: "6월 7일 일요일", weather: { temp: 24, cond: "맑음 · 한낮 28°", icon: "sun" }, commute: "출근 23분", sleep: "7시간 12분", note: "오늘은 오후 미팅이 핵심이에요. 분기 리포트", }; describe("HeroBriefing", () => { it("브리핑 노트 HTML 강조 + 칩 + 명령 입력", () => { render(); expect(screen.getByText("아리 브리핑")).toBeInTheDocument(); expect(document.querySelector(".brief b")?.textContent).toBe("분기 리포트"); expect(screen.getByText("내일 오후 비워줘")).toBeInTheDocument(); expect(screen.getByPlaceholderText("오늘 하루, 무엇이든 맡겨보세요…")).toBeInTheDocument(); }); }); describe("ApprovalSummaryCard", () => { const items: ApprovalSummary[] = [ { id: "a4", icon: "mail", tone: "violet", title: "현우님께 회신 초안이 준비됐어요", time: "보내기 대기" }, ]; it("대기 N건 + 미니 행 + CTA", () => { render(); expect(screen.getByText("아리 결재함")).toBeInTheDocument(); expect(screen.getByText("오늘 47분 아껴드렸어요")).toBeInTheDocument(); expect(screen.getByText("대기 3건")).toBeInTheDocument(); expect(screen.getByText("현우님께 회신 초안이 준비됐어요")).toBeInTheDocument(); expect(screen.getByRole("link", { name: /결재함에서 승인하기/ })).toHaveAttribute( "href", "/approvals", ); }); it("0건이면 빈 상태", () => { render(); expect(screen.getByText(/다 처리해뒀어요/)).toBeInTheDocument(); }); }); describe("GoalsCard", () => { it("진행 막대 width + progressbar aria", () => { const goals: DashGoal[] = [ { id: "g1", title: "분기 OKR", pct: 68, sub: "12개 중 8개", tone: "blue" }, ]; render(); const bar = screen.getByRole("progressbar", { name: "분기 OKR" }); expect(bar).toHaveAttribute("aria-valuenow", "68"); expect(bar.querySelector("i")).toHaveStyle({ width: "68%" }); }); }); describe("InboxSummaryCard", () => { it("kind별 아이콘 + 새로 적기 CTA(/inbox)", () => { const items: InboxRecent[] = [ { id: "s3", kind: "voice", raw: "엄마 생신 선물", type: "task", proj_label: "가족", tone: "green" }, ]; render(); expect(screen.getByText("오늘 7건")).toBeInTheDocument(); expect(screen.getByText("엄마 생신 선물")).toBeInTheDocument(); expect(screen.getByText("작업")).toBeInTheDocument(); // typeLabel(task) expect(screen.getByRole("link", { name: /새로 적기/ })).toHaveAttribute("href", "/inbox"); }); });