## McpFormModal Component Tests (+5 tests)
### Infrastructure Improvements
- Enhance McpWizardModal mock from null to functional mock with testable onApply callback
- Refactor renderForm helper to support custom onSave/onClose mock injection
- Add McpServer type import for type-safe test data
### New Test Cases
1. **Wizard Integration**: Verify wizard generates config and auto-fills ID + JSON fields
- Click "Use Wizard" → Apply → Form fields populated with wizard-id and config
- Uses act() wrapper for React 18 async state updates
2. **TOML Auto-extraction (Codex)**: Test TOML → JSON conversion with ID extraction
- Parse `[mcp.servers.demo]` → auto-fill ID as "demo"
- Verify server object correctly parsed from TOML format
- Codex-specific feature for config.toml compatibility
3. **TOML Validation Error**: Test missing required field handling
- TOML with type="stdio" but no command → block submit
- Display localized error toast: mcp.error.idRequired (3s duration)
4. **Edit Mode Immutability**: Verify ID field disabled during edit
- ID input has disabled attribute and keeps original value
- Config updates applied while enabled state preserved
- syncOtherSide defaults to false in edit mode
5. **Error Recovery**: Test save failure button state restoration
- Inject failing onSave mock → trigger error
- Verify toast error displays translated message
- Submit button disabled state resets to false for retry
## useMcpActions Hook Tests (+2 tests)
### New API Mocks
- Add syncEnabledToClaude and syncEnabledToCodex mock functions
### New Test Cases
1. **Backend Error Message Mapping**: Map Chinese error to i18n key
- Backend: "stdio 类型的 MCP 服务器必须包含 command 字段"
- Frontend: mcp.error.commandRequired (6s toast duration)
2. **Cross-app Sync Logic**: Verify conditional sync behavior
- claude → claude: setEnabled called, syncEnabledToClaude NOT called
- Validates sync only occurs when crossing app types
## Minor Changes
- McpPanel.test.tsx: Add trailing newline (formatter compliance)
## Test Coverage
- Test files: 17 (unchanged)
- Total tests: 112 → 119 (+7, +6.3%)
- Execution time: 3.20s
- All 119 tests passing ✅
Milestone Achievement: 100% Hooks Coverage 🎉
- Hooks coverage: 87.5% (7/8) → 100% (8/8)
- Total tests: 81 → 105 (+29.6%)
- MCP functionality: 0 → 24 tests
useMcpActions Tests (8 tests):
- Test server reload with loading state management
- Use deferred promise pattern to verify loading state transitions
- Verify intermediate loading=true state during async operation
- Verify error toast (duration: 6s) on reload failure
- Ensure loading returns to false after error
- Test optimistic toggle with rollback on failure
- Immediately update enabled flag before API confirmation
- Verify success toast messages for enable/disable
- Roll back state to original value on API failure
- Show error toast (duration: 6s) when toggle fails
- Test server save with list refresh
- Verify ID rewrite logic: saveServer(newId, {...input, id: oldId}) → {id: newId}
- Verify syncOtherSide option correctly propagated to API
- Refresh server list after successful save
- Propagate errors to caller while showing error toast
- Do not refresh list when save fails
- Test server delete with state management
- Verify deleteServerInConfig called with correct parameters
- Verify list refresh removes deleted server
- Show success toast (duration: 1.5s) on delete
- Keep state unchanged on delete failure
- Propagate error to caller with error toast
useMcpValidation Tests (16 tests):
- Test JSON validation (4 tests)
- Return empty string for blank/whitespace text
- Return "mcp.error.jsonInvalid" for parsing failures
- Reject non-object types (string, array)
- Accept valid object payloads
- Test TOML error formatting (2 tests)
- Map mustBeObject/parseError to "mcp.error.tomlInvalid"
- Append error details for unknown errors
- Test TOML config validation (5 tests)
- Propagate errors from validateToml utility
- Return "mcp.error.commandRequired" for stdio without command
- Return "mcp.wizard.urlRequired" for http without url
- Catch and format tomlToMcpServer exceptions
- Return empty string when validation passes
- Test JSON config validation (5 tests)
- Reject invalid JSON syntax
- Reject mcpServers array format (single object required)
- Require command field for stdio type servers
- Require url field for http type servers
- Accept valid server configurations
Technical Highlights:
- Deferred Promise Pattern: Precise async timing control
- Optimistic Updates: Test immediate feedback + rollback
- Error Propagation: Distinguish caller errors vs toast notifications
- i18n Validation: All validators return translation keys
- Factory Functions: Reusable test data builders
All tests passing: 105/105