import assert from 'node:assert/strict'; import test from 'node:test'; import { access, mkdir, rm, writeFile } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { loadManifest, validateManifest, checkDestinations } from '../scripts/lib/migration.mjs'; test('manifest accounts for exactly 29 unique source pages', async () => { const manifest = await loadManifest('docs/migration-manifest.json'); const result = validateManifest(manifest); assert.equal(result.entries.length, 29); assert.equal(new Set(result.entries.map(({ source }) => source)).size, 29); }); test('generic DokuWiki pages are excluded', async () => { const manifest = await loadManifest('docs/migration-manifest.json'); assert.equal(manifest.entries.some(({ source }) => source.startsWith('pages/wiki/')), false); }); test('validation rejects source traversal outside the selected scope', async () => { const manifest = await loadManifest('docs/migration-manifest.json'); manifest.entries[2].source = 'pages/study/../../wiki/x.txt'; assert.throws(() => validateManifest(manifest), /outside the selected migration scope/); }); test('validation rejects destination traversal outside the docs root', async () => { const manifest = await loadManifest('docs/migration-manifest.json'); manifest.entries[2].destination = 'src/content/docs/../../../outside.md'; assert.throws(() => validateManifest(manifest), /outside src\/content\/docs/); }); test('validation rejects duplicate destinations unless the later entry is a merge', async () => { const manifest = await loadManifest('docs/migration-manifest.json'); manifest.entries[1].mode = 'page'; assert.throws(() => validateManifest(manifest), /Duplicate destination/); }); test('destination check reports only files that have not been migrated', async () => { const root = await mkdir(join(tmpdir(), `migration-${process.pid}-${Date.now()}`), { recursive: true }); const existing = join(root, 'src/content/docs/present.md'); await mkdir(join(root, 'src/content/docs'), { recursive: true }); await writeFile(existing, '# Present\n'); try { const result = await checkDestinations({ entries: [ { destination: 'src/content/docs/present.md' }, { destination: 'src/content/docs/missing.md' }, ], }, root); await access(existing); assert.deepEqual(result.missing, ['src/content/docs/missing.md']); } finally { await rm(root, { recursive: true, force: true }); } });