---
phase: 18-api-route-tests
plan: 04
type: execute
---
Add tests for generate API route covering Replicate and fal.ai provider paths.
Purpose: Complete generate route test coverage with external provider mocking.
Output: Tests for /api/generate Replicate and fal.ai paths with mocked fetch calls.
~/.claude/get-shit-done/workflows/execute-phase.md
~/.claude/get-shit-done/templates/summary.md
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
**Route to test:**
@src/app/api/generate/route.ts
**Existing tests to extend:**
@src/app/api/generate/__tests__/route.test.ts
Task 1: Add generate route tests for Replicate provider
src/app/api/generate/__tests__/route.test.ts
Add tests for /api/generate route Replicate path to existing test file:
- POST: Generates image successfully via Replicate
- POST: Generates video successfully via Replicate
- POST: Returns 401 when Replicate API key missing
- POST: Handles rate limit (429) from Replicate
- POST: Handles prediction failure
- POST: Handles prediction timeout (5 min max)
- POST: Polls for prediction completion
- POST: Returns video URL for large videos (>20MB)
Mock global fetch for Replicate API calls:
```typescript
// Model info fetch
mockFetch.mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({
latest_version: { id: "version123", openapi_schema: {} },
}),
});
// Create prediction
mockFetch.mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({
id: "prediction123",
status: "starting",
}),
});
// Poll prediction (succeeded)
mockFetch.mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({
id: "prediction123",
status: "succeeded",
output: ["https://replicate.delivery/output.png"],
}),
});
// Fetch output media
mockFetch.mockResolvedValueOnce({
ok: true,
headers: new Headers({ "content-type": "image/png" }),
arrayBuffer: () => Promise.resolve(new ArrayBuffer(1024)),
});
```
Test X-Replicate-API-Key header is passed correctly.
Test dynamicInputs are passed to prediction input.
npm test -- src/app/api/generate/__tests__/route.test.ts --testNamePattern="Replicate"
Replicate provider tests pass covering success, polling, and error paths
Task 2: Add generate route tests for fal.ai provider
src/app/api/generate/__tests__/route.test.ts
Add tests for /api/generate route fal.ai path to existing test file:
- POST: Generates image successfully via fal.ai (images array response)
- POST: Generates video successfully via fal.ai (video object response)
- POST: Works without API key (fal.ai allows unauthenticated)
- POST: Handles rate limit (429) with and without key
- POST: Handles various response formats (image, images, video, output)
- POST: Returns video URL for large videos (>20MB)
- POST: Filters empty dynamicInputs values
Mock global fetch for fal.ai API calls:
```typescript
// Sync API call (fal.run)
mockFetch.mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({
images: [{ url: "https://fal.media/output.png" }],
}),
});
// Fetch output media
mockFetch.mockResolvedValueOnce({
ok: true,
headers: new Headers({ "content-type": "image/png" }),
arrayBuffer: () => Promise.resolve(new ArrayBuffer(1024)),
});
// Video response format
mockFetch.mockResolvedValueOnce({
ok: true,
json: () => Promise.resolve({
video: { url: "https://fal.media/output.mp4" },
}),
});
```
Test X-Fal-API-Key header is passed when provided.
Test getFalInputMapping schema parsing (via behavior).
npm test -- src/app/api/generate/__tests__/route.test.ts
All generate route tests pass covering all three providers
Before declaring plan complete:
- [ ] `npm test -- src/app/api/generate/__tests__/route.test.ts` passes
- [ ] Tests cover Replicate and fal.ai provider paths
- [ ] Polling logic tested for Replicate
- [ ] Various response formats tested for fal.ai
- [ ] No TypeScript errors
- All tasks completed
- All verification checks pass
- All three providers thoroughly tested
- Error handling tested for each provider