You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
3.5 KiB
TypeScript

// 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: "오늘은 오후 미팅이 핵심이에요. <b>분기 리포트</b>",
};
describe("HeroBriefing", () => {
it("브리핑 노트 HTML 강조 + 칩 + 명령 입력", () => {
render(<HeroBriefing briefing={briefing} />);
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(<ApprovalSummaryCard items={items} savedToday="47분" pending={3} />);
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(<ApprovalSummaryCard items={[]} savedToday="0분" pending={0} />);
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(<GoalsCard goals={goals} />);
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(<InboxSummaryCard items={items} todayRouted={7} />);
expect(screen.getByText("오늘 7건")).toBeInTheDocument();
expect(screen.getByText("엄마 생신 선물")).toBeInTheDocument();
expect(screen.getByText("작업")).toBeInTheDocument(); // typeLabel(task)
expect(screen.getByRole("link", { name: /새로 적기/ })).toHaveAttribute("href", "/inbox");
});
});