import { buildYtdlpArgs } from '../ytdlp' const base = { url: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', uuid: 'abc-123', format: 'mp4', quality: 'best', subtitles: false, subtitleLangs: null, clipStart: null, clipEnd: null, audioQuality: null, extraArgs: null, } describe('buildYtdlpArgs', () => { it('always includes --no-playlist', () => { expect(buildYtdlpArgs(base)).toContain('--no-playlist') }) it('sets output path with uuid and %(ext)s template', () => { const args = buildYtdlpArgs(base) const idx = args.indexOf('-o') expect(idx).toBeGreaterThan(-1) expect(args[idx + 1]).toContain('abc-123') expect(args[idx + 1]).toContain('%(ext)s') }) it('always sets --merge-output-format to the chosen video format', () => { const args = buildYtdlpArgs(base) const idx = args.indexOf('--merge-output-format') expect(idx).toBeGreaterThan(-1) expect(args[idx + 1]).toBe('mp4') }) it('adds a height filter to -f when quality is not "best"', () => { const args = buildYtdlpArgs({ ...base, quality: '1080p' }) const idx = args.indexOf('-f') expect(idx).toBeGreaterThan(-1) expect(args[idx + 1]).toContain('height<=?1080') }) it('does not add a height filter when quality is "best"', () => { const args = buildYtdlpArgs(base) const idx = args.indexOf('-f') expect(args[idx + 1]).not.toContain('height<=?') }) it('extracts audio with -x and --audio-format when format is mp3', () => { const args = buildYtdlpArgs({ ...base, format: 'mp3' }) expect(args).toContain('-x') const idx = args.indexOf('--audio-format') expect(args[idx + 1]).toBe('mp3') expect(args).not.toContain('--merge-output-format') }) it('sets --audio-quality to 0 for best mp3 quality', () => { const args = buildYtdlpArgs({ ...base, format: 'mp3', audioQuality: 'best' }) const idx = args.indexOf('--audio-quality') expect(args[idx + 1]).toBe('0') }) it('sets --audio-quality to a bitrate when a specific mp3 quality is given', () => { const args = buildYtdlpArgs({ ...base, format: 'mp3', audioQuality: '192' }) const idx = args.indexOf('--audio-quality') expect(args[idx + 1]).toBe('192K') }) it('adds subtitle flags when subtitles is true', () => { const args = buildYtdlpArgs({ ...base, subtitles: true }) expect(args).toContain('--write-subs') expect(args).toContain('--write-auto-subs') expect(args).toContain('--sub-lang') }) it('does not add subtitle flags when subtitles is false', () => { expect(buildYtdlpArgs(base)).not.toContain('--write-subs') }) it('defaults subtitle languages to fr,en when none are given', () => { const args = buildYtdlpArgs({ ...base, subtitles: true }) const idx = args.indexOf('--sub-lang') expect(args[idx + 1]).toBe('fr,en') }) it('uses the given subtitle languages when provided', () => { const args = buildYtdlpArgs({ ...base, subtitles: true, subtitleLangs: ['es', 'it'] }) const idx = args.indexOf('--sub-lang') expect(args[idx + 1]).toBe('es,it') }) it('adds --download-sections when a clip range is given', () => { const args = buildYtdlpArgs({ ...base, clipStart: 10, clipEnd: 30 }) const idx = args.indexOf('--download-sections') expect(args[idx + 1]).toBe('*10-30') }) it('defaults clip start to 0 when only clipEnd is given', () => { const args = buildYtdlpArgs({ ...base, clipEnd: 30 }) const idx = args.indexOf('--download-sections') expect(args[idx + 1]).toBe('*0-30') }) it('leaves the clip end open when only clipStart is given', () => { const args = buildYtdlpArgs({ ...base, clipStart: 10 }) const idx = args.indexOf('--download-sections') expect(args[idx + 1]).toBe('*10-') }) it('does not add --download-sections when no clip range is given', () => { expect(buildYtdlpArgs(base)).not.toContain('--download-sections') }) it('appends extra args from a JSON array string', () => { const args = buildYtdlpArgs({ ...base, extraArgs: '["--sponsorblock-remove","all"]', }) expect(args).toContain('--sponsorblock-remove') expect(args).toContain('all') }) it('ignores malformed extraArgs JSON', () => { expect(() => buildYtdlpArgs({ ...base, extraArgs: 'not-json' }) ).not.toThrow() }) it('url is the last argument', () => { const args = buildYtdlpArgs(base) expect(args[args.length - 1]).toBe(base.url) }) })