# Playwright API testing exercises: validate filtering and bad input

API tests can validate a contract before a browser UI is involved. This exercise checks every returned item, then proves that an invalid filter is rejected.

## Before you start

- Node.js and an existing Playwright Test project with @playwright/test installed.
- Save the example as tests/pizza-api.spec.js and run npx playwright test tests/pizza-api.spec.js.
- The examples send public GET requests. Each test creates a unique X-Sandbox-ID.

## Assert the filtered result and validation error

Add these two tests to your project. The request context is isolated from browser pages, and each test uses its own server sandbox.

```javascript
import { test, expect } from '@playwright/test';
import { randomUUID } from 'node:crypto';

test('vegetarian filter returns only vegetarian pizzas', async ({ request }) => {
  const response = await request.get('https://funapi.dev/api/pizza/v1/menu', {
    headers: { 'X-Sandbox-ID': randomUUID() },
    params: { vegetarian: 'true' }
  });
  expect(response.status()).toBe(200);
  const body = await response.json();
  expect(body.data.length).toBeGreaterThan(0);
  expect(body.total).toBe(body.data.length);
  for (const pizza of body.data) expect(pizza.vegetarian).toBe(true);
});

test('invalid filter is rejected', async ({ request }) => {
  const response = await request.get('https://funapi.dev/api/pizza/v1/menu', {
    headers: { 'X-Sandbox-ID': randomUUID() },
    params: { vegetarian: 'sometimes' }
  });
  expect(response.status()).toBe(400);
  expect((await response.json()).error).toBe('Bad Request');
});
```

## Inspect a deliberate server error

As a separate exploration, GET /api/pizza/v1/oven/status returns 500 by design. If you add a test for it, assert 500 explicitly rather than treating the training endpoint as an outage.


## Expected result

Two passing tests: 200 with a nonempty vegetarian result, and 400 for the invalid filter. No order is created.

## Common pitfalls

- Do not use response.ok() when the expected result is an intentional 400 or 500.
- A nonempty assertion prevents an empty list from incorrectly passing an every-item check.
- Do not assert a fixed latency against a public network service.
