import { describe, it, expect, vi } from 'vitest'; import request from 'supertest'; import { EventEmitter } from 'node:events'; import { Readable } from 'node:stream'; // ensure end-to-end stream delivery const FIXTURE_PATH = new URL( '../fixtures/audio/minimal_sine.mp3', import.meta.url ).pathname; vi.mock('node:child_process', async () => { const actual = await vi.importActual( 'node:child_process' ); return { ...actual, spawn: (cmd: string, args: readonly string[], opts: unknown) => { // mock yt-dlp source stream if (cmd === 'yt-dlp') { return actual.spawn( 'cat', [FIXTURE_PATH], opts as Parameters[2] ); } return ( actual.spawn as unknown as ( c: string, a: readonly string[], o: unknown ) => unknown )(cmd, args, opts); }, }; }); vi.mock('../../src/services/extractors/youtube/index.js', () => ({ getInfo: vi.fn().mockResolvedValue({ type: 'video', id: 'happyDl12345', title: 'Happy Path Test', uploader: 'Test Uploader', webpageUrl: 'https://www.youtube.com/watch?v=happyDl12345', duration: 30, extractorKey: 'youtube', isJsInfo: true, isPartial: false, isFullData: true, formats: [ { formatId: '140', url: 'https://cdn.example.com/audio.m4a', extension: 'm4a', resolution: '128kbps', height: 0, vcodec: 'none', acodec: 'mp4a.40.2', isMuxed: false, isVideo: false, isAudio: true, }, ], audioFormats: [ { formatId: '140', url: 'https://cdn.example.com/audio.m4a', extension: 'm4a', quality: '128kbps', vcodec: 'none', acodec: 'mp4a.40.2', isAudio: true, }, ], }), getStream: vi .fn() .mockImplementation(() => Promise.resolve(EventEmitter as unknown as Readable) ), })); import app from '../../src/app.js'; describe('/convert — happy path', () => { it('returns 200 with audio Content-Type and a non-empty body', async () => { const targetUrl = 'https://www.youtube.com/watch?v=happyDl12345'; const res = await request(app) .get('/convert') .query({ url: targetUrl, format: 'm4a', formatId: '140', id: 'happyDlClient', token: 'happyDlClient', title: 'Happy Path Test', artist: 'Test Uploader', }) .buffer(true) .parse((res, callback) => { const chunks: Buffer[] = []; res.on('data', (chunk: Buffer) => chunks.push(chunk)); res.on('end', () => callback(null, Buffer.concat(chunks))); }); expect(res.status).toBe(200); // check for valid media type const contentType = res.headers['content-type'] || ''; expect(contentType).toMatch(/audio|video|octet-stream/u); // confirm attachment disposition header const disposition = res.headers['content-disposition'] || ''; expect(disposition).toContain('attachment'); // ensure body content received const body = res.body as Buffer; expect(body).toBeInstanceOf(Buffer); expect(body.length).toBeGreaterThan(1024); }, 30_000); it('rejects /convert with no url', async () => { const res = await request(app).get('/convert'); expect(res.status).toBe(400); }); });