test(frontend/copilot): add CopilotPage banner coverage for sessionDryRun

Adds integration tests that verify the test-mode banner renders only
when both sessionId and sessionDryRun are truthy, covering the new
conditional introduced in the PR to prevent stale-preference banners.
This commit is contained in:
majdyz
2026-04-15 19:52:44 +07:00
parent f72bddb51e
commit 66cda847c7

View File

@@ -0,0 +1,168 @@
import { render, screen, cleanup } from "@/tests/integrations/test-utils";
import { afterEach, describe, expect, it, vi } from "vitest";
import { CopilotPage } from "../CopilotPage";
// Mock child components that are complex and not under test here
vi.mock("../components/ChatContainer/ChatContainer", () => ({
ChatContainer: () => <div data-testid="chat-container" />,
}));
vi.mock("../components/ChatSidebar/ChatSidebar", () => ({
ChatSidebar: () => <div data-testid="chat-sidebar" />,
}));
vi.mock("../components/DeleteChatDialog/DeleteChatDialog", () => ({
DeleteChatDialog: () => null,
}));
vi.mock("../components/MobileDrawer/MobileDrawer", () => ({
MobileDrawer: () => null,
}));
vi.mock("../components/MobileHeader/MobileHeader", () => ({
MobileHeader: () => null,
}));
vi.mock("../components/NotificationBanner/NotificationBanner", () => ({
NotificationBanner: () => null,
}));
vi.mock("../components/NotificationDialog/NotificationDialog", () => ({
NotificationDialog: () => null,
}));
vi.mock("../components/RateLimitResetDialog/RateLimitResetDialog", () => ({
RateLimitResetDialog: () => null,
}));
vi.mock("../components/ScaleLoader/ScaleLoader", () => ({
ScaleLoader: () => <div data-testid="scale-loader" />,
}));
vi.mock("../components/ArtifactPanel/ArtifactPanel", () => ({
ArtifactPanel: () => null,
}));
vi.mock("@/components/ui/sidebar", () => ({
SidebarProvider: ({ children }: { children: React.ReactNode }) => (
<div>{children}</div>
),
}));
// Mock hooks that hit the network
vi.mock("@/app/api/__generated__/endpoints/chat/chat", () => ({
useGetV2GetCopilotUsage: () => ({
data: undefined,
isSuccess: false,
isError: false,
}),
}));
vi.mock("@/hooks/useCredits", () => ({
default: () => ({ credits: null, fetchCredits: vi.fn() }),
}));
vi.mock("@/services/feature-flags/use-get-flag", () => ({
Flag: {
ENABLE_PLATFORM_PAYMENT: "ENABLE_PLATFORM_PAYMENT",
ARTIFACTS: "ARTIFACTS",
CHAT_MODE_OPTION: "CHAT_MODE_OPTION",
},
useGetFlag: () => false,
}));
// Build the base mock return value for useCopilotPage
const basePageState = {
sessionId: null as string | null,
messages: [],
status: "ready" as const,
error: undefined,
stop: vi.fn(),
isReconnecting: false,
isSyncing: false,
createSession: vi.fn(),
onSend: vi.fn(),
isLoadingSession: false,
isSessionError: false,
isCreatingSession: false,
isUploadingFiles: false,
isUserLoading: false,
isLoggedIn: true,
hasMoreMessages: false,
isLoadingMore: false,
loadMore: vi.fn(),
isMobile: false,
isDrawerOpen: false,
sessions: [],
isLoadingSessions: false,
handleOpenDrawer: vi.fn(),
handleCloseDrawer: vi.fn(),
handleDrawerOpenChange: vi.fn(),
handleSelectSession: vi.fn(),
handleNewChat: vi.fn(),
sessionToDelete: null,
isDeleting: false,
handleConfirmDelete: vi.fn(),
handleCancelDelete: vi.fn(),
historicalDurations: {},
rateLimitMessage: null,
dismissRateLimit: vi.fn(),
isDryRun: false,
sessionDryRun: false,
};
const mockUseCopilotPage = vi.fn(() => basePageState);
vi.mock("../useCopilotPage", () => ({
useCopilotPage: () => mockUseCopilotPage(),
}));
afterEach(() => {
cleanup();
mockUseCopilotPage.mockReset();
mockUseCopilotPage.mockImplementation(() => basePageState);
});
describe("CopilotPage test-mode banner", () => {
it("does not show test-mode banner when there is no active session", () => {
render(<CopilotPage />);
expect(
screen.queryByText(/test mode.*this session runs agents/i),
).toBeNull();
});
it("does not show test-mode banner when session exists but sessionDryRun is false", () => {
mockUseCopilotPage.mockReturnValue({
...basePageState,
sessionId: "session-abc",
sessionDryRun: false,
});
render(<CopilotPage />);
expect(
screen.queryByText(/test mode.*this session runs agents/i),
).toBeNull();
});
it("shows test-mode banner when session exists and sessionDryRun is true", () => {
mockUseCopilotPage.mockReturnValue({
...basePageState,
sessionId: "session-abc",
sessionDryRun: true,
});
render(<CopilotPage />);
expect(
screen.getByText(/test mode.*this session runs agents/i),
).toBeDefined();
});
it("does not show test-mode banner when sessionDryRun is true but no sessionId", () => {
mockUseCopilotPage.mockReturnValue({
...basePageState,
sessionId: null,
sessionDryRun: true,
});
render(<CopilotPage />);
expect(
screen.queryByText(/test mode.*this session runs agents/i),
).toBeNull();
});
it("shows loading spinner when user is loading", () => {
mockUseCopilotPage.mockReturnValue({
...basePageState,
isUserLoading: true,
isLoggedIn: false,
});
render(<CopilotPage />);
expect(screen.getByTestId("scale-loader")).toBeDefined();
expect(screen.queryByTestId("chat-container")).toBeNull();
});
});