mirror of
https://github.com/fancive/obsidian-parallel-reader.git
synced 2026-07-22 17:20:24 +00:00
Replaces the monolithic modules.test.js (983 lines) with focused per-module test files sharing a common test-setup.js. Each file is under 225 lines. All existing test assertions preserved. New files: test-setup.js, anchor.test.js, schema.test.js, cache.test.js, cards-nav.test.js, markdown.test.js, vault-batch.test.js, i18n.test.js, scroll.test.js, settings.test.js, providers.test.js, streaming.test.js, cli.test.js Change-Id: I37a3342a1588807277e679e6535cde361e650565
87 lines
4.9 KiB
JavaScript
87 lines
4.9 KiB
JavaScript
const { assert, t } = require('./test-setup');
|
|
|
|
// ── vault.ts ──
|
|
|
|
assert.deepStrictEqual(t.folderPathsForTarget(''), [], 'empty path');
|
|
assert.deepStrictEqual(t.folderPathsForTarget('A/B/C'), ['A', 'A/B', 'A/B/C']);
|
|
assert.deepStrictEqual(t.folderPathsForTarget('/A//B/'), ['A', 'A/B'], 'normalizes slashes');
|
|
assert.deepStrictEqual(t.folderPathsForTarget('single'), ['single']);
|
|
assert.deepStrictEqual(t.folderPathsForTarget('../../etc/passwd'), ['etc', 'etc/passwd'], 'strips .. path traversal');
|
|
assert.deepStrictEqual(t.folderPathsForTarget('./a/../b'), ['a', 'a/b'], 'strips . and .. segments');
|
|
assert.deepStrictEqual(t.folderPathsForTarget('a/../../b'), ['a', 'a/b'], 'strips mid-path ..');
|
|
|
|
// ── batch.ts ──
|
|
|
|
assert.strictEqual(t.normalizeBatchFolderInput('/Reading//Articles/'), 'Reading/Articles', 'normalizes folder input');
|
|
assert.strictEqual(t.normalizeBatchFolderInput('../Inbox/./Daily'), 'Inbox/Daily', 'strips unsafe folder segments');
|
|
assert.strictEqual(t.hasUnsafeBatchFolderSegments('../Inbox/./Daily'), true, 'unsafe folder segments are detected');
|
|
assert.strictEqual(t.hasUnsafeBatchFolderSegments('/Reading//Articles/'), false, 'normal folder paths are safe');
|
|
assert.deepStrictEqual(
|
|
t.validateBatchFolderInput('', () => false),
|
|
{ valid: true, reason: 'ok', folderPath: '' },
|
|
'empty batch folder targets vault root',
|
|
);
|
|
assert.deepStrictEqual(
|
|
t.validateBatchFolderInput('Reading', (path) => path === 'Reading'),
|
|
{ valid: true, reason: 'ok', folderPath: 'Reading' },
|
|
'existing folder input is valid',
|
|
);
|
|
assert.deepStrictEqual(
|
|
t.validateBatchFolderInput('../Reading', () => true),
|
|
{ valid: false, reason: 'unsafe', folderPath: 'Reading' },
|
|
'unsafe folder input is invalid even if normalized target exists',
|
|
);
|
|
assert.deepStrictEqual(
|
|
t.validateBatchFolderInput('Missing', () => false),
|
|
{ valid: false, reason: 'missing', folderPath: 'Missing' },
|
|
'missing folder input is invalid',
|
|
);
|
|
const batchFiles = [
|
|
{ path: 'root.md', parent: null },
|
|
{ path: 'Reading/note.md', parent: { path: 'Reading' } },
|
|
{ path: 'Reading/Deep/nested.md', parent: { path: 'Reading/Deep' } },
|
|
];
|
|
assert.deepStrictEqual(t.selectBatchFiles(batchFiles, '').map((file) => file.path), ['root.md'], 'root folder only');
|
|
assert.deepStrictEqual(
|
|
t.selectBatchFiles(batchFiles, '/Reading/').map((file) => file.path),
|
|
['Reading/note.md'],
|
|
'selected folder is non-recursive',
|
|
);
|
|
assert.deepStrictEqual(t.batchProgressVars(1, 3), { current: 2, total: 3 }, 'progress vars are one-based');
|
|
const batchStats = t.createBatchStats(3);
|
|
const skippedStats = t.recordBatchSkip(batchStats);
|
|
const processedStats = t.recordBatchProcessed(skippedStats);
|
|
const errorStats = t.recordBatchError(processedStats);
|
|
assert.deepStrictEqual(batchStats, { total: 3, processed: 0, skipped: 0, errors: 0 }, 'batch stats are immutable');
|
|
assert.deepStrictEqual(skippedStats, { total: 3, processed: 1, skipped: 1, errors: 0 }, 'batch skip updates progress');
|
|
assert.deepStrictEqual(processedStats, { total: 3, processed: 2, skipped: 1, errors: 0 }, 'batch processed count accumulates');
|
|
assert.deepStrictEqual(errorStats, { total: 3, processed: 3, skipped: 1, errors: 1 }, 'batch error count accumulates');
|
|
|
|
const batchState = t.createBatchRunState();
|
|
assert.deepStrictEqual(batchState, { cancelled: false, currentPath: '' }, 'batch state starts idle');
|
|
assert.strictEqual(t.markBatchFileRunning(batchState, 'Reading/a.md'), batchState, 'batch state updates in place');
|
|
assert.strictEqual(batchState.currentPath, 'Reading/a.md', 'batch state records current file');
|
|
assert.strictEqual(t.requestBatchCancel(batchState), true, 'first batch cancellation request succeeds');
|
|
assert.strictEqual(batchState.cancelled, true, 'batch cancellation flag is set');
|
|
assert.strictEqual(t.requestBatchCancel(batchState), false, 'duplicate batch cancellation request is ignored');
|
|
assert.strictEqual(t.requestBatchCancel(null), false, 'missing batch state cannot be cancelled');
|
|
|
|
const batchA = t.createBatchRunState();
|
|
const batchB = t.createBatchRunState();
|
|
t.markBatchFileRunning(batchA, 'folderA/note.md');
|
|
t.markBatchFileRunning(batchB, 'folderB/note.md');
|
|
assert.strictEqual(batchA.currentPath, 'folderA/note.md', 'batch A tracks its own file');
|
|
assert.strictEqual(batchB.currentPath, 'folderB/note.md', 'batch B tracks its own file');
|
|
t.requestBatchCancel(batchA);
|
|
assert.strictEqual(batchA.cancelled, true, 'batch A cancelled');
|
|
assert.strictEqual(batchB.cancelled, false, 'batch B unaffected by A cancellation');
|
|
|
|
const midCancelStats = t.createBatchStats(5);
|
|
const s1 = t.recordBatchProcessed(midCancelStats);
|
|
const s2 = t.recordBatchSkip(s1);
|
|
assert.strictEqual(s2.processed, 2, 'two files processed before cancel');
|
|
assert.strictEqual(s2.skipped, 1, 'one skipped before cancel');
|
|
assert.strictEqual(s2.errors, 0, 'no errors before cancel');
|
|
assert.strictEqual(s2.total, 5, 'total unchanged by partial processing');
|
|
|
|
console.log('vault-batch tests passed');
|