const { test } = require('node:test'); const assert = require('node:assert'); const { partitionRestoredJobsByLog } = require('../lib/queue-dedup'); function job(status, fileName, hoster) { return { status, fileName, hoster, file: `C:/dl/${fileName}` }; } test('regression: pending preview jobs are NEVER dropped, even when all match the log', () => { // Exact shape of the reproduced bug: 4 preview jobs for one file across 4 // hosters, every fileName|hoster present in the lifetime upload log. const jobs = [ job('preview', 'Einfach mal die Fresse halten!!!.mp4', 'doodstream.com'), job('preview', 'Einfach mal die Fresse halten!!!.mp4', 'voe.sx'), job('preview', 'Einfach mal die Fresse halten!!!.mp4', 'vidmoly.me'), job('preview', 'Einfach mal die Fresse halten!!!.mp4', 'byse.sx') ]; const log = [ { fileName: 'Einfach mal die Fresse halten!!!.mp4', hoster: 'doodstream.com' }, { fileName: 'Einfach mal die Fresse halten!!!.mp4', hoster: 'voe.sx' }, { fileName: 'Einfach mal die Fresse halten!!!.mp4', hoster: 'vidmoly.me' }, { fileName: 'Einfach mal die Fresse halten!!!.mp4', hoster: 'byse.sx' } ]; const { kept, removed } = partitionRestoredJobsByLog(jobs, log); assert.equal(removed.length, 0, 'no pending job may be removed'); assert.equal(kept.length, 4, 'all 4 pending jobs survive restart/update'); }); test('done jobs in the log are dropped (declutter); pending/error/aborted kept', () => { const jobs = [ job('done', 'a.mkv', 'doodstream.com'), job('preview', 'a.mkv', 'voe.sx'), job('error', 'b.mkv', 'doodstream.com'), job('aborted', 'c.mkv', 'doodstream.com') ]; const log = [ { fileName: 'a.mkv', hoster: 'doodstream.com' }, { fileName: 'a.mkv', hoster: 'voe.sx' }, { fileName: 'b.mkv', hoster: 'doodstream.com' }, { fileName: 'c.mkv', hoster: 'doodstream.com' } ]; const { kept, removed } = partitionRestoredJobsByLog(jobs, log); assert.equal(removed.length, 1); assert.equal(removed[0].status, 'done'); assert.equal(removed[0].hoster, 'doodstream.com'); // The preview a.mkv|voe.sx, error b.mkv, aborted c.mkv all survive. assert.equal(kept.length, 3); assert.ok(kept.some(j => j.status === 'preview' && j.hoster === 'voe.sx')); assert.ok(kept.some(j => j.status === 'error')); assert.ok(kept.some(j => j.status === 'aborted')); }); test('done job NOT in the log is kept (e.g. hoster had logToFile disabled)', () => { const jobs = [job('done', 'd.mkv', 'doodstream.com')]; const { kept, removed } = partitionRestoredJobsByLog(jobs, []); assert.equal(removed.length, 0); assert.equal(kept.length, 1); }); test('case-insensitive match on fileName and hoster', () => { const jobs = [job('done', 'Movie.MKV', 'DoodStream.com')]; const log = [{ fileName: 'movie.mkv', hoster: 'doodstream.com' }]; const { removed } = partitionRestoredJobsByLog(jobs, log); assert.equal(removed.length, 1); }); test('empty/missing inputs do not throw', () => { assert.deepEqual(partitionRestoredJobsByLog([], []), { kept: [], removed: [] }); assert.deepEqual(partitionRestoredJobsByLog(null, null), { kept: [], removed: [] }); const jobs = [job('done', 'x.mkv', 'voe.sx')]; assert.equal(partitionRestoredJobsByLog(jobs, undefined).kept.length, 1); });