1.8 KiB
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