import Fastify from 'fastify'; import { describe, expect, it, vi } from 'vitest'; vi.mock('../src/services/ytDlpRunner.js', async (importOriginal) => { const actual = await importOriginal(); return { ...actual, runYtDlp: vi.fn() }; }); import { channelRoutes } from '../src/routes/channel.js'; import { YtDlpError, runYtDlp } from '../src/services/ytDlpRunner.js'; describe('GET /api/channel', () => { it('retourne les vidéos correspondantes pour une chaîne valide', async () => { vi.mocked(runYtDlp).mockResolvedValue( JSON.stringify({ id: 'v1', title: 'Test video', url: 'https://youtu.be/v1' }), ); const app = Fastify(); await app.register(channelRoutes); const response = await app.inject({ method: 'GET', url: '/api/channel?channel=@test§ion=videos', }); expect(response.statusCode).toBe(200); expect(response.json()).toEqual({ videos: [ { id: 'v1', title: 'Test video', url: 'https://youtu.be/v1', thumbnailUrl: null, durationSeconds: null, uploadDate: null, }, ], }); }); it('renvoie 400 pour un identifiant de chaîne invalide', async () => { const app = Fastify(); await app.register(channelRoutes); const response = await app.inject({ method: 'GET', url: '/api/channel?channel=--exec' }); expect(response.statusCode).toBe(400); }); it('renvoie 400 si le paramètre channel est manquant (validation de schéma)', async () => { const app = Fastify(); await app.register(channelRoutes); const response = await app.inject({ method: 'GET', url: '/api/channel' }); expect(response.statusCode).toBe(400); }); it('renvoie 502 quand yt-dlp échoue avec un code de sortie non nul', async () => { vi.mocked(runYtDlp).mockRejectedValue(new YtDlpError(1, 'network error')); const app = Fastify(); await app.register(channelRoutes); const response = await app.inject({ method: 'GET', url: '/api/channel?channel=@test' }); expect(response.statusCode).toBe(502); }); it('renvoie 502 (pas 500) quand le binaire yt-dlp est introuvable (ENOENT)', async () => { // Node rejette avec une Error brute (pas une YtDlpError) quand le spawn // lui-même échoue - voir ytDlpRunner.ts, l'événement 'error' du child. const spawnError = Object.assign(new Error('spawn yt-dlp ENOENT'), { code: 'ENOENT' }); vi.mocked(runYtDlp).mockRejectedValue(spawnError); const app = Fastify(); await app.register(channelRoutes); const response = await app.inject({ method: 'GET', url: '/api/channel?channel=@test' }); expect(response.statusCode).toBe(502); }); });