// frontend/tests/connectors/AddAccountMenu.test.tsx — phase-16 계정 추가(OAuth) 메뉴
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { AddAccountMenu } from "@/components/connectors/AddAccountMenu";
import { connectorsApi } from "@/lib/connectors/api";
vi.mock("@/lib/connectors/api", () => ({
connectorsApi: { providers: vi.fn(), oauthStart: vi.fn() },
}));
const providersMock = vi.mocked(connectorsApi.providers);
const oauthStartMock = vi.mocked(connectorsApi.oauthStart);
const assignMock = vi.fn();
const originalLocation = window.location;
beforeEach(() => {
providersMock.mockReset();
oauthStartMock.mockReset();
assignMock.mockReset();
// jsdom location.assign 은 non-configurable → location 객체 자체를 교체
Object.defineProperty(window, "location", {
configurable: true,
writable: true,
value: { ...originalLocation, assign: assignMock },
});
});
afterEach(() => {
Object.defineProperty(window, "location", {
configurable: true,
writable: true,
value: originalLocation,
});
vi.restoreAllMocks();
});
const PROVIDERS = [
{ domain: "mail", provider: "gmail", label: "Gmail", configured: true },
{ domain: "mail", provider: "outlook", label: "Outlook", configured: false },
];
describe("AddAccountMenu", () => {
it("provider 가 없으면 아무것도 렌더하지 않는다", async () => {
providersMock.mockResolvedValue([]);
const { container } = render();
await waitFor(() => expect(providersMock).toHaveBeenCalledWith("mail"));
expect(container.textContent).toBe("");
});
it("열면 configured/미구성 provider 를 보여준다", async () => {
providersMock.mockResolvedValue(PROVIDERS);
render();
const btn = await screen.findByText("계정 추가");
fireEvent.click(btn);
expect(screen.getByRole("menuitem", { name: /Gmail/ })).not.toBeDisabled();
expect(screen.getByRole("menuitem", { name: /Outlook/ })).toBeDisabled(); // 미구성
expect(screen.getByText("설정 필요")).toBeInTheDocument();
});
it("configured provider 클릭 시 oauthStart 후 authorize_url 로 이동", async () => {
providersMock.mockResolvedValue(PROVIDERS);
oauthStartMock.mockResolvedValue({ authorize_url: "https://accounts.google.com/o/oauth2/x" });
render();
fireEvent.click(await screen.findByText("계정 추가"));
fireEvent.click(screen.getByRole("menuitem", { name: /Gmail/ }));
await waitFor(() =>
expect(oauthStartMock).toHaveBeenCalledWith("mail", "gmail", "/settings?tab=mail"),
);
await waitFor(() =>
expect(assignMock).toHaveBeenCalledWith("https://accounts.google.com/o/oauth2/x"),
);
});
it("oauthStart 실패 시 onError 토스트 호출", async () => {
providersMock.mockResolvedValue(PROVIDERS);
oauthStartMock.mockRejectedValue(new Error("400"));
const onError = vi.fn();
render();
fireEvent.click(await screen.findByText("계정 추가"));
fireEvent.click(screen.getByRole("menuitem", { name: /Gmail/ }));
await waitFor(() => expect(onError).toHaveBeenCalledWith("Gmail 연결을 시작하지 못했어요"));
});
});