Files
2026-04-12 01:06:31 +07:00

1.8 KiB

API Testing

Supertest (Jest/Vitest)

import request from 'supertest';
import app from './app';

describe('POST /users', () => {
  it('creates user with valid data', async () => {
    const res = await request(app)
      .post('/users')
      .send({ email: 'test@example.com', password: 'secret123' });

    expect(res.status).toBe(201);
    expect(res.body.id).toBeDefined();
  });

  it('rejects duplicate email', async () => {
    await request(app).post('/users').send({ email: 'dup@example.com' });
    const res = await request(app).post('/users').send({ email: 'dup@example.com' });
    expect(res.status).toBe(409);
  });

  it('requires authentication', async () => {
    const res = await request(app).get('/protected');
    expect(res.status).toBe(401);
  });
});

API Checklist

Authentication

  • Valid credentials return 200 + token
  • Invalid credentials return 401
  • Missing/expired token returns 401

Authorization

  • User accesses own resources
  • Cannot access others' resources (403)

Input Validation

  • Missing required fields → 400
  • Invalid types → 400
  • SQL/XSS payloads rejected

Response

  • Correct status codes
  • Schema matches docs
  • Error messages helpful

Rate Limiting

  • Rate limit headers present
  • 429 when limit exceeded

Postman Tests

pm.test("Status 200", () => pm.response.to.have.status(200));
pm.test("Has user ID", () => {
  pm.expect(pm.response.json().id).to.be.a('number');
});

GraphQL Testing

const query = `query { users { id email } }`;
const res = await request(app).post('/graphql').send({ query });
expect(res.body.data.users).toHaveLength(2);

Contract Testing

npx dredd api.yaml http://localhost:3000