// frontend/tests/calendar/MeetDrawer.test.tsx — 회의 도우미 4상태 렌더 + 액션 왕복 import { render, screen, fireEvent, waitFor } from "@testing-library/react"; import { expect, test, vi } from "vitest"; import { MeetDrawer } from "@/components/calendar/MeetDrawer"; import { calendarApi } from "@/lib/calendar/api"; vi.mock("@/lib/calendar/api"); const ev = { id: "e3", title: "팀 데일리 스탠드업", start: "09:30", end: "09:45", loc: "Zoom", } as never; const cal = { id: "team", name: "팀", tone: "green", on: true, count: 4 } as never; test("done 회의: 요약·결정·액션 + 작업으로", async () => { (calendarApi.meeting as never as ReturnType).mockResolvedValue({ id: "e3", phase: "done", one_on_one: false, meta: "...", summary: ["s1"], decisions: ["d1"], actions: [ { idx: 2, text: "매출 데이터 전달", who: "현우", when: "오늘", added: false, materialized_task_id: null, }, ], agenda: [], last_meeting: {}, last_actions: [], insights: [], docs: [], person: {}, promises: [], signals: [], talking_points: [], starts_in: "", }); (calendarApi.materialize as never as ReturnType).mockResolvedValue({ action: {}, task: {}, all_added: true, }); render( {}} />); expect(await screen.findByText("회의 노트 정리됨")).toBeInTheDocument(); expect(screen.getByText("매출 데이터 전달")).toBeInTheDocument(); // "작업으로" 행 버튼 (전체 보내기 버튼 "…모두 작업으로 보내기" 와 구분) fireEvent.click(screen.getByRole("button", { name: "작업으로" })); await waitFor(() => expect(calendarApi.materialize).toHaveBeenCalledWith("e3", 2)); }); test("upcoming: 안건·지난액션·인사이트·docs", async () => { (calendarApi.meeting as never as ReturnType).mockResolvedValue({ id: "e6", phase: "upcoming", one_on_one: false, starts_in: "2시간 50분 후 시작", agenda: ["Q2 핵심 지표 리뷰 — 리텐션 · 매출"], docs: ["분기 리포트 초안 · 75%"], insights: ["리텐션 KPI가 전분기 대비 +6%p"], last_actions: [{ text: "x", who: "나", done: false }], last_meeting: { when: "지난주 월", note: "n" }, summary: [], decisions: [], actions: [], person: {}, promises: [], signals: [], talking_points: [], meta: "", }); render( {}} />, ); expect(await screen.findByText("2시간 50분 후 시작")).toBeInTheDocument(); expect(screen.getByText(/Q2 핵심 지표 리뷰/)).toBeInTheDocument(); expect(screen.getByText(/분기 리포트 초안 · 75%/)).toBeInTheDocument(); }); test("live: 기록 중 배지", async () => { (calendarApi.meeting as never as ReturnType).mockResolvedValue({ id: "e4", phase: "live", one_on_one: false, summary: ["논의1"], decisions: [], actions: [ { idx: 0, text: "a", who: "나", when: "내일", added: false, materialized_task_id: null }, ], agenda: [], last_meeting: {}, last_actions: [], insights: [], docs: [], person: {}, promises: [], signals: [], talking_points: [], meta: "", starts_in: "", }); render( {}} />); expect(await screen.findByText("기록 중")).toBeInTheDocument(); }); test("1:1: 약속·시그널·대화 주제", async () => { (calendarApi.meeting as never as ReturnType).mockResolvedValue({ id: "e7", phase: "upcoming", one_on_one: true, starts_in: "오늘 16:30", person: { name: "민서", initial: "민", tone: "green" }, promises: [{ text: "강의 지원 품의", done: false }], signals: [{ k: "업무량", v: "진행 4건", tone: "amber" }], talking_points: ["전처리 과제에서 막히는 부분이 있는지"], last_meeting: { when: "5월 25일", note: "n" }, summary: [], decisions: [], agenda: [], last_actions: [], insights: [], docs: [], actions: [], meta: "", }); render( {}} />, ); expect(await screen.findByText("1:1 어시스턴트")).toBeInTheDocument(); expect(screen.getByText("민서님 시그널")).toBeInTheDocument(); expect(screen.getByText("전처리 과제에서 막히는 부분이 있는지")).toBeInTheDocument(); });