Skip to content

[P1] Improve E2E test coverage for API and WebSocket failures #172

Description

@frankbria

Problem

Recent production bugs were not caught by E2E tests because the tests verify DOM elements exist but don't verify underlying API/WebSocket calls succeed.

Bugs That Slipped Through

  1. agentAssignment.ts hardcoded wrong API URL (localhost:8002)

    • Used Vite-style window.VITE_API_URL instead of Next.js process.env.NEXT_PUBLIC_API_URL
    • Tests passed because agent panel renders with empty state on API failure
  2. WebSocket missing auth token

    • Frontend connected without ?token=... query parameter
    • Backend rejected with code 1008, but tests didn't detect rejection
    • Test assertion expect(messages.length).toBeGreaterThanOrEqual(0) accepts 0 messages

Root Causes

Gap Impact
Tests verify DOM exists, not API success Components render with empty state on API failure
Permissive assertions (>=0) Zero messages treated as success
No console error monitoring Network errors silently ignored
No WebSocket close code checking Auth rejection (1008) not detected

Proposed Improvements

1. Add Console Error Monitoring

// In test setup
test.beforeEach(async ({ page }) => {
  const errors: string[] = [];
  page.on('console', msg => {
    if (msg.type() === 'error') {
      errors.push(msg.text());
    }
  });
  
  // Store for later assertion
  (page as any).__consoleErrors = errors;
});

// In test teardown or assertion
test.afterEach(async ({ page }) => {
  const errors = (page as any).__consoleErrors || [];
  const criticalErrors = errors.filter(e => 
    e.includes('net::ERR_') || 
    e.includes('Failed to fetch') ||
    e.includes('WebSocket')
  );
  expect(criticalErrors).toHaveLength(0);
});

2. Verify API Responses, Not Just DOM

// Current (insufficient):
await expect(page.locator('[data-testid="agent-status-panel"]')).toBeVisible();

// Improved:
const response = await page.waitForResponse(r => 
  r.url().includes('/api/projects/') && r.url().includes('/agents')
);
expect(response.status()).toBe(200);
const data = await response.json();
// Verify we got actual data, not just an empty response

3. Verify WebSocket Connection Success

// Current (insufficient):
const ws = await page.waitForEvent('websocket');
expect(messages.length).toBeGreaterThanOrEqual(0); // Accepts 0!

// Improved:
const ws = await page.waitForEvent('websocket');
let closeCode: number | null = null;

ws.on('close', (code) => {
  closeCode = code;
});

// Wait for potential close
await page.waitForTimeout(2000);

// Verify connection stayed open (or closed gracefully, not with auth error)
if (closeCode !== null) {
  expect(closeCode).not.toBe(1008); // Auth required
  expect(closeCode).not.toBe(1003); // Unsupported data
}

// Verify we received at least a pong or subscribed message
expect(messages.some(m => 
  m.includes('pong') || m.includes('subscribed')
)).toBe(true);

4. Add Network Request Failure Detection

test.beforeEach(async ({ page }) => {
  const failedRequests: string[] = [];
  
  page.on('requestfailed', request => {
    failedRequests.push(`${request.url()} - ${request.failure()?.errorText}`);
  });
  
  (page as any).__failedRequests = failedRequests;
});

test.afterEach(async ({ page }) => {
  const failed = (page as any).__failedRequests || [];
  expect(failed).toHaveLength(0);
});

5. Ensure Environment Variable Consistency

Add a pre-test check that all API files use the same env var pattern:

# In CI pipeline
grep -r "localhost:800" web-ui/src --include="*.ts" --include="*.tsx" | \
  grep -v "process.env.NEXT_PUBLIC" && \
  echo "ERROR: Found hardcoded localhost URLs" && exit 1

Files to Update

  • tests/e2e/test_dashboard.spec.ts - Add API response verification
  • tests/e2e/test-utils.ts - Add console/network error monitoring helpers
  • tests/e2e/playwright.config.ts - Add global error monitoring setup
  • .github/workflows/deploy.yml - Add env var consistency check

Acceptance Criteria

  • Tests fail when API returns empty/error responses
  • Tests fail when WebSocket connection is rejected
  • Tests fail on console errors containing network failures
  • Tests fail on request failures (net::ERR_*)
  • CI checks for hardcoded localhost URLs in frontend code

Related Commits

  • eaae0da - Fixed agentAssignment.ts API URL
  • 5005e7e - Fixed WebSocket auth token

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1-high-betaHigh priority - should fix before beta for best experiencebugSomething isn't workingtesting

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions