DEV Community

TestDino
TestDino

Posted on

Playwright Mistake 8/14: You Only Check Status Codes on API Responses

The docs said the field was a string. Production returned null. Your test passed because you only asserted status === 200.

That's the problem.

What actually happened

The frontend called .toUpperCase() on null. Page crashed. Your test had no idea.

Checking the status code and calling it tested is like confirming the door is closed without checking if it's locked.

These two error messages tell the whole story

"Expected string, received null at 'name'" → 2-minute fix
"Cannot read properties of undefined"      → 2-hour debug
Enter fullscreen mode Exit fullscreen mode

One catches the issue at test time. The other catches it in production.

The fix: validate the response shape

// BEFORE
test('get user profile', async ({ request }) => {
  const response = await request.get('/api/users/123');
  await response.json();
  expect(response.status()).toBe(200);
  // Backend returns { name: null }. Test passes. Frontend breaks.
});
Enter fullscreen mode Exit fullscreen mode
// AFTER
import { z } from 'zod';

const UserSchema = z.object({
  id:        z.string().uuid(),
  name:      z.string(),
  email:     z.string().email(),
  role:      z.enum(['admin', 'member']),
  createdAt: z.string().datetime(),
});

test('get user profile - validate contract', async ({ request }) => {
  const response = await request.get('/api/users/123');
  expect(response.status()).toBe(200);

  const body   = await response.json();
  const result = UserSchema.safeParse(body);

  // name null?       Caught here.
  // field removed?   Caught here.
  // type changed?    Caught here.
  expect(result.success).toBe(true);
});

Enter fullscreen mode Exit fullscreen mode

Why it matters at scale

  • One method: safeParse covers every field in one call
  • Visible failure: tells you exactly which field broke and why
  • No prod surprises: field renames, null returns, type changes all fail at test time

When you have 200+ API tests only checking status codes, you have 200+ tests that can pass while the app is broken.

Tag someone who's still only asserting status codes.

Top comments (0)