test: add comprehensive MCP UI test coverage with MSW infrastructure
## MSW Infrastructure Enhancement - Add 5 MCP API handlers to tests/msw/handlers.ts: - get_mcp_config: Fetch MCP configuration for app type - import_mcp_from_claude/codex: Mock import operations (returns count: 1) - set_mcp_enabled: Toggle MCP server enabled state - upsert_mcp_server_in_config: Create/update MCP server - delete_mcp_server_in_config: Remove MCP server - Add MCP state management to tests/msw/state.ts: - McpConfigState type with per-app server storage - Default test data (stdio server for Claude, http server for Codex) - CRUD functions: getMcpConfig, setMcpServerEnabled, upsertMcpServer, deleteMcpServer - Immutable state operations with deep cloning ## McpFormModal Component Tests (4 tests) - Test preset application: Verify ID and config JSON auto-fill from preset selection - Test conflict detection: Async validation shows warning when syncing to conflicting ID - Test field sanitization: Verify trim whitespace, split tags, clean URLs before save - Test validation errors: Block submit and show toast error for invalid stdio config (missing command) ## McpPanel Integration Tests (3 tests) - Test toggle enabled state: Click toggle button triggers useMcpActions.toggleEnabled with correct params - Test create server flow: Open form → submit → saveServer called with syncOtherSide option - Test delete server flow: Click delete → confirm dialog → deleteServer called with ID ## Test Utilities - Add createTestQueryClient helper with retry: false for faster test execution ## Test Coverage - Test files: 15 → 17 (+2) - Total tests: 105 → 112 (+6.7%) - All 112 tests passing - Execution time: 3.15s
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import type { AppType } from "@/lib/api/types";
|
||||
import type { Provider, Settings } from "@/types";
|
||||
import type { McpServer, Provider, Settings } from "@/types";
|
||||
|
||||
type ProvidersByApp = Record<AppType, Record<string, Provider>>;
|
||||
type CurrentProviderState = Record<AppType, string>;
|
||||
type McpConfigState = Record<AppType, Record<string, McpServer>>;
|
||||
|
||||
const createDefaultProviders = (): ProvidersByApp => ({
|
||||
claude: {
|
||||
@@ -59,6 +60,30 @@ let settingsState: Settings = {
|
||||
language: "zh",
|
||||
};
|
||||
let appConfigDirOverride: string | null = null;
|
||||
let mcpConfigs: McpConfigState = {
|
||||
claude: {
|
||||
sample: {
|
||||
id: "sample",
|
||||
name: "Sample Claude Server",
|
||||
enabled: true,
|
||||
server: {
|
||||
type: "stdio",
|
||||
command: "claude-server",
|
||||
},
|
||||
},
|
||||
},
|
||||
codex: {
|
||||
httpServer: {
|
||||
id: "httpServer",
|
||||
name: "HTTP Codex Server",
|
||||
enabled: false,
|
||||
server: {
|
||||
type: "http",
|
||||
url: "http://localhost:3000",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const cloneProviders = (value: ProvidersByApp) =>
|
||||
JSON.parse(JSON.stringify(value)) as ProvidersByApp;
|
||||
@@ -75,6 +100,30 @@ export const resetProviderState = () => {
|
||||
language: "zh",
|
||||
};
|
||||
appConfigDirOverride = null;
|
||||
mcpConfigs = {
|
||||
claude: {
|
||||
sample: {
|
||||
id: "sample",
|
||||
name: "Sample Claude Server",
|
||||
enabled: true,
|
||||
server: {
|
||||
type: "stdio",
|
||||
command: "claude-server",
|
||||
},
|
||||
},
|
||||
},
|
||||
codex: {
|
||||
httpServer: {
|
||||
id: "httpServer",
|
||||
name: "HTTP Codex Server",
|
||||
enabled: false,
|
||||
server: {
|
||||
type: "http",
|
||||
url: "http://localhost:3000",
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const getProviders = (appType: AppType) =>
|
||||
@@ -143,3 +192,45 @@ export const getAppConfigDirOverride = () => appConfigDirOverride;
|
||||
export const setAppConfigDirOverrideState = (value: string | null) => {
|
||||
appConfigDirOverride = value;
|
||||
};
|
||||
|
||||
export const getMcpConfig = (appType: AppType) => {
|
||||
const servers = JSON.parse(
|
||||
JSON.stringify(mcpConfigs[appType] ?? {}),
|
||||
) as Record<string, McpServer>;
|
||||
return {
|
||||
configPath: `/mock/${appType}.mcp.json`,
|
||||
servers,
|
||||
};
|
||||
};
|
||||
|
||||
export const setMcpConfig = (appType: AppType, value: Record<string, McpServer>) => {
|
||||
mcpConfigs[appType] = JSON.parse(JSON.stringify(value)) as Record<string, McpServer>;
|
||||
};
|
||||
|
||||
export const setMcpServerEnabled = (
|
||||
appType: AppType,
|
||||
id: string,
|
||||
enabled: boolean,
|
||||
) => {
|
||||
if (!mcpConfigs[appType]?.[id]) return;
|
||||
mcpConfigs[appType][id] = {
|
||||
...mcpConfigs[appType][id],
|
||||
enabled,
|
||||
};
|
||||
};
|
||||
|
||||
export const upsertMcpServer = (
|
||||
appType: AppType,
|
||||
id: string,
|
||||
server: McpServer,
|
||||
) => {
|
||||
if (!mcpConfigs[appType]) {
|
||||
mcpConfigs[appType] = {};
|
||||
}
|
||||
mcpConfigs[appType][id] = JSON.parse(JSON.stringify(server)) as McpServer;
|
||||
};
|
||||
|
||||
export const deleteMcpServer = (appType: AppType, id: string) => {
|
||||
if (!mcpConfigs[appType]) return;
|
||||
delete mcpConfigs[appType][id];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user