Skip to main content
REST API

Buggy Bookings โ€” Find the Defects

RequestValidateHard

Description

A booking API whose documentation and behaviour disagree in five places. The job is not to automate it โ€” it is to prove what is wrong.

Test Scenario

// This challenge inverts the usual exercise: assert the API is WRONG.
// Five defects are reachable from a plain HTTP client. One is shown here.

// Defect: a record is lost between page 1 and page 2.
const seen = new Set();
let page = 1;

while (page <= 4) {
  const res = await request.get(`/api/v1/buggy/bookings?page=${page}&limit=3`);
  const body = await res.json();

  for (const booking of body.data) {
    seen.add(booking.id);
  }

  page++;
}

const total = (await (await request.get('/api/v1/buggy/bookings')).json()).meta.total;

// Walking every page should reach every record. It does not.
expect(seen.size).toBe(total);

// Defect: PUT reports success but drops one field.
const created = await (await request.post('/api/v1/buggy/bookings', {
  data: { name: 'Test User', email: 't@example.com', nights: 2, notes: 'original' },
})).json();

const put = await request.put(`/api/v1/buggy/bookings/${created.data.id}`, {
  data: { name: 'Test User', email: 't@example.com', nights: 2, notes: 'updated' },
});

// The write response says the change landed...
expect((await put.json()).data.notes).toBe('updated');

// ...but reading it back disagrees. Never assert on the write response alone.
const readBack = await (await request.get(`/api/v1/buggy/bookings/${created.data.id}`)).json();
expect(readBack.data.notes).toBe('updated');
Endpoint/api/v1/buggy/bookings

Testing Tips

  • โ€ขEvery happy-path test passes here โ€” start from the documented contract and look for where reality departs from it
  • โ€ขPaging is documented as 1-based and contiguous: walk every page and compare the union against total
  • โ€ขPUT is documented to replace the whole record โ€” never trust the write response, always read it back
  • โ€ขDELETE is documented as 204 and idempotent: check the status, and check what a second delete returns
  • โ€ขnights is documented as a positive integer โ€” try a string, a float and a boolean
  • โ€ขDELETE /api/v1/buggy/bookings?reset=true reseeds the store; the data also reseeds itself every 10 minutes
// Playwright API Testing - REST
import { test, expect } from '@playwright/test';
test('REST API request', async ({ request }) => {
const response = await request.get('/api/v1/resource');
expect(response.ok()).toBeTruthy();
expect(response.status()).toBe(200);
const data = await response.json();
expect(data).toBeDefined();
});

Challenge ID: rest-buggy-bookings

2 frameworks available

API Playground

Send requests and inspect responses

Endpoint: /api/v1/buggy/bookings

Press Enter to send