From 64ba063b0f7d127f230dcd8f50debbf1abbaeb2c Mon Sep 17 00:00:00 2001 From: Giancarmine Salucci Date: Thu, 9 Jul 2026 05:26:23 +0200 Subject: [PATCH] Fix D5 downloader test mocks: execFile args pass (cmd, args[], cb) not flat list --- src/tests/downloader.test.ts | 49 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/src/tests/downloader.test.ts b/src/tests/downloader.test.ts index 60ad143..a885069 100644 --- a/src/tests/downloader.test.ts +++ b/src/tests/downloader.test.ts @@ -2,13 +2,17 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; import { rm } from 'fs/promises'; import type { TranscriptResponse } from 'youtube-transcript'; -const { mockExecFile, mockFetchTranscript } = vi.hoisted(() => ({ - mockExecFile: vi.fn(), - mockFetchTranscript: vi.fn() -})); - -const TEST_DATA_DIR = `/tmp/tonemark-downloader-test-${Date.now()}`; -vi.stubEnv('DATA_DIR', TEST_DATA_DIR); +const { mockExecFile, mockFetchTranscript, TEST_DATA_DIR } = vi.hoisted(() => { + const dir = `/tmp/tonemark-downloader-test-${Date.now()}`; + // Set DATA_DIR before any import evaluation so that the module-level + // DATA_DIR constant in data-dir.ts picks up the test temp dir. + process.env.DATA_DIR = dir; + return { + mockExecFile: vi.fn(), + mockFetchTranscript: vi.fn(), + TEST_DATA_DIR: dir + }; +}); vi.mock('child_process', () => ({ execFile: mockExecFile @@ -137,13 +141,13 @@ describe('downloadYouTube', () => { describe('empty captions fallback (D5)', () => { it('falls back to audio when fetchTranscript returns empty segments array', async () => { mockFetchTranscript.mockResolvedValue([] satisfies TranscriptResponse[]); - mockExecFile.mockImplementation((...args: unknown[]) => { - const allArgs = args.slice(0, -1) as string[]; + mockExecFile.mockImplementation(function ytdlpMock(...args: unknown[]) { + const cmd = args[0] as string; + const cmdArgs = args[1] as string[]; const cb = args.at(-1) as (...callbackArgs: unknown[]) => void; - // downloadAudio: yt-dlp -f bestaudio [...] - if (allArgs.includes('-f')) { - const oIdx = allArgs.indexOf('-o'); - const outPattern = oIdx !== -1 ? allArgs[oIdx + 1] : ''; + if (cmd === 'yt-dlp' && cmdArgs.includes('-f')) { + const oIdx = cmdArgs.indexOf('-o'); + const outPattern = oIdx !== -1 ? cmdArgs[oIdx + 1] : ''; const outDir = outPattern ? outPattern.substring(0, outPattern.lastIndexOf('/')) : ''; if (outDir) { const { mkdirSync, writeFileSync } = require('fs'); @@ -154,12 +158,8 @@ describe('empty captions fallback (D5)', () => { } cb(null, JSON.stringify({ title: 'Empty Captions Video' }), ''); }); - const result = await downloadYouTube('https://youtube.com/watch?v=empty', 'test-empty-1'); - - expect(mockFetchTranscript).toHaveBeenCalledWith('https://youtube.com/watch?v=empty', { - lang: 'en' - }); + expect(mockFetchTranscript).toHaveBeenCalledWith('https://youtube.com/watch?v=empty', { lang: 'en' }); expect(result.type).toBe('audio'); expect(result.title).toBe('Empty Captions Video'); }); @@ -169,12 +169,13 @@ describe('empty captions fallback (D5)', () => { { text: ' ', offset: 1000, duration: 2000, lang: 'en' }, { text: ' ', offset: 3000, duration: 1000, lang: 'en' } ] satisfies TranscriptResponse[]); - mockExecFile.mockImplementation((...args: unknown[]) => { - const allArgs = args.slice(0, -1) as string[]; + mockExecFile.mockImplementation(function ytdlpMock(...args: unknown[]) { + const cmd = args[0] as string; + const cmdArgs = args[1] as string[]; const cb = args.at(-1) as (...callbackArgs: unknown[]) => void; - if (allArgs.includes('-f')) { - const oIdx = allArgs.indexOf('-o'); - const outPattern = oIdx !== -1 ? allArgs[oIdx + 1] : ''; + if (cmd === 'yt-dlp' && cmdArgs.includes('-f')) { + const oIdx = cmdArgs.indexOf('-o'); + const outPattern = oIdx !== -1 ? cmdArgs[oIdx + 1] : ''; const outDir = outPattern ? outPattern.substring(0, outPattern.lastIndexOf('/')) : ''; if (outDir) { const { mkdirSync, writeFileSync } = require('fs'); @@ -185,9 +186,7 @@ describe('empty captions fallback (D5)', () => { } cb(null, JSON.stringify({ title: 'Whitespace Only' }), ''); }); - const result = await downloadYouTube('https://youtube.com/watch?v=ws-only', 'test-empty-2'); - expect(result.type).toBe('audio'); });