import { render, screen } from "@testing-library/react";
import { describe, it, expect, vi, beforeEach } from "vitest";
// Mutable mock state for controlling breakpoint
let mockIsMobile = false;
// Track ChatInterface unmount via vi.fn()
const chatInterfaceUnmount = vi.fn();
vi.mock("#/hooks/use-breakpoint", () => ({
useBreakpoint: () => mockIsMobile,
}));
vi.mock("#/hooks/use-resizable-panels", () => ({
useResizablePanels: () => ({
leftWidth: 50,
rightWidth: 50,
isDragging: false,
containerRef: { current: null },
handleMouseDown: vi.fn(),
}),
}));
vi.mock("#/stores/conversation-store", () => ({
useConversationStore: () => ({
isRightPanelShown: false,
}),
}));
// Mock ChatInterface with useEffect to track mount/unmount lifecycle
vi.mock("#/components/features/chat/chat-interface", () => {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const React = require("react");
return {
ChatInterface: () => {
React.useEffect(() => {
return () => chatInterfaceUnmount();
}, []);
return
Chat Interface
;
},
};
});
vi.mock(
"#/components/features/conversation/conversation-tabs/conversation-tab-content/conversation-tab-content",
() => ({
ConversationTabContent: () => ,
}),
);
import { ConversationMain } from "#/components/features/conversation/conversation-main/conversation-main";
describe("ConversationMain - Layout Transition Stability", () => {
beforeEach(() => {
mockIsMobile = false;
chatInterfaceUnmount.mockClear();
});
it("renders ChatInterface at desktop width", () => {
mockIsMobile = false;
render();
expect(screen.getByTestId("chat-interface")).toBeInTheDocument();
});
it("renders ChatInterface at mobile width", () => {
mockIsMobile = true;
render();
expect(screen.getByTestId("chat-interface")).toBeInTheDocument();
});
it("does not unmount ChatInterface when crossing from desktop to mobile", () => {
mockIsMobile = false;
const { rerender } = render();
expect(chatInterfaceUnmount).not.toHaveBeenCalled();
// Cross the breakpoint to mobile
mockIsMobile = true;
rerender();
// ChatInterface must NOT have been unmounted and remounted
expect(chatInterfaceUnmount).not.toHaveBeenCalled();
expect(screen.getByTestId("chat-interface")).toBeInTheDocument();
});
it("does not unmount ChatInterface when crossing from mobile to desktop", () => {
mockIsMobile = true;
const { rerender } = render();
expect(chatInterfaceUnmount).not.toHaveBeenCalled();
// Cross the breakpoint to desktop
mockIsMobile = false;
rerender();
// ChatInterface must NOT have been unmounted and remounted
expect(chatInterfaceUnmount).not.toHaveBeenCalled();
expect(screen.getByTestId("chat-interface")).toBeInTheDocument();
});
it("survives rapid back-and-forth resize without unmounting ChatInterface", () => {
mockIsMobile = false;
const { rerender } = render();
// Simulate rapid resize back and forth across the breakpoint
for (const mobile of [true, false, true, false, true]) {
mockIsMobile = mobile;
rerender();
}
expect(chatInterfaceUnmount).not.toHaveBeenCalled();
expect(screen.getByTestId("chat-interface")).toBeInTheDocument();
});
});