/** @jest-environment node */ import { createVideoTranscodeRecoveryScheduler, VIDEO_TRANSCODE_RECOVERY_INTERVAL_MS, } from '@/lib/video-transcode-recovery' describe('video transcode startup recovery scheduler', () => { beforeEach(() => { jest.useFakeTimers() }) afterEach(() => { jest.useRealTimers() }) test('创建后立即扫描,并按 60 秒周期继续扫描', async () => { const scan = jest.fn().mockResolvedValue(0) const scheduler = createVideoTranscodeRecoveryScheduler({ scan }) await scheduler.initial expect(scan).toHaveBeenCalledTimes(1) await jest.advanceTimersByTimeAsync(VIDEO_TRANSCODE_RECOVERY_INTERVAL_MS) expect(scan).toHaveBeenCalledTimes(2) scheduler.stop() }) test('本轮失败不会取消定时器,下一轮会重试', async () => { const onError = jest.fn() const scan = jest.fn() .mockRejectedValueOnce(new Error('database unavailable')) .mockResolvedValueOnce(2) const scheduler = createVideoTranscodeRecoveryScheduler({ scan, onError }) await expect(scheduler.initial).rejects.toThrow('database unavailable') expect(onError).toHaveBeenCalledTimes(1) await jest.advanceTimersByTimeAsync(VIDEO_TRANSCODE_RECOVERY_INTERVAL_MS) expect(scan).toHaveBeenCalledTimes(2) scheduler.stop() }) test('上一轮未结束时不启动重叠扫描', async () => { let release!: (value: number) => void const pending = new Promise((resolve) => { release = resolve }) const scan = jest.fn(() => pending) const scheduler = createVideoTranscodeRecoveryScheduler({ scan }) await jest.advanceTimersByTimeAsync(VIDEO_TRANSCODE_RECOVERY_INTERVAL_MS * 2) expect(scan).toHaveBeenCalledTimes(1) release(0) await scheduler.initial scheduler.stop() }) })