/** * @file SessionDefaultsSettings.test.tsx * @description Session defaults: Bypass becomes Claude's default permission * mode or Codex's default bypass only after the confirm, a cancelled confirm * keeps the old default, the plain modes save at once, and the pet chat's * safe read never returns bypass. * @author Nguyễn Ngọc Trí Vĩ */ import { fireEvent, render, screen, waitFor } from "@testing-library/react"; import { beforeEach, describe, expect, it, vi } from "vitest"; import { SessionDefaultsSettings } from "../SessionDefaultsSettings"; import { confirmDialog } from "../../../lib/confirm"; import { readCodexDefaults, readDefaultMode } from "../../../lib/sessionDefaults"; const aiTools = vi.hoisted(() => ({ tools: [ { id: "claude", label: "Claude Code", installed: true, enabled: true }, { id: "codex", label: "Codex", installed: true, enabled: true }, ], })); vi.mock("../../../hooks/useAiTools", () => ({ useAiTools: () => aiTools })); vi.mock("../../../lib/confirm", () => ({ confirmDialog: vi.fn() })); const confirm = vi.mocked(confirmDialog); const radio = (name: RegExp) => screen.getAllByRole("radio", { name })[0]!; describe("SessionDefaultsSettings", () => { beforeEach(() => { localStorage.clear(); confirm.mockReset(); }); it("saves a plain mode without asking", () => { render(); fireEvent.click(radio(/plan/i)); expect(confirm).not.toHaveBeenCalled(); expect(readDefaultMode()).toBe("plan"); }); it("makes Bypass Claude's default only once confirmed", async () => { confirm.mockResolvedValueOnce(false); render(); fireEvent.click(radio(/bypass/i)); await waitFor(() => expect(confirm).toHaveBeenCalledTimes(1)); expect(readDefaultMode()).toBe("auto"); confirm.mockResolvedValueOnce(true); fireEvent.click(radio(/bypass/i)); await waitFor(() => expect(readDefaultMode()).toBe("bypassPermissions")); expect(readDefaultMode({ safe: true })).toBe("auto"); }); it("turns Codex's default bypass on only once confirmed, off without asking", async () => { confirm.mockResolvedValueOnce(true); render(); const sw = screen.getByRole("switch"); fireEvent.click(sw); await waitFor(() => expect(readCodexDefaults().bypass).toBe(true)); fireEvent.click(screen.getByRole("switch")); await waitFor(() => expect(readCodexDefaults().bypass).toBe(false)); expect(confirm).toHaveBeenCalledTimes(1); }); it("shows nothing when neither Claude nor Codex is enabled", () => { const saved = aiTools.tools; aiTools.tools = []; const { container } = render(); expect(container.firstChild).toBeNull(); aiTools.tools = saved; }); });