import { EventEmitter } from 'events' import { processDownload } from '../processor' import { prisma } from '@/lib/prisma' import * as tokenLib from '@/lib/token' import * as cp from 'child_process' jest.mock('@/lib/prisma', () => ({ prisma: { download: { findUnique: jest.fn(), update: jest.fn() }, }, })) jest.mock('@/lib/token') jest.mock('child_process') jest.mock('fs', () => ({ existsSync: jest.fn(() => false), readdirSync: jest.fn(() => ['uuid-abc.mp4']), statSync: jest.fn(() => ({ size: 1024 })), })) const mockFindUnique = prisma.download.findUnique as jest.Mock const mockUpdate = prisma.download.update as jest.Mock const mockCreateToken = tokenLib.createToken as jest.Mock const mockSpawn = cp.spawn as jest.Mock const baseDownload = { id: 'dl-1', uuid: 'uuid-abc', url: 'https://youtube.com/watch?v=abc', format: 'mp4', quality: 'best', subtitles: false, extraArgs: null, } function makeChildProcess(exitCode: number, stderrMsg = '') { const proc = new EventEmitter() as any proc.stdout = new EventEmitter() proc.stderr = new EventEmitter() setImmediate(() => { if (stderrMsg) proc.stderr.emit('data', Buffer.from(stderrMsg)) proc.emit('close', exitCode) }) return proc } describe('processDownload', () => { beforeEach(() => { jest.clearAllMocks() mockFindUnique.mockResolvedValue(baseDownload) mockUpdate.mockResolvedValue({}) mockCreateToken.mockResolvedValue('new-token') }) it('marks download as DONE on yt-dlp exit code 0', async () => { mockSpawn.mockReturnValue(makeChildProcess(0)) await processDownload('dl-1') expect(mockUpdate).toHaveBeenCalledWith( expect.objectContaining({ where: { id: 'dl-1' }, data: expect.objectContaining({ status: 'DONE' }), }) ) }) it('creates a token on success', async () => { mockSpawn.mockReturnValue(makeChildProcess(0)) await processDownload('dl-1') expect(mockCreateToken).toHaveBeenCalledWith('dl-1') }) it('marks download as FAILED on non-zero exit code', async () => { mockSpawn.mockReturnValue(makeChildProcess(1, 'unsupported URL')) await processDownload('dl-1') expect(mockUpdate).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ status: 'FAILED', errorMsg: expect.stringContaining('unsupported URL'), }), }) ) }) it('does nothing when download not found', async () => { mockFindUnique.mockResolvedValue(null) await expect(processDownload('nonexistent')).resolves.toBeUndefined() expect(mockSpawn).not.toHaveBeenCalled() }) })