import { afterEach, describe, expect, it } from 'vitest'; import { YtDlpError, runYtDlp } from '../src/services/ytDlpRunner.js'; describe('runYtDlp', () => { afterEach(() => { // biome-ignore lint/performance/noDelete: une assignation à `undefined` stockerait la chaîne "undefined" dans process.env. delete process.env.YTDLP_PATH; }); it('retourne stdout quand le processus réussit', async () => { process.env.YTDLP_PATH = process.execPath; const stdout = await runYtDlp(['-e', "console.log('bonjour')"]); expect(stdout.trim()).toBe('bonjour'); }); it('lève YtDlpError quand le processus se termine en échec', async () => { process.env.YTDLP_PATH = process.execPath; await expect(runYtDlp(['-e', "console.error('boom'); process.exit(3)"])).rejects.toBeInstanceOf( YtDlpError, ); }); it('appelle onStdoutLine pour chaque ligne, sans attendre la fin du processus', async () => { process.env.YTDLP_PATH = process.execPath; const lines: string[] = []; await runYtDlp(['-e', "console.log('a'); console.log('b'); console.log('c')"], { onStdoutLine: (line) => lines.push(line), }); expect(lines).toEqual(['a', 'b', 'c']); }); it('émet le fragment final même sans saut de ligne terminal', async () => { process.env.YTDLP_PATH = process.execPath; const lines: string[] = []; await runYtDlp(['-e', "process.stdout.write('sans-newline')"], { onStdoutLine: (line) => lines.push(line), }); expect(lines).toEqual(['sans-newline']); }); it("rejette avec une AbortError quand le signal d'annulation se déclenche", async () => { process.env.YTDLP_PATH = process.execPath; const controller = new AbortController(); const promise = runYtDlp(['-e', 'setTimeout(() => {}, 5000)'], { signal: controller.signal }); controller.abort(); await expect(promise).rejects.toMatchObject({ name: 'AbortError' }); }); });