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.
133 lines
3.7 KiB
TypeScript
133 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: "나",
|
|
cc: "",
|
|
thread_id: "",
|
|
subject: "온보딩 시안 v3",
|
|
time: "8분 전",
|
|
read: true,
|
|
starred: false,
|
|
has_attach: true,
|
|
labels: [],
|
|
preview: "p",
|
|
category: "primary",
|
|
ai,
|
|
date: "오늘 09:12",
|
|
body: ["본문"],
|
|
body_html: "",
|
|
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);
|
|
});
|
|
});
|