// npx vitest run src/__tests__/App.spec.tsx import React from "react" import { render, screen, act, cleanup } from "@/utils/test-utils" import AppWithProviders from "../App" vi.mock("@src/utils/vscode", () => ({ vscode: { postMessage: vi.fn(), }, })) // Mock the ErrorBoundary component vi.mock("@src/components/ErrorBoundary", () => ({ __esModule: true, default: ({ children }: { children: React.ReactNode }) => <>{children}, })) // Mock the telemetry client vi.mock("@src/utils/TelemetryClient", () => ({ telemetryClient: { capture: vi.fn(), updateTelemetryState: vi.fn(), }, })) vi.mock("@src/components/chat/ChatView", () => ({ __esModule: true, default: function ChatView({ isHidden }: { isHidden: boolean }) { return (
Chat View
) }, })) vi.mock("@src/components/settings/SettingsView", () => ({ __esModule: true, default: function SettingsView({ onDone }: { onDone: () => void }) { return (
Settings View
) }, })) vi.mock("@src/components/history/HistoryView", () => ({ __esModule: true, default: function HistoryView({ onDone }: { onDone: () => void }) { return (
History View
) }, })) vi.mock("@src/components/mcp/McpView", () => ({ __esModule: true, default: function McpView({ onDone }: { onDone: () => void }) { return (
MCP View
) }, })) vi.mock("@src/components/modes/ModesView", () => ({ __esModule: true, default: function ModesView({ onDone }: { onDone: () => void }) { return (
Modes View
) }, })) vi.mock("@src/components/marketplace/MarketplaceView", () => ({ MarketplaceView: function MarketplaceView({ onDone }: { onDone: () => void }) { return (
Marketplace View
) }, })) vi.mock("@src/components/cloud/CloudView", () => ({ CloudView: function CloudView({ onDone }: { onDone: () => void }) { return (
Cloud View
) }, })) const mockUseExtensionState = vi.fn() // Mock the HumanRelayDialog component vi.mock("@src/components/human-relay/HumanRelayDialog", () => ({ HumanRelayDialog: ({ _children, isOpen, onClose }: any) => (
Human Relay Dialog
), })) // Mock i18next and react-i18next vi.mock("i18next", () => { const tFunction = (key: string) => key const i18n = { t: tFunction, use: () => i18n, init: () => Promise.resolve(tFunction), changeLanguage: vi.fn(() => Promise.resolve()), } return { default: i18n } }) vi.mock("react-i18next", () => { const tFunction = (key: string) => key return { withTranslation: () => (Component: any) => { const MockedComponent = (props: any) => { return } MockedComponent.displayName = `withTranslation(${Component.displayName || Component.name || "Component"})` return MockedComponent }, Trans: ({ children }: { children: React.ReactNode }) => <>{children}, useTranslation: () => { return { t: tFunction, i18n: { t: tFunction, changeLanguage: vi.fn(() => Promise.resolve()), }, } }, initReactI18next: { type: "3rdParty", init: vi.fn(), }, } }) // Mock TranslationProvider to pass through children vi.mock("@src/i18n/TranslationContext", () => { const tFunction = (key: string) => key return { __esModule: true, default: ({ children }: { children: React.ReactNode }) => <>{children}, useAppTranslation: () => ({ t: tFunction, i18n: { t: tFunction, changeLanguage: vi.fn(() => Promise.resolve()), }, }), } }) vi.mock("@src/context/ExtensionStateContext", () => ({ useExtensionState: () => mockUseExtensionState(), ExtensionStateContextProvider: ({ children }: { children: React.ReactNode }) => <>{children}, })) // Mock environment variables vi.mock("process.env", () => ({ NODE_ENV: "test", PKG_VERSION: "1.0.0-test", })) describe("App", () => { beforeEach(() => { vi.clearAllMocks() window.removeEventListener("message", () => {}) // Set up default mock return value mockUseExtensionState.mockReturnValue({ didHydrateState: true, showWelcome: false, shouldShowAnnouncement: false, experiments: {}, language: "en", }) }) afterEach(() => { cleanup() window.removeEventListener("message", () => {}) }) const triggerMessage = (action: string) => { const messageEvent = new MessageEvent("message", { data: { type: "action", action, }, }) window.dispatchEvent(messageEvent) } it("shows chat view by default", () => { render() const chatView = screen.getByTestId("chat-view") expect(chatView).toBeInTheDocument() expect(chatView.getAttribute("data-hidden")).toBe("false") }) it("switches to settings view when receiving settingsButtonClicked action", async () => { render() act(() => { triggerMessage("settingsButtonClicked") }) const settingsView = await screen.findByTestId("settings-view") expect(settingsView).toBeInTheDocument() const chatView = screen.getByTestId("chat-view") expect(chatView.getAttribute("data-hidden")).toBe("true") }) it("switches to history view when receiving historyButtonClicked action", async () => { render() act(() => { triggerMessage("historyButtonClicked") }) const historyView = await screen.findByTestId("history-view") expect(historyView).toBeInTheDocument() const chatView = screen.getByTestId("chat-view") expect(chatView.getAttribute("data-hidden")).toBe("true") }) it("switches to MCP view when receiving mcpButtonClicked action", async () => { render() act(() => { triggerMessage("mcpButtonClicked") }) const mcpView = await screen.findByTestId("mcp-view") expect(mcpView).toBeInTheDocument() const chatView = screen.getByTestId("chat-view") expect(chatView.getAttribute("data-hidden")).toBe("true") }) it("switches to prompts view when receiving promptsButtonClicked action", async () => { render() act(() => { triggerMessage("promptsButtonClicked") }) const promptsView = await screen.findByTestId("prompts-view") expect(promptsView).toBeInTheDocument() const chatView = screen.getByTestId("chat-view") expect(chatView.getAttribute("data-hidden")).toBe("true") }) it("returns to chat view when clicking done in settings view", async () => { render() act(() => { triggerMessage("settingsButtonClicked") }) const settingsView = await screen.findByTestId("settings-view") act(() => { settingsView.click() }) const chatView = screen.getByTestId("chat-view") expect(chatView.getAttribute("data-hidden")).toBe("false") expect(screen.queryByTestId("settings-view")).not.toBeInTheDocument() }) it.each(["history", "mcp", "prompts"])("returns to chat view when clicking done in %s view", async (view) => { render() act(() => { triggerMessage(`${view}ButtonClicked`) }) const viewElement = await screen.findByTestId(`${view}-view`) act(() => { viewElement.click() }) const chatView = screen.getByTestId("chat-view") expect(chatView.getAttribute("data-hidden")).toBe("false") expect(screen.queryByTestId(`${view}-view`)).not.toBeInTheDocument() }) it("switches to marketplace view when receiving marketplaceButtonClicked action", async () => { render() act(() => { triggerMessage("marketplaceButtonClicked") }) const marketplaceView = await screen.findByTestId("marketplace-view") expect(marketplaceView).toBeInTheDocument() const chatView = screen.getByTestId("chat-view") expect(chatView.getAttribute("data-hidden")).toBe("true") }) it("returns to chat view when clicking done in marketplace view", async () => { render() act(() => { triggerMessage("marketplaceButtonClicked") }) const marketplaceView = await screen.findByTestId("marketplace-view") act(() => { marketplaceView.click() }) const chatView = screen.getByTestId("chat-view") expect(chatView.getAttribute("data-hidden")).toBe("false") expect(screen.queryByTestId("marketplace-view")).not.toBeInTheDocument() }) })