mcpField
A
api-testing

api-testing

github.com/motormetricsTesting & quality2280 installsUpdated today
Repository

About api-testing

An API-testing skill that documents Vitest commands and patterns for testing routes, query parameters, POST requests, and dependencies. It is aimed at developers testing web APIs with database, external API, and Redis mocks.

Key features

  1. 01Vitest test commands
  2. 02Route and HTTP response tests
  3. 03Query parameter and error tests
  4. 04Database and service mocking
  5. 05Coverage configuration guidance

Use cases

  1. 01Testing API route responses
  2. 02Checking invalid query parameters
  3. 03Testing POST endpoint behavior
  4. 04Isolating tests from external services

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/motormetrics/motormetrics --skill api-testing

After installing, type/api-testingin Claude Code to confirm it loaded.

Details

From the project README

API Testing Skill

Running Tests

pnpm test                  # Run all tests
pnpm test:watch            # Watch mode
pnpm test:coverage         # With coverage
pnpm -F @sgcarstrends/web test              # Run web tests
pnpm -F @sgcarstrends/web test:watch        # Watch mode for web

Test Structure

apps/web/__tests__/
├── setup.ts              # Test setup
├── helpers.ts            # Test utilities
├── queries/              # Query tests
├── components/           # Component tests
└── utils/                # Utility tests

Testing API Routes

Basic Endpoint Test
import { describe, it, expect } from "vitest";

describe("GET /api/health", () => {
  it("returns 200 OK", async () => {
    const res = await fetch("http://localhost:3000/api/health");
    expect(res.status).toBe(200);
    expect(await res.json()).toEqual({ status: "ok" });
  });
});
Testing with Query Params
describe("GET /api/cars", () => {
  it("filters by month", async () => {
    const res = await fetch("http://localhost:3000/api/cars?month=2024-01");
    expect(res.status).toBe(200);
  });

  it("returns 400 for invalid month", async () => {
    const res = await fetch("http://localhost:3000/api/cars?month=invalid");
    expect(res.status).toBe(400);
  });
});
Testing POST Endpoints
describe("POST /api/posts", () => {
  it("creates a new post", async () => {
    const res = await fetch("http://localhost:3000/api/posts", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ title: "Test", content: "Content" }),
    });
    expect(res.status).toBe(201);
  });
});

Mocking

Mock Database
import { vi } from "vitest";
import { db } from "../src/config/database";

vi.spyOn(db.query.cars, "findMany").mockResolvedValue([
  { make: "Toyota", model: "Corolla", number: 100 },
]);
Mock External APIs
const mockFetch = vi.fn().mockResolvedValue({
  ok: true,
  json: async () => ({ records: [] }),
});
global.fetch = mockFetch;
Mock Redis
vi.mock("@sgcarstrends/utils", () => ({
  redis: {
    get: vi.fn(),
    set: vi.fn(),
    del: vi.fn(),
  },
}));

Test Helpers

// apps/web/__tests__/helpers.ts
export const createAuthHeader = (token: string) => ({
  Authorization: `Bearer ${token}`,
});

export const seedDatabase = async (data: any[]) => {
  await db.insert(cars).values(data);
};

export const clearDatabase = async () => {
  await db.delete(cars);
};

Best Practices

  1. Isolate tests - Each test should be independent
  2. Test error cases - Test both happy and error paths
  3. Use mocks - Mock external dependencies
  4. Clean up - Reset state in afterEach
  5. Descriptive names - Clear test descriptions
  6. Coverage goals - Aim for 80%+ coverage

Coverage Configuration

// vitest.config.ts
export default defineConfig({
  test: {
    coverage: {
      provider: "v8",
      thresholds: { lines: 80, functions: 80, branches: 80 },
    },
  },
});

References

Comments

Markdown supported