Files
ink-note-app/test/importer.test.js
T
2026-10-15 11:57:09 +02:00

73 lines
3.6 KiB
JavaScript

import { test } from 'node:test';
import assert from 'node:assert/strict';
import { createRequire } from 'node:module';
import { mkdtemp, readFile, writeFile, mkdir, rm } from 'node:fs/promises';
import { existsSync } from 'node:fs';
import { tmpdir } from 'node:os';
import path from 'node:path';
const require = createRequire(import.meta.url);
const { importFolder, importZip, stripId } = require('../electron/importer.cjs');
const { zipFolder } = require('../electron/backup.cjs');
const tmp = () => mkdtemp(path.join(tmpdir(), 'ink-import-'));
const ID = '0123456789abcdef0123456789abcdef';
async function notion(root) {
await mkdir(path.join(root, `Projects ${ID}`), { recursive: true });
await writeFile(path.join(root, `Projects ${ID}.md`), `# Projects\n\nSee [Roadmap](Projects%20${ID}/Roadmap%20${ID.replace(/0/g, '1')}.md) and ![shot](Projects%20${ID}/shot.png).\n[Web](https://example.com/a.md)\n`);
await writeFile(path.join(root, `Projects ${ID}`, `Roadmap ${ID.replace(/0/g, '1')}.md`), '# Roadmap\n');
await writeFile(path.join(root, `Projects ${ID}`, 'shot.png'), Buffer.from([1, 2, 3]));
await writeFile(path.join(root, `Projects ${ID}_all.csv`), 'a,b\n');
await mkdir(path.join(root, '.obsidian'));
await writeFile(path.join(root, '.obsidian', 'app.json'), '{}');
}
test('Notion ids are stripped from names', () => {
assert.equal(stripId(`Page ${ID}.md`), 'Page.md');
assert.equal(stripId(`Folder ${ID}`), 'Folder');
assert.equal(stripId('Plain name.md'), 'Plain name.md');
});
test('a Notion export folder is imported into a new folder, with links as [[wiki links]]', async () => {
const src = await tmp(), vault = await tmp();
await notion(src);
await writeFile(path.join(vault, 'Existing.md'), 'keep');
const r = await importFolder(vault, src);
assert.equal(r.notes, 2);
assert.equal(r.files, 1); // the picture; the _all.csv and .obsidian are left out
const folder = path.join(vault, r.folder);
const top = await readFile(path.join(folder, 'Projects.md'), 'utf8');
assert.ok(top.includes(`[[${r.folder}/Projects/Roadmap]]`), top);
assert.ok(top.includes('![shot](Projects/shot.png)'), top);
assert.ok(top.includes('[Web](https://example.com/a.md)'));
assert.ok(existsSync(path.join(folder, 'Projects', 'Roadmap.md')));
assert.ok(existsSync(path.join(folder, 'Projects', 'shot.png')));
assert.ok(!existsSync(path.join(folder, '.obsidian')));
assert.equal(await readFile(path.join(vault, 'Existing.md'), 'utf8'), 'keep');
await rm(src, { recursive: true }); await rm(vault, { recursive: true });
});
test('a zip is imported the same way, ignoring one wrapping folder, and a second import makes a second folder', async () => {
const base = await tmp(), vault = await tmp(), out = await tmp();
const src = path.join(base, 'Export');
await mkdir(src);
await notion(src);
const zip = path.join(out, 'Export.zip');
await zipFolder(base, zip);
const a = await importZip(vault, zip);
const b = await importZip(vault, zip);
assert.equal(a.notes, 2);
assert.notEqual(a.folder, b.folder);
assert.ok(existsSync(path.join(vault, a.folder, 'Projects', 'Roadmap.md')));
for (const d of [base, vault, out]) await rm(d, { recursive: true });
});
test('a zip with .. in a name is not written outside the notes', async () => {
const vault = await tmp();
const { importFiles } = require('../electron/importer.cjs');
await importFiles(vault, 'X', [{ rel: 'ok.md', read: () => Buffer.from('a') }, { rel: '../../evil.md', read: () => Buffer.from('b') }]).catch(() => {});
assert.ok(!existsSync(path.join(vault, '..', 'evil.md')));
await rm(vault, { recursive: true });
});