Fuzz your API endpoints with random but valid inputs. Find edge cases, crashes, and 500 errors that manual testing misses.
## Task
API fuzzing with property-based testing to find edge cases and crashes.
## Requirements
- Framework: fast-check (property-based testing)
- HTTP client: built-in fetch or axios
- Language: TypeScript
## Test Strategy
```typescript
import fc from "fast-check";
describe("POST /api/users", () => {
// Property: API should never return 500 for any valid-shaped input
it("never crashes on valid input", async () => {
await fc.assert(
fc.asyncProperty(
fc.record({
name: fc.string({ minLength: 0, maxLength: 1000 }),
email: fc.emailAddress(),
age: fc.integer({ min: -1000, max: 1000 }),
bio: fc.option(fc.string({ maxLength: 10000 })),
}),
async (input) => {
const res = await fetch("/api/users", {
method: "POST",
body: JSON.stringify(input),
headers: { "Content-Type": "application/json" },
});
// Property: response is NEVER 500
expect(res.status).not.toBe(500);
// Property: invalid input returns 400, valid returns 201
if (res.status === 201) {
const body = await res.json();
expect(body.id).toBeDefined();
}
}
),
{ numRuns: 200 }
);
});
// Property: API is idempotent for same email
it("rejects duplicate emails consistently", async () => {
await fc.assert(
fc.asyncProperty(fc.emailAddress(), async (email) => {
// Create first
const r1 = await createUser({ name: "Test", email });
// Try duplicate
const r2 = await createUser({ name: "Test2", email });
if (r1.status === 201) {
expect(r2.status).toBe(409); // Conflict
}
})
);
});
});
```
## Fuzzing Strategies
```
1. Boundary values: 0, -1, MAX_INT, empty string, null
2. Unicode: emojis, RTL text, zero-width chars, SQL injection chars
3. Huge inputs: 1MB strings, arrays with 10K items
4. Type confusion: number where string expected, array where object expected
5. Missing fields: every combination of optional fields
6. Content-Type mismatch: send XML with JSON content-type
```
## Implementation Notes
1. Run against a test/staging environment — never production
2. Seed the random generator for reproducible failures
3. fast-check shrinking: when a failure is found, it minimizes the input
4. Log the exact failing input for reproduction
5. CI: run 100 iterations on PRs, 1000 nightly
6. Track: database of all unique failure patterns foundNo gallery images yet.