import { POST } from '../route' import { prisma } from '@/lib/prisma' import { downloadRateLimiter } from '@/lib/rate-limit' jest.mock('@/lib/prisma', () => ({ prisma: { download: { create: jest.fn() } }, })) jest.mock('@/lib/rate-limit', () => ({ downloadRateLimiter: { isLimited: jest.fn() }, })) const mockCreate = prisma.download.create as jest.Mock const mockIsLimited = downloadRateLimiter.isLimited as jest.Mock function req(body: object, ip = '1.2.3.4') { return new Request('http://localhost/api/downloads', { method: 'POST', headers: { 'content-type': 'application/json', 'x-forwarded-for': ip }, body: JSON.stringify(body), }) } describe('POST /api/downloads', () => { beforeEach(() => { mockIsLimited.mockReturnValue(false) mockCreate.mockResolvedValue({ uuid: 'test-uuid' }) }) it('returns 429 when rate limited', async () => { mockIsLimited.mockReturnValue(true) const res = await POST(req({ url: 'https://y.com', format: 'mp4', quality: 'best', subtitles: false })) expect(res.status).toBe(429) }) it('returns 400 when url is missing', async () => { const res = await POST(req({ format: 'mp4', quality: 'best', subtitles: false })) expect(res.status).toBe(400) }) it('returns 400 when format is missing', async () => { const res = await POST(req({ url: 'https://y.com', quality: 'best', subtitles: false })) expect(res.status).toBe(400) }) it('returns 400 when clipEnd is not greater than clipStart', async () => { const res = await POST(req({ url: 'https://y.com', format: 'mp4', quality: 'best', subtitles: false, clipStart: 30, clipEnd: 10, })) expect(res.status).toBe(400) }) it('returns 201 with uuid on success', async () => { const res = await POST(req({ url: 'https://youtube.com/watch?v=abc', format: 'mp4', quality: 'best', subtitles: false })) expect(res.status).toBe(201) expect(await res.json()).toEqual({ uuid: 'test-uuid' }) }) it('passes correct fields to prisma', async () => { await POST(req({ url: 'https://y.com/watch?v=x', format: 'mp3', quality: '720p', subtitles: true }, '9.9.9.9')) expect(mockCreate).toHaveBeenCalledWith({ data: expect.objectContaining({ url: 'https://y.com/watch?v=x', format: 'mp3', quality: '720p', subtitles: true, ipAddress: '9.9.9.9', }), }) }) it('stores subtitleLangs as a comma-joined string', async () => { await POST(req({ url: 'https://y.com', format: 'mp4', quality: 'best', subtitles: true, subtitleLangs: ['fr', 'en'], })) expect(mockCreate).toHaveBeenCalledWith({ data: expect.objectContaining({ subtitleLangs: 'fr,en' }), }) }) it('stores clip range and audio quality when provided', async () => { await POST(req({ url: 'https://y.com', format: 'mp3', quality: 'best', subtitles: false, clipStart: 10, clipEnd: 30, audioQuality: '192', })) expect(mockCreate).toHaveBeenCalledWith({ data: expect.objectContaining({ clipStart: 10, clipEnd: 30, audioQuality: '192' }), }) }) it('stores the video title when provided', async () => { await POST(req({ url: 'https://y.com', format: 'mp4', quality: 'best', subtitles: false, title: 'My Video', })) expect(mockCreate).toHaveBeenCalledWith({ data: expect.objectContaining({ title: 'My Video' }), }) }) it('stores a null title when not provided', async () => { await POST(req({ url: 'https://y.com', format: 'mp4', quality: 'best', subtitles: false })) expect(mockCreate).toHaveBeenCalledWith({ data: expect.objectContaining({ title: null }), }) }) })