Skip to main content
Documentation

Buggy API Reference

The Buggy API is intentionally unreliable. It has the same endpoints as V1 but introduces random failures, delays, and data inconsistencies. That includes task comments and label/search behaviour. Use it to practise writing resilient tests and error-handling strategies.

⚠️ Warning: This API deliberately returns wrong data, slow responses, and random errors. Do not use it as a stable data source β€” use it to test how your test suite handles flakiness.

Base URL

bash
https://api.testauto.app/api/buggy

No authentication required. Same endpoint paths as V1.

Known Bugs & Failure Modes

BugFrequencyDescription
πŸ’₯ 500 Internal Server Error~10%Random server crash on any endpoint
🐌 Slow response~15%2–5 second artificial delay
πŸ“¦ Missing fields~8%Response omits description or priority
πŸ”’ Wrong status code~5%Returns 200 instead of 201 on creation
πŸ“„ Pagination off-by-one~5%totalPages or currentPage is incorrect
πŸ“… Date format inconsistency~10%Mixes ISO 8601 and Unix timestamps
πŸ” Search case sensitivity~20%Search stops being case-insensitive

Endpoints

All V1 task endpoints are available under https://api.testauto.app/api/buggy:

  • GET /tasks
  • GET /tasks/{id}
  • POST /tasks
  • PUT /tasks/{id}
  • DELETE /tasks/{id}
  • POST /tasks/{id}/comments
  • PUT /tasks/{id}/comments/{commentId}
  • DELETE /tasks/{id}/comments/{commentId}
  • GET /tasks/summary

See the V1 reference for request/response schemas β€” they are the same when the Buggy API behaves correctly, including comment payloads shaped as {"text":"..."}.

Testing Strategies

Retry on Transient Failures

typescript
async function fetchWithRetry(url: string, maxRetries = 3): Promise<Response> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    const response = await fetch(url);
    if (response.ok) return response;

    console.warn(`Attempt ${attempt} failed with status ${response.status}`);
    if (attempt < maxRetries) {
      await new Promise(r => setTimeout(r, 1000 * attempt)); // exponential back-off
    }
  }
  throw new Error(`All ${maxRetries} attempts failed`);
}

// Usage
const response = await fetchWithRetry('https://api.testauto.app/api/buggy/tasks');

Timeout Handling

typescript
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5000); // 5 second timeout

try {
  const response = await fetch('https://api.testauto.app/api/buggy/tasks', {
    signal: controller.signal,
  });
  const data = await response.json();
  return data;
} catch (error) {
  if (error.name === 'AbortError') {
    console.error('Request timed out after 5 seconds');
  }
  throw error;
} finally {
  clearTimeout(timeoutId);
}

Validating Response Schema

typescript
test('task response always has required fields', async () => {
  // Run multiple times to catch intermittent missing-field bugs
  for (let i = 0; i < 10; i++) {
    const response = await fetch('https://api.testauto.app/api/buggy/tasks');
    if (!response.ok) continue; // skip 500 errors for this test

    const data = await response.json();
    for (const task of data.content) {
      expect(task.id).toBeDefined();
      expect(task.title).toBeDefined();
      expect(task.status).toMatch(/^(TODO|IN_PROGRESS|DONE)$/);
      expect(task.priority).toMatch(/^(LOW|MEDIUM|HIGH|URGENT)$/);
      // Note: description and other optional fields may sometimes be missing
    }
  }
});

Testing with Playwright β€” Ignoring Known Flakiness

typescript
import { test, expect } from '@playwright/test';

test('buggy API endpoint eventually succeeds', async ({ request }) => {
  let lastStatus = 0;

  // Retry up to 5 times
  for (let i = 0; i < 5; i++) {
    const response = await request.get('https://api.testauto.app/api/buggy/tasks');
    lastStatus = response.status();
    if (response.ok()) {
      const body = await response.json();
      expect(body.content).toBeInstanceOf(Array);
      return; // test passes
    }
    await new Promise(r => setTimeout(r, 1000));
  }

  throw new Error(`Buggy API never returned 200 after 5 retries (last: ${lastStatus})`);
});

What to Practise

  • βœ… Retry logic: Write tests that tolerate intermittent failures
  • βœ… Timeout handling: Detect and handle slow responses
  • βœ… Schema validation: Assert all expected fields are present
  • βœ… Status code range checks: Expect success within a retry window
  • βœ… Date format normalisation: Handle multiple date formats in the same field
  • βœ… Assertion resilience: Avoid false failures from known bugs