|
1 | | -import { render, screen } from "@/utils/test-utils" |
2 | | -import userEvent from "@testing-library/user-event" |
3 | | - |
| 1 | +import { render, waitFor } from "@testing-library/react" |
| 2 | +import { vi, describe, it, expect, beforeEach } from "vitest" |
4 | 3 | import { MarketplaceView } from "../MarketplaceView" |
5 | 4 | import { MarketplaceViewStateManager } from "../MarketplaceViewStateManager" |
| 5 | +import { ExtensionStateContext } from "@/context/ExtensionStateContext" |
| 6 | +import { vscode } from "@/utils/vscode" |
6 | 7 |
|
| 8 | +// Mock vscode API |
7 | 9 | vi.mock("@/utils/vscode", () => ({ |
8 | 10 | vscode: { |
9 | 11 | postMessage: vi.fn(), |
10 | | - getState: vi.fn(() => ({})), |
11 | | - setState: vi.fn(), |
12 | 12 | }, |
13 | 13 | })) |
14 | 14 |
|
| 15 | +// Mock the translation hook |
15 | 16 | vi.mock("@/i18n/TranslationContext", () => ({ |
16 | 17 | useAppTranslation: () => ({ |
17 | 18 | t: (key: string) => key, |
18 | 19 | }), |
19 | 20 | })) |
20 | 21 |
|
21 | | -vi.mock("../useStateManager", () => ({ |
22 | | - useStateManager: () => [ |
23 | | - { |
24 | | - allItems: [], |
25 | | - displayItems: [], |
26 | | - isFetching: false, |
27 | | - activeTab: "mcp", |
28 | | - filters: { type: "", search: "", tags: [] }, |
29 | | - }, |
30 | | - { |
31 | | - transition: vi.fn(), |
32 | | - onStateChange: vi.fn(() => vi.fn()), |
33 | | - }, |
34 | | - ], |
35 | | -})) |
36 | | - |
37 | | -vi.mock("../MarketplaceListView", () => ({ |
38 | | - MarketplaceListView: ({ filterByType }: { filterByType: string }) => ( |
39 | | - <div data-testid="marketplace-list-view">MarketplaceListView - {filterByType}</div> |
40 | | - ), |
41 | | -})) |
42 | | - |
43 | | -// Mock Tab components to avoid ExtensionStateContext dependency |
44 | | -vi.mock("@/components/common/Tab", () => ({ |
45 | | - Tab: ({ children, ...props }: any) => <div {...props}>{children}</div>, |
46 | | - TabHeader: ({ children, ...props }: any) => <div {...props}>{children}</div>, |
47 | | - TabContent: ({ children, ...props }: any) => <div {...props}>{children}</div>, |
48 | | - TabList: ({ children, ...props }: any) => <div {...props}>{children}</div>, |
49 | | - TabTrigger: ({ children, ...props }: any) => <button {...props}>{children}</button>, |
50 | | -})) |
51 | | - |
52 | 22 | describe("MarketplaceView", () => { |
53 | | - const mockOnDone = vi.fn() |
54 | | - const mockStateManager = new MarketplaceViewStateManager() |
| 23 | + let stateManager: MarketplaceViewStateManager |
| 24 | + let mockExtensionState: any |
55 | 25 |
|
56 | 26 | beforeEach(() => { |
57 | 27 | vi.clearAllMocks() |
| 28 | + stateManager = new MarketplaceViewStateManager() |
| 29 | + |
| 30 | + // Initialize state manager with some test data |
| 31 | + stateManager.transition({ |
| 32 | + type: "FETCH_COMPLETE", |
| 33 | + payload: { |
| 34 | + items: [ |
| 35 | + { |
| 36 | + id: "test-mcp", |
| 37 | + name: "Test MCP", |
| 38 | + type: "mcp" as const, |
| 39 | + description: "Test MCP server", |
| 40 | + tags: ["test"], |
| 41 | + content: "Test content", |
| 42 | + url: "https://test.com", |
| 43 | + author: "Test Author", |
| 44 | + }, |
| 45 | + ], |
| 46 | + }, |
| 47 | + }) |
| 48 | + |
| 49 | + mockExtensionState = { |
| 50 | + organizationSettingsVersion: 1, |
| 51 | + // Add other required properties for the context |
| 52 | + didHydrateState: true, |
| 53 | + showWelcome: false, |
| 54 | + theme: {}, |
| 55 | + mcpServers: [], |
| 56 | + filePaths: [], |
| 57 | + openedTabs: [], |
| 58 | + commands: [], |
| 59 | + organizationAllowList: { allowAll: true, providers: {} }, |
| 60 | + cloudIsAuthenticated: false, |
| 61 | + sharingEnabled: false, |
| 62 | + hasOpenedModeSelector: false, |
| 63 | + setHasOpenedModeSelector: vi.fn(), |
| 64 | + alwaysAllowFollowupQuestions: false, |
| 65 | + setAlwaysAllowFollowupQuestions: vi.fn(), |
| 66 | + followupAutoApproveTimeoutMs: 60000, |
| 67 | + setFollowupAutoApproveTimeoutMs: vi.fn(), |
| 68 | + profileThresholds: {}, |
| 69 | + setProfileThresholds: vi.fn(), |
| 70 | + // ... other required context properties |
| 71 | + } |
58 | 72 | }) |
59 | 73 |
|
60 | | - it("renders without crashing", () => { |
61 | | - render(<MarketplaceView stateManager={mockStateManager} onDone={mockOnDone} />) |
62 | | - |
63 | | - expect(screen.getByText("marketplace:title")).toBeInTheDocument() |
64 | | - expect(screen.getByText("marketplace:done")).toBeInTheDocument() |
65 | | - }) |
66 | | - |
67 | | - it("calls onDone when Done button is clicked", async () => { |
68 | | - const user = userEvent.setup() |
69 | | - render(<MarketplaceView stateManager={mockStateManager} onDone={mockOnDone} />) |
70 | | - |
71 | | - await user.click(screen.getByText("marketplace:done")) |
72 | | - expect(mockOnDone).toHaveBeenCalledTimes(1) |
| 74 | + it("should trigger fetchMarketplaceData when organization settings version changes", async () => { |
| 75 | + const { rerender } = render( |
| 76 | + <ExtensionStateContext.Provider value={mockExtensionState}> |
| 77 | + <MarketplaceView stateManager={stateManager} /> |
| 78 | + </ExtensionStateContext.Provider>, |
| 79 | + ) |
| 80 | + |
| 81 | + // Initial render should not trigger fetch (version hasn't changed) |
| 82 | + expect(vscode.postMessage).not.toHaveBeenCalledWith({ |
| 83 | + type: "fetchMarketplaceData", |
| 84 | + }) |
| 85 | + |
| 86 | + // Update the organization settings version |
| 87 | + mockExtensionState = { |
| 88 | + ...mockExtensionState, |
| 89 | + organizationSettingsVersion: 2, |
| 90 | + } |
| 91 | + |
| 92 | + // Re-render with updated context |
| 93 | + rerender( |
| 94 | + <ExtensionStateContext.Provider value={mockExtensionState}> |
| 95 | + <MarketplaceView stateManager={stateManager} /> |
| 96 | + </ExtensionStateContext.Provider>, |
| 97 | + ) |
| 98 | + |
| 99 | + // Wait for the effect to run |
| 100 | + await waitFor(() => { |
| 101 | + expect(vscode.postMessage).toHaveBeenCalledWith({ |
| 102 | + type: "fetchMarketplaceData", |
| 103 | + }) |
| 104 | + }) |
73 | 105 | }) |
74 | 106 |
|
75 | | - it("renders tab buttons", () => { |
76 | | - render(<MarketplaceView stateManager={mockStateManager} onDone={mockOnDone} />) |
77 | | - |
78 | | - expect(screen.getByText("MCP")).toBeInTheDocument() |
79 | | - expect(screen.getByText("Modes")).toBeInTheDocument() |
| 107 | + it("should not trigger fetchMarketplaceData when organization settings version is undefined", async () => { |
| 108 | + // Start with undefined version |
| 109 | + mockExtensionState = { |
| 110 | + ...mockExtensionState, |
| 111 | + organizationSettingsVersion: undefined, |
| 112 | + } |
| 113 | + |
| 114 | + const { rerender } = render( |
| 115 | + <ExtensionStateContext.Provider value={mockExtensionState}> |
| 116 | + <MarketplaceView stateManager={stateManager} /> |
| 117 | + </ExtensionStateContext.Provider>, |
| 118 | + ) |
| 119 | + |
| 120 | + // Update to a defined version |
| 121 | + mockExtensionState = { |
| 122 | + ...mockExtensionState, |
| 123 | + organizationSettingsVersion: 1, |
| 124 | + } |
| 125 | + |
| 126 | + rerender( |
| 127 | + <ExtensionStateContext.Provider value={mockExtensionState}> |
| 128 | + <MarketplaceView stateManager={stateManager} /> |
| 129 | + </ExtensionStateContext.Provider>, |
| 130 | + ) |
| 131 | + |
| 132 | + // Should not trigger fetch when transitioning from undefined |
| 133 | + await waitFor(() => { |
| 134 | + expect(vscode.postMessage).not.toHaveBeenCalledWith({ |
| 135 | + type: "fetchMarketplaceData", |
| 136 | + }) |
| 137 | + }) |
80 | 138 | }) |
81 | 139 |
|
82 | | - it("renders MarketplaceListView", () => { |
83 | | - render(<MarketplaceView stateManager={mockStateManager} onDone={mockOnDone} />) |
84 | | - |
85 | | - expect(screen.getByTestId("marketplace-list-view")).toBeInTheDocument() |
| 140 | + it("should not trigger fetchMarketplaceData when organization settings version remains the same", async () => { |
| 141 | + const { rerender } = render( |
| 142 | + <ExtensionStateContext.Provider value={mockExtensionState}> |
| 143 | + <MarketplaceView stateManager={stateManager} /> |
| 144 | + </ExtensionStateContext.Provider>, |
| 145 | + ) |
| 146 | + |
| 147 | + // Re-render with same version |
| 148 | + rerender( |
| 149 | + <ExtensionStateContext.Provider value={mockExtensionState}> |
| 150 | + <MarketplaceView stateManager={stateManager} /> |
| 151 | + </ExtensionStateContext.Provider>, |
| 152 | + ) |
| 153 | + |
| 154 | + // Should not trigger fetch when version hasn't changed |
| 155 | + await waitFor(() => { |
| 156 | + expect(vscode.postMessage).not.toHaveBeenCalledWith({ |
| 157 | + type: "fetchMarketplaceData", |
| 158 | + }) |
| 159 | + }) |
86 | 160 | }) |
87 | 161 | }) |
0 commit comments