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.

129 lines
3.7 KiB
TypeScript

// frontend/tests/mail/AriPanel.test.tsx — 섹션 조건부 렌더 + 모두 적용 바 + added 상태
import { fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { AriPanel } from "@/components/mail/AriPanel";
import type { AiAnalysis, EmailDetail } from "@/lib/types";
const fullAi: AiAnalysis = {
summary: "온보딩 시안 v3 도착",
priority: "높음",
category: "검토 요청",
tasks: [
{
text: "온보딩 시안 v3 피드백 정리",
project: "온보딩 리디자인 · 와이어프레임",
due: "6/13",
prio: "높음",
},
],
events: [],
replies: [{ tone: "수락 · 일정 약속", preview: "금요일까지 피드백 드릴게요", body: "본문" }],
file: { project: "온보딩 리디자인", reason: "‘와이어프레임’ 작업과 직접 연결돼요" },
};
function detail(ai: AiAnalysis | null): EmailDetail {
return {
id: "m1",
account: "work",
from: "hyunwoo",
to: "나",
subject: "온보딩 시안 v3",
time: "8분 전",
read: true,
starred: false,
has_attach: true,
labels: [],
preview: "p",
ai,
date: "오늘 09:12",
body: ["본문"],
attachments: [],
};
}
describe("AriPanel", () => {
it("분석 헤더 + 요약 + 할일/답장/정리 섹션 렌더", () => {
render(
<AriPanel
m={detail(fullAi)}
added={{}}
onAdd={() => {}}
onReply={() => {}}
onAddAll={() => {}}
/>,
);
expect(screen.getByText("아리가 분석했어요")).toBeInTheDocument();
expect(screen.getByText(/요약 —/)).toBeInTheDocument();
expect(screen.getByText("온보딩 시안 v3 피드백 정리")).toBeInTheDocument();
expect(screen.getByText("금요일까지 피드백 드릴게요")).toBeInTheDocument();
expect(screen.getByText(/온보딩 리디자인에 정리/)).toBeInTheDocument();
});
it("keys>1 일 때 모두 적용 바 표시", () => {
// task 1 + file 1 = keys 2 → ap-allbar
render(
<AriPanel
m={detail(fullAi)}
added={{}}
onAdd={() => {}}
onReply={() => {}}
onAddAll={() => {}}
/>,
);
expect(screen.getByText(/한 번에 적용할 수 있어요/)).toBeInTheDocument();
});
it("m7 빈 ai → 요약만, 섹션/모두 적용 바 없음", () => {
const empty: AiAnalysis = {
summary: "Stripe 영수증",
priority: "낮음",
category: "영수증",
tasks: [],
events: [],
replies: [],
file: null,
};
render(
<AriPanel
m={detail(empty)}
added={{}}
onAdd={() => {}}
onReply={() => {}}
onAddAll={() => {}}
/>,
);
expect(screen.getByText(/요약 —/)).toBeInTheDocument();
expect(screen.queryByText("할 일로 추가")).not.toBeInTheDocument();
expect(screen.queryByText(/한 번에 적용할 수 있어요/)).not.toBeInTheDocument();
});
it("added 상태에서 추가 버튼은 추가됨/done 클래스", () => {
render(
<AriPanel
m={detail(fullAi)}
added={{ "t:m1:0": true }}
onAdd={() => {}}
onReply={() => {}}
onAddAll={() => {}}
/>,
);
const btn = screen.getByText("추가됨").closest("button");
expect(btn).toHaveClass("done");
});
it("정리 버튼 클릭 시 onAdd(file) 호출", () => {
const onAdd = vi.fn();
render(
<AriPanel
m={detail(fullAi)}
added={{}}
onAdd={onAdd}
onReply={() => {}}
onAddAll={() => {}}
/>,
);
fireEvent.click(screen.getByText("정리"));
expect(onAdd).toHaveBeenCalledWith("f:m1", "file", 0);
});
});