Procedurally generates a radio weather report
at master 2.3 kB view raw
1import { Stitcher } from '../src/stitcher.js'; 2import { describe, expect, it, vi, beforeEach } from 'vitest'; 3import { EventEmitter } from 'events'; 4import { spawn } from 'child_process'; 5 6const mockChildProcess = new (class MockChildProcess 7 extends EventEmitter { 8 kill = vi.fn(() => { 9 return true; 10 }); 11})(); 12 13vi.mock('child_process', () => { 14 return { 15 spawn: vi.fn(() => mockChildProcess) 16 } 17}); 18 19describe('stitcher', () => { 20 21 beforeEach(() => { 22 vi.clearAllMocks(); 23 }); 24 25 it('passes the correct arguments to ffmpeg', async () => { 26 const p = Stitcher(['1.flac', 'dir/2.flac']); 27 mockChildProcess.emit('exit', 0, null); 28 await p; 29 expect(spawn).toBeCalledWith('ffmpeg', [ 30 "-i", 31 '1.flac', 32 '-i', 33 'dir/2.flac', 34 '-filter_complex', 35 '[0:a][1:a][2:a]concat=n=2:v=0:a=1[out]', 36 '-map', 37 '[out]', 38 '-ar', 39 '44100', 40 '-ac', 41 '2', 42 '-c:a', 43 'pcm_s16le', 44 'output.wav', 45 '-y' 46 ]); 47 }); 48 49 it('throws an error when ffmpeg fails', async () => { 50 const p = Stitcher(['sound.mp3']); 51 mockChildProcess.emit('exit', 1, null); 52 await expect(p).rejects.toThrow('exited with 1'); 53 expect(spawn).toBeCalledWith('ffmpeg', [ 54 "-i", 55 'sound.mp3', 56 '-filter_complex', 57 '[0:a][1:a][2:a]concat=n=1:v=0:a=1[out]', 58 '-map', 59 '[out]', 60 '-ar', 61 '44100', 62 '-ac', 63 '2', 64 '-c:a', 65 'pcm_s16le', 66 'output.wav', 67 '-y' 68 ]); 69 }); 70 71 it('throws an error when ffmpeg takes longer than expected', { timeout: 6000 }, async () => { 72 await expect(Stitcher(['in.wav'])).rejects.toThrow('timed out'); 73 expect(spawn).toBeCalledWith('ffmpeg', [ 74 "-i", 75 'in.wav', 76 '-filter_complex', 77 '[0:a][1:a][2:a]concat=n=1:v=0:a=1[out]', 78 '-map', 79 '[out]', 80 '-ar', 81 '44100', 82 '-ac', 83 '2', 84 '-c:a', 85 'pcm_s16le', 86 'output.wav', 87 '-y' 88 ]); 89 }); 90});