Preserve queue recovery and desktop drop integrity

Resolve floating drops through Electron native paths, expand folders recursively, correlate terminal outcomes by job ID until final queue persistence succeeds, and keep current queue badges, telemetry, cancellation behavior, and copy-link wording synchronized.
This commit is contained in:
Sucukdeluxe
2026-08-13 20:45:01 +02:00
parent b64cdd0ff3
commit 4630c8c467
12 changed files with 363 additions and 55 deletions
+75
View File
@@ -0,0 +1,75 @@
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
test('terminal recovery snapshots retain exact job outcomes and canonical links', () => {
const { buildTerminalJobSnapshots } = require('../lib/upload-recovery');
const snapshots = buildTerminalJobSnapshots({
files: [{
name: 'episode.mkv',
results: [
{ jobId: 'done-job', hoster: 'doodstream.com', status: 'done', download_url: 'https://doodstream.com/d/abc123', file_code: 'abc123' },
{ jobId: 'error-job', hoster: 'voe.sx', status: 'error', error: 'rejected', failureDetails: { kind: 'hoster' } },
{ hoster: 'byse.sx', status: 'done', download_url: 'https://byse.sx/d/no-id' }
]
}]
});
assert.deepEqual(snapshots, [
{
jobId: 'done-job',
status: 'done',
error: null,
failureDetails: null,
result: { download_url: 'https://doodstream.com/d/abc123', embed_url: null, file_code: 'abc123' }
},
{
jobId: 'error-job',
status: 'error',
error: 'rejected',
failureDetails: { kind: 'hoster' },
result: null
}
]);
});
test('recovery markers affect only their exact job IDs and never restart terminal outcomes', () => {
const { getRecoveryOutcome } = require('../lib/upload-recovery');
const recovery = {
jobIds: ['done-job', 'active-job'],
terminalJobs: [{
jobId: 'done-job',
status: 'done',
error: null,
failureDetails: null,
result: { download_url: 'https://doodstream.com/d/abc123', embed_url: null, file_code: 'abc123' }
}]
};
assert.deepEqual(getRecoveryOutcome({ id: 'done-job', status: 'preview' }, recovery), {
status: 'done',
error: null,
failureDetails: null,
result: { download_url: 'https://doodstream.com/d/abc123', embed_url: null, file_code: 'abc123' },
interrupted: false
});
assert.deepEqual(getRecoveryOutcome({ id: 'active-job', status: 'queued' }, recovery), { status: 'queued', interrupted: true });
assert.deepEqual(getRecoveryOutcome({ id: 'foreign-job', status: 'queued' }, recovery), { status: 'queued', interrupted: false });
assert.deepEqual(getRecoveryOutcome({ id: 'already-done', status: 'done' }, recovery), { status: 'done', interrupted: false });
});
test('main and renderer keep recovery evidence until final queue persistence succeeds', () => {
const root = path.join(__dirname, '..');
const mainSource = fs.readFileSync(path.join(root, 'main.js'), 'utf8');
const rendererSource = fs.readFileSync(path.join(root, 'renderer', 'app.js'), 'utf8');
const indexSource = fs.readFileSync(path.join(root, 'renderer', 'index.html'), 'utf8');
const batchDone = mainSource.slice(mainSource.indexOf("uploadManager.on('batch-done'"), mainSource.indexOf("ipcMain.handle('cancel-upload'"));
assert.match(batchDone, /buildTerminalJobSnapshots\(summary\)/);
assert.match(batchDone, /if \(queuePersisted\)[\s\S]*saveUploadRecovery\(null\)/);
assert.ok(batchDone.indexOf('saveUploadRecovery(recoveryWithTerminalJobs)') < batchDone.indexOf('requestUploadFinalization(summary, historyPersisted)'));
assert.match(rendererSource, /window\.UploadRecovery\.getRecoveryOutcome/);
assert.match(rendererSource, /data\.historyPersisted !== true/);
assert.ok(indexSource.indexOf('../lib/upload-recovery.js') < indexSource.indexOf('app.js'));
});