import { describe, it, expect, vi, beforeEach } from "vitest"; import { render, screen } from "@testing-library/react"; import { AppModals } from "../AppModals"; import type { ModalManager } from "../../hooks/useModalManager"; import type { Toast } from "../../hooks/useToast"; // Mock the modals to avoid rendering all of them vi.mock("../TaskDetailModal", () => ({ TaskDetailModal: () => null, })); vi.mock("../SettingsModal", () => ({ SettingsModal: () => null, })); vi.mock("../GitHubImportModal", () => ({ GitHubImportModal: () => null, })); vi.mock("../PlanningModeModal", () => ({ PlanningModeModal: () => null, })); vi.mock("../SubtaskBreakdownModal", () => ({ SubtaskBreakdownModal: () => null, })); vi.mock("../TerminalModal", () => ({ TerminalModal: () => null, })); vi.mock("../ScriptsModal", () => ({ ScriptsModal: () => null, })); vi.mock("../FileBrowserModal", () => ({ FileBrowserModal: () => null, })); vi.mock("../UsageIndicator", () => ({ UsageIndicator: () => null, })); // Mock ScheduledTasksModal to capture props const mockScheduledTasksModalProps = vi.fn(); vi.mock("../ScheduledTasksModal", () => ({ ScheduledTasksModal: ({ projectId, ...rest }: any) => { mockScheduledTasksModalProps({ projectId, rest }); return null; }, })); vi.mock("../NewTaskModal", () => ({ NewTaskModal: () => null, })); vi.mock("../ActivityLogModal", () => ({ ActivityLogModal: () => null, })); vi.mock("../GitManagerModal", () => ({ GitManagerModal: () => null, })); vi.mock("../WorkflowStepManager", () => ({ WorkflowStepManager: () => null, })); vi.mock("../AgentListModal", () => ({ AgentListModal: () => null, })); vi.mock("../SetupWizardModal", () => ({ SetupWizardModal: () => null, })); const mockModelOnboardingModalProps = vi.fn(); vi.mock("../ModelOnboardingModal", () => ({ ModelOnboardingModal: (props: any) => { mockModelOnboardingModalProps(props); return null; }, })); vi.mock("../ToastContainer", () => ({ ToastContainer: () => null, })); vi.mock("../../hooks/useTaskHandlers", () => ({ useTaskHandlers: () => ({ handleModalCreate: vi.fn(), handlePlanningTaskCreated: vi.fn(), handlePlanningTasksCreated: vi.fn(), handleSubtaskTasksCreated: vi.fn(), handleGitHubImport: vi.fn(), }), })); vi.mock("../../hooks/useProjectActions", () => ({ useProjectActions: () => ({ handleSetupComplete: vi.fn(), handleModelOnboardingComplete: vi.fn(), }), })); // Mock @fusion/core types vi.mock("@fusion/core", () => ({})); // Mock ModalErrorBoundary vi.mock("../ErrorBoundary", () => ({ ModalErrorBoundary: ({ children }: { children: React.ReactNode }) => <>{children}, })); describe("AppModals", () => { const mockModalManager: ModalManager = { detailTask: null, settingsOpen: false, githubImportOpen: false, isPlanningOpen: false, planningInitialPlan: null, planningResumeSessionId: null, isSubtaskOpen: false, subtaskInitialDescription: null, subtaskResumeSessionId: null, terminalOpen: false, terminalInitialCommand: null, scriptsOpen: false, runScript: vi.fn(), filesOpen: false, fileBrowserWorkspace: "project", usageOpen: false, schedulesOpen: false, newTaskModalOpen: false, activityLogOpen: false, gitManagerOpen: false, workflowStepsOpen: false, agentsOpen: false, setupWizardOpen: false, modelOnboardingOpen: false, openDetailTask: vi.fn(), updateDetailTask: vi.fn(), openSettings: vi.fn(), closeSettings: vi.fn(), closeGitHubImport: vi.fn(), openPlanning: vi.fn(), closePlanning: vi.fn(), openSubtaskBreakdown: vi.fn(), closeSubtask: vi.fn(), openTerminal: vi.fn(), closeTerminal: vi.fn(), openScripts: vi.fn(), closeScripts: vi.fn(), openFiles: vi.fn(), closeFiles: vi.fn(), setFileWorkspace: vi.fn(), openUsage: vi.fn(), closeUsage: vi.fn(), openSchedules: vi.fn(), closeSchedules: vi.fn(), openNewTask: vi.fn(), closeNewTask: vi.fn(), openActivityLog: vi.fn(), closeActivityLog: vi.fn(), openGitManager: vi.fn(), closeGitManager: vi.fn(), openWorkflowSteps: vi.fn(), closeWorkflowSteps: vi.fn(), openAgents: vi.fn(), closeAgents: vi.fn(), openSetupWizard: vi.fn(), closeSetupWizard: vi.fn(), openModelOnboarding: vi.fn(), closeModelOnboarding: vi.fn(), openDetailTaskInitialTab: vi.fn(), settingsInitialSection: null, detailTaskInitialTab: null, }; const mockToasts: Toast[] = []; const mockSettings = { prAuthAvailable: false, themeMode: "dark" as const, colorTheme: "default" as const, setThemeMode: vi.fn(), setColorTheme: vi.fn(), }; beforeEach(() => { vi.clearAllMocks(); mockScheduledTasksModalProps.mockClear(); mockModelOnboardingModalProps.mockClear(); }); it("renders without crashing", () => { render( ); expect(document.body).toBeDefined(); }); describe("ModelOnboardingModal wiring", () => { it("passes project context and setup-wizard callback into onboarding modal", () => { const handleAddProject = vi.fn(); const manager = { ...mockModalManager, modelOnboardingOpen: true }; render( , ); expect(mockModelOnboardingModalProps).toHaveBeenCalledTimes(1); const props = mockModelOnboardingModalProps.mock.calls[0][0]; expect(props.projectId).toBe(""); expect(props.onOpenSetupWizard).toBe(handleAddProject); }); }); describe("ScheduledTasksModal projectId forwarding", () => { it("does not render ScheduledTasksModal when schedulesOpen is false", () => { const manager = { ...mockModalManager, schedulesOpen: false }; render( ); expect(mockScheduledTasksModalProps).not.toHaveBeenCalled(); }); it("renders ScheduledTasksModal with projectId when schedulesOpen is true and projectId is defined", () => { const manager = { ...mockModalManager, schedulesOpen: true }; render( ); expect(mockScheduledTasksModalProps).toHaveBeenCalledTimes(1); const captured = mockScheduledTasksModalProps.mock.calls[0][0]; expect(captured.projectId).toBe("proj-abc"); }); it("renders ScheduledTasksModal with undefined projectId when schedulesOpen is true and projectId is undefined", () => { const manager = { ...mockModalManager, schedulesOpen: true }; render( ); expect(mockScheduledTasksModalProps).toHaveBeenCalledTimes(1); const captured = mockScheduledTasksModalProps.mock.calls[0][0]; expect(captured.projectId).toBeUndefined(); }); it("renders ScheduledTasksModal with undefined projectId when projectId is empty string", () => { const manager = { ...mockModalManager, schedulesOpen: true }; render( ); expect(mockScheduledTasksModalProps).toHaveBeenCalledTimes(1); const captured = mockScheduledTasksModalProps.mock.calls[0][0]; // Empty string should pass through as-is expect(captured.projectId).toBe(""); }); }); });