import { describe, expect, it, vi, beforeEach, afterEach } from "vitest"; import { screen } from "@testing-library/react"; import { EventMessage } from "#/components/v1/chat/event-message"; import { useConversationStore } from "#/stores/conversation-store"; import { useAgentState } from "#/hooks/use-agent-state"; import { AgentState } from "#/types/agent-state"; import { renderWithProviders, createPlanningObservationEvent, } from "test-utils"; // Mock useConfig vi.mock("#/hooks/query/use-config", () => ({ useConfig: () => ({ data: { APP_MODE: "saas" }, }), })); // Mock useAgentState vi.mock("#/hooks/use-agent-state"); // Mock PlanPreview component to verify it's rendered with correct props // Mock useConversationId (EventMessage -> useAgentState -> useActiveConversation -> useConversationId) vi.mock("#/hooks/use-conversation-id", () => ({ useConversationId: () => ({ conversationId: "test-conversation-id" }), })); // Mock PlanPreview component to verify it's rendered vi.mock("#/components/features/chat/plan-preview", () => ({ PlanPreview: ({ planContent, isStreaming, }: { planContent?: string | null; isStreaming?: boolean; }) => (
Plan Preview: {planContent || "null"}
), })); describe("EventMessage - PlanPreview rendering", () => { beforeEach(() => { vi.clearAllMocks(); // Reset conversation store useConversationStore.setState({ planContent: null, }); // Default mock for useAgentState vi.mocked(useAgentState).mockReturnValue({ curAgentState: AgentState.INIT, isArchived: false, }); }); afterEach(() => { vi.clearAllMocks(); }); it("should render PlanPreview when PlanningFileEditorObservation event ID is in planPreviewEventIds", () => { const event = createPlanningObservationEvent("plan-obs-1"); const planPreviewEventIds = new Set(["plan-obs-1"]); const planContent = "This is the plan content"; useConversationStore.setState({ planContent }); renderWithProviders( , ); expect(screen.getByTestId("plan-preview")).toBeInTheDocument(); expect( screen.getByText(`Plan Preview: ${planContent}`), ).toBeInTheDocument(); }); it("should return null when PlanningFileEditorObservation event ID is NOT in planPreviewEventIds", () => { const event = createPlanningObservationEvent("plan-obs-1"); const planPreviewEventIds = new Set(["plan-obs-2"]); // Different ID const { container } = renderWithProviders( , ); expect(screen.queryByTestId("plan-preview")).not.toBeInTheDocument(); expect(container.firstChild).toBeNull(); }); it("should return null when planPreviewEventIds is undefined", () => { const event = createPlanningObservationEvent("plan-obs-1"); const { container } = renderWithProviders( , ); expect(screen.queryByTestId("plan-preview")).not.toBeInTheDocument(); expect(container.firstChild).toBeNull(); }); it("should use planContent from conversation store", () => { const event = createPlanningObservationEvent("plan-obs-1"); const planPreviewEventIds = new Set(["plan-obs-1"]); const planContent = "Store plan content"; useConversationStore.setState({ planContent }); renderWithProviders( , ); expect( screen.getByText(`Plan Preview: ${planContent}`), ).toBeInTheDocument(); }); it("should handle null planContent from store", () => { const event = createPlanningObservationEvent("plan-obs-1"); const planPreviewEventIds = new Set(["plan-obs-1"]); useConversationStore.setState({ planContent: null }); renderWithProviders( , ); expect(screen.getByTestId("plan-preview")).toBeInTheDocument(); expect(screen.getByText("Plan Preview: null")).toBeInTheDocument(); }); it("should handle empty planPreviewEventIds set", () => { const event = createPlanningObservationEvent("plan-obs-1"); const planPreviewEventIds = new Set(); const { container } = renderWithProviders( , ); expect(screen.queryByTestId("plan-preview")).not.toBeInTheDocument(); expect(container.firstChild).toBeNull(); }); describe("isStreaming prop", () => { it("should pass isStreaming=true when isLastMessage is true and agent state is RUNNING", () => { const event = createPlanningObservationEvent("plan-obs-1"); const planPreviewEventIds = new Set(["plan-obs-1"]); const planContent = "Streaming plan content"; useConversationStore.setState({ planContent }); vi.mocked(useAgentState).mockReturnValue({ curAgentState: AgentState.RUNNING, isArchived: false, }); renderWithProviders( , ); const planPreview = screen.getByTestId("plan-preview"); expect(planPreview).toBeInTheDocument(); expect(planPreview).toHaveAttribute("data-is-streaming", "true"); }); it("should pass isStreaming=false when isLastMessage is false even if agent is RUNNING", () => { const event = createPlanningObservationEvent("plan-obs-1"); const planPreviewEventIds = new Set(["plan-obs-1"]); const planContent = "Plan content"; useConversationStore.setState({ planContent }); vi.mocked(useAgentState).mockReturnValue({ curAgentState: AgentState.RUNNING, isArchived: false, }); renderWithProviders( , ); const planPreview = screen.getByTestId("plan-preview"); expect(planPreview).toBeInTheDocument(); expect(planPreview).toHaveAttribute("data-is-streaming", "false"); }); it("should pass isStreaming=false when agent state is not RUNNING even if isLastMessage is true", () => { const event = createPlanningObservationEvent("plan-obs-1"); const planPreviewEventIds = new Set(["plan-obs-1"]); const planContent = "Completed plan content"; useConversationStore.setState({ planContent }); vi.mocked(useAgentState).mockReturnValue({ curAgentState: AgentState.AWAITING_USER_INPUT, isArchived: false, }); renderWithProviders( , ); const planPreview = screen.getByTestId("plan-preview"); expect(planPreview).toBeInTheDocument(); expect(planPreview).toHaveAttribute("data-is-streaming", "false"); }); it("should pass isStreaming=false when agent state is FINISHED", () => { const event = createPlanningObservationEvent("plan-obs-1"); const planPreviewEventIds = new Set(["plan-obs-1"]); const planContent = "Finished plan content"; useConversationStore.setState({ planContent }); vi.mocked(useAgentState).mockReturnValue({ curAgentState: AgentState.FINISHED, isArchived: false, }); renderWithProviders( , ); const planPreview = screen.getByTestId("plan-preview"); expect(planPreview).toBeInTheDocument(); expect(planPreview).toHaveAttribute("data-is-streaming", "false"); }); }); });