api-testing

Expert knowledge for testing HTTP APIs with Supertest (TypeScript/JavaScript) and httpx/pytest (Python).

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "api-testing" with this command: npx skills add secondsky/claude-skills/secondsky-claude-skills-api-testing

API Testing

Expert knowledge for testing HTTP APIs with Supertest (TypeScript/JavaScript) and httpx/pytest (Python).

TypeScript/JavaScript (Supertest)

Installation

Using Bun

bun add -d supertest @types/supertest

or: npm install -D supertest @types/supertest

Basic Setup

import { describe, it, expect } from 'vitest' import request from 'supertest' import { app } from './app'

describe('API Tests', () => { it('returns health status', async () => { const response = await request(app) .get('/api/health') .expect(200)

expect(response.body).toEqual({ status: 'ok' })

})

it('creates a user', async () => { const response = await request(app) .post('/api/users') .send({ name: 'John Doe', email: 'john@example.com' }) .expect(201)

expect(response.body).toMatchObject({
  id: expect.any(Number),
  name: 'John Doe',
})

})

it('validates required fields', async () => { await request(app) .post('/api/users') .send({ name: 'John Doe' }) .expect(400) }) })

Request Methods

// GET await request(app).get('/api/users').expect(200)

// POST with body await request(app) .post('/api/users') .send({ name: 'John' }) .expect(201)

// PUT await request(app) .put('/api/users/1') .send({ name: 'Jane' }) .expect(200)

// DELETE await request(app).delete('/api/users/1').expect(204)

Headers and Query Parameters

// Set headers await request(app) .get('/api/protected') .set('Authorization', 'Bearer token123') .expect(200)

// Query parameters await request(app) .get('/api/users') .query({ page: 1, limit: 10 }) .expect(200)

Authentication Testing

describe('Authentication', () => { let authToken: string

beforeAll(async () => { const response = await request(app) .post('/api/auth/login') .send({ email: 'user@example.com', password: 'password123' }) .expect(200)

authToken = response.body.token

})

it('accesses protected endpoint', async () => { await request(app) .get('/api/protected') .set('Authorization', Bearer ${authToken}) .expect(200) })

it('rejects without token', async () => { await request(app).get('/api/protected').expect(401) }) })

Error Handling

it('handles validation errors', async () => { const response = await request(app) .post('/api/users') .send({ email: 'invalid-email' }) .expect(400)

expect(response.body).toMatchObject({ error: 'Validation failed', details: expect.any(Array), }) })

it('handles not found', async () => { await request(app).get('/api/users/999999').expect(404) })

Python (httpx + pytest)

Installation

uv add --dev httpx pytest-asyncio

Basic Setup

import pytest from fastapi.testclient import TestClient from main import app

client = TestClient(app)

def test_health_check(): response = client.get("/api/health") assert response.status_code == 200 assert response.json() == {"status": "ok"}

def test_create_user(): response = client.post( "/api/users", json={"name": "John Doe", "email": "john@example.com"} ) assert response.status_code == 201 data = response.json() assert data["name"] == "John Doe" assert "id" in data

def test_not_found(): response = client.get("/api/users/999") assert response.status_code == 404

Fixtures

@pytest.fixture def auth_token(client): response = client.post( "/api/auth/login", json={"email": "user@example.com", "password": "password123"} ) return response.json()["token"]

def test_protected_endpoint(client, auth_token): response = client.get( "/api/protected", headers={"Authorization": f"Bearer {auth_token}"} ) assert response.status_code == 200

File Upload

def test_file_upload(client, tmp_path): test_file = tmp_path / "test.txt" test_file.write_text("test content")

with open(test_file, "rb") as f:
    response = client.post(
        "/api/upload",
        files={"file": ("test.txt", f, "text/plain")}
    )

assert response.status_code == 200

GraphQL Testing

it('queries GraphQL endpoint', async () => { const query = query GetUser($id: ID!) { user(id: $id) { id name email } }

const response = await request(app) .post('/graphql') .send({ query, variables: { id: '1' } }) .expect(200)

expect(response.body.data.user).toMatchObject({ id: '1', name: expect.any(String), }) })

Performance Testing

it('responds within acceptable time', async () => { const start = Date.now() await request(app).get('/api/users').expect(200) const duration = Date.now() - start expect(duration).toBeLessThan(100) // 100ms threshold })

Best Practices

  • Group related endpoints in describe blocks

  • Reset database between tests

  • Validate status codes first

  • Check response structure

  • Test error message format

  • Mock external services

  • Test both happy path and error cases

See Also

  • vitest-testing

  • Unit testing framework

  • playwright-testing

  • E2E API testing

  • test-quality-analysis

  • Test quality patterns

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

code-review

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

claude-code-bash-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

chrome-devtools

No summary provided by upstream source.

Repository SourceNeeds Review