Skip to content

Latest commit

 

History

History
281 lines (231 loc) · 6.67 KB

TEST.md

File metadata and controls

281 lines (231 loc) · 6.67 KB

Test Organization

Quick Reference

Test Types & Locations

src/__tests__/
├── vitest/              # Integration tests (ESM)
│   ├── docs/           # Documentation tests
│   └── setup.ts        # Vitest setup
└── vscode/             # VS Code tests (CommonJS)
    ├── runTest.cts     # VS Code test runner
    └── suite/          # VS Code test suite
        ├── index.cts   # Test suite entry point
        └── *.test.cts  # Test files

Running Tests

pnpm test:vitest        # Run integration tests
pnpm test:vscode        # Run VS Code tests
pnpm test:all          # Run all tests

Module System Strategy

The project uses a mixed module system approach:

  1. Main Project (ESM)

    • Root package.json: "type": "module"
    • Modern ES modules for better tree-shaking
    • Used by Vitest tests and React components
  2. VS Code Extension (CommonJS)

    • VS Code API requires CommonJS
    • Extension code built with webpack (CommonJS output)
    • Test files use .cts extension
    • Single package.json in VS Code test directory

Test Environment Setup

Vitest Tests

  • Uses ESM (.ts files)
  • Configuration in vitest.config.ts:
    export default defineConfig({
      test: {
        testTimeout: 2000,    // 2s for tests
        hookTimeout: 2000,    // 2s for hooks
        teardownTimeout: 200, // 200ms for cleanup
        setupFiles: ['src/__tests__/vitest/setup.ts'],
        environment: 'node'
      }
    });
  • Test setup in setup.ts:
    • Starts MCP server
    • Sets up test workspace
    • Handles cleanup
  • No webpack involvement
  • Native ESM support

VS Code Tests

  • Uses CommonJS (.cts files)
  • Dedicated package.json with "type": "commonjs"
  • Configuration in src/__tests__/vscode/tsconfig.json:
    {
      "compilerOptions": {
        "module": "commonjs",
        "outDir": "../../../out/vscode-tests",
        "types": ["mocha", "node"]
      }
    }
  • Test runner in runTest.cts:
    • Uses @vscode/test-electron
    • Handles extension loading
    • Sets up test workspace
  • Direct TypeScript compilation
  • Fixed test port (54321)

Common Patterns

SSE Testing

// Setup connection
const eventSource = new EventSource(`${serverUrl}/sse`);

// Handle connection open
eventSource.onopen = () => {
  console.log('SSE connection established');
};

// Handle messages
eventSource.onmessage = (event) => {
  const message = JSON.parse(event.data);
  // Handle message
};

// Handle errors
eventSource.onerror = (error) => {
  console.error('SSE error:', error);
};

// Cleanup
eventSource.close();

VS Code Testing

// Get extension
const ext = vscode.extensions.getExtension('id');
await ext.activate();

// Test WebView
const panel = ext.exports.getWebviewPanel();
await panel.webview.postMessage({ type: 'TEST' });

// Wait for response
await new Promise<void>((resolve) => {
  panel.webview.onDidReceiveMessage(msg => {
    if (msg.type === 'RESPONSE') resolve();
  });
});

Best Practices

Module Imports

  • VS Code tests: Use relative paths (../../utils/logging)
  • Vitest tests: Can use path aliases
  • Keep imports consistent within each test suite
  • No path aliases in VS Code tests (makes debugging easier)

Test Organization

  • Keep tests close to implementation
  • Use appropriate module system per domain
  • Share utilities within module boundaries
  • Maintain clear separation of concerns

Test Cleanup

  1. Server Cleanup

    • Close SSE connections first
    • Wait for server to close
    • Close HTTP server
    • Clear test instances
  2. Resource Management

    • Dispose WebView panels
    • Clean test workspaces
    • Reset global state

Test Logging

// Enable test logging
setLogCallback((msg, type) => {
  console.log(`[${new Date().toISOString()}] ${msg}`);
});

// Log test steps
logStep('Test step description');
logSuccess('Test succeeded');

SSE Connection Management

Connection States

  1. Initial Connection

    • Timeout: 200ms
    • Retry attempts: 3
    • Backoff: 20ms
  2. Message Exchange

    • Timeout: 2000ms per message
    • Keep-alive interval: 20s
    • Ping/pong mechanism
  3. Reconnection

    • Max retries: 3
    • Backoff: Exponential (20ms, 200ms, 2000ms)
    • State preservation
  4. Cleanup

    • Grace period: 200ms
    • Force close: After 2000ms
    • Resource cleanup timeout: 20ms

Error Handling

  1. Connection Errors

    • Network issues
    • Invalid origin
    • Server unavailable
  2. Message Errors

    • Invalid format
    • Missing fields
    • Protocol violations
  3. State Errors

    • Connection lost
    • Server timeout
    • Client timeout

Testing Patterns

  1. Connection Testing

    it('should handle connection lifecycle', async () => {
      // Setup
      const eventSource = new EventSource(url);
      
      // Test phases
      await testConnection(eventSource);
      await testMessageExchange(eventSource);
      await testReconnection(eventSource);
      
      // Cleanup
      await gracefulClose(eventSource);
    });
  2. Error Testing

    it('should handle errors gracefully', async () => {
      const eventSource = new EventSource(url);
      
      // Test error scenarios
      await testNetworkError(eventSource);
      await testInvalidMessage(eventSource);
      await testTimeout(eventSource);
      
      // Verify cleanup
      await verifyCleanup(eventSource);
    });

Test Timeouts

All timeouts must follow these rules:

  1. Valid Values

    • Must be powers of 10 multiplied by 2: [2, 20, 200, 2000, 20000] ms
    • No timeout may exceed 20 seconds (20000ms)
    • Default timeouts:
      • Test timeout: 2000ms (2s)
      • Hook timeout: 2000ms (2s)
      • Teardown timeout: 200ms
      • Connection timeout: 200ms
      • Cleanup wait: 20ms
  2. Configuration Locations

    • Vitest: Global timeouts in vitest.config.ts
    • VS Code: Per-test timeouts in test files
    • Server operations: Constants in src/constants.ts
  3. Best Practices

    • Use smallest sufficient timeout value
    • Document timeout choices in comments
    • Use constants from TIMEOUTS object
    • Prefer event-based waiting over fixed timeouts

Troubleshooting

Common Issues

  1. Port Conflicts

    • VS Code tests use fixed port 54321
    • Other tests use random ports 54321-54421
    • Solution: Check lsof -i :54321 and kill processes
  2. SSE Connection Issues

    • Verify origin matches test environment
    • Check connection cleanup
    • Use test utilities for connections
    • Verify server state management
  3. State Management

    • Monitor connection states
    • Track message sequences
    • Verify cleanup completion
    • Check resource disposal