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.
83 lines
3.4 KiB
TypeScript
83 lines
3.4 KiB
TypeScript
// 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(<AddAccountMenu domain="mail" redirectAfter="/settings" />);
|
|
await waitFor(() => expect(providersMock).toHaveBeenCalledWith("mail"));
|
|
expect(container.textContent).toBe("");
|
|
});
|
|
|
|
it("열면 configured/미구성 provider 를 보여준다", async () => {
|
|
providersMock.mockResolvedValue(PROVIDERS);
|
|
render(<AddAccountMenu domain="mail" redirectAfter="/settings?tab=mail" />);
|
|
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(<AddAccountMenu domain="mail" redirectAfter="/settings?tab=mail" />);
|
|
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(<AddAccountMenu domain="mail" redirectAfter="/settings" onError={onError} />);
|
|
fireEvent.click(await screen.findByText("계정 추가"));
|
|
fireEvent.click(screen.getByRole("menuitem", { name: /Gmail/ }));
|
|
await waitFor(() => expect(onError).toHaveBeenCalledWith("Gmail 연결을 시작하지 못했어요"));
|
|
});
|
|
});
|