126 lines
5.7 KiB
JavaScript
126 lines
5.7 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { createRequire } from 'node:module';
|
|
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import zlib from 'node:zlib';
|
|
import { DEFAULTS, cleanPrefs, wikiToMarkdownLinks } from '../src/lib/prefs.js';
|
|
import { formatDate, dailyId, dailyBody } from '../src/lib/daily.js';
|
|
import { weekOf, monthGrid, weekdayNames } from '../src/lib/database.js';
|
|
|
|
const require = createRequire(import.meta.url);
|
|
|
|
test('cleanPrefs fills defaults and drops values of the wrong kind', () => {
|
|
assert.deepEqual(cleanPrefs(undefined), DEFAULTS);
|
|
assert.deepEqual(cleanPrefs('nope'), DEFAULTS);
|
|
const p = cleanPrefs({ density: 'huge', sidebarWidth: 9999, codeSize: '110', autoPair: 'yes', hiddenKinds: ['quote', 4], trashDays: -3, dateFormat: 'DD/MM' });
|
|
assert.equal(p.density, 'default');
|
|
assert.equal(p.sidebarWidth, 420);
|
|
assert.equal(p.codeSize, 110);
|
|
assert.equal(p.autoPair, true);
|
|
assert.deepEqual(p.hiddenKinds, ['quote']);
|
|
assert.equal(p.trashDays, 0);
|
|
assert.equal(p.dateFormat, 'YYYY-MM-DD');
|
|
assert.equal(cleanPrefs({ historyKeep: '' }).historyKeep, DEFAULTS.historyKeep);
|
|
});
|
|
|
|
test('daily note names follow the chosen format', () => {
|
|
const d = new Date(2026, 0, 5);
|
|
assert.equal(formatDate(d), '2026-01-05');
|
|
assert.equal(formatDate(d, 'DD-MM-YYYY'), '05-01-2026');
|
|
assert.equal(formatDate(d, 'MMMM D, YYYY', 'en-US'), 'January 5, 2026');
|
|
assert.equal(formatDate(d, 'YYYY-MM-DD dddd', 'en-US'), '2026-01-05 Monday');
|
|
assert.equal(dailyId('Daily', d, 'YYYY.MM.DD'), 'Daily/2026.01.05');
|
|
assert.equal(dailyId('Daily', d), 'Daily/2026-01-05');
|
|
});
|
|
|
|
test('the daily template fills in the date and weekday', () => {
|
|
const d = new Date(2026, 0, 5);
|
|
assert.equal(dailyBody('## {{weekday}} {{ date }}', d, 'DD-MM-YYYY', 'en-US'), '## Monday 05-01-2026');
|
|
assert.equal(dailyBody('', d), '');
|
|
});
|
|
|
|
test('calendar weeks can start on Sunday', () => {
|
|
assert.equal(weekOf('2026-01-07')[0].iso, '2026-01-05'); // Monday
|
|
assert.equal(weekOf('2026-01-07', true)[0].iso, '2026-01-04'); // Sunday
|
|
assert.equal(weekOf('2026-01-04', true)[0].iso, '2026-01-04');
|
|
assert.deepEqual(weekdayNames(true).slice(0, 2), ['Sun', 'Mon']);
|
|
const g = monthGrid(2026, 1, true); // February 2026 starts on a Sunday: a Sunday-first grid has no lead days
|
|
assert.equal(g[0][0].iso, '2026-02-01');
|
|
assert.equal(g.length, 4);
|
|
});
|
|
|
|
test('Markdown export can write links as Markdown links', () => {
|
|
const md = 'See [[My Page]] and [[Other|that one]], ![[photo.png]], [[Page#Some Heading]].\n`[[kept]]`\n```\n[[kept too]]\n```';
|
|
const out = wikiToMarkdownLinks(md);
|
|
assert.match(out, /\[My Page\]\(My%20Page\.md\)/);
|
|
assert.match(out, /\[that one\]\(Other\.md\)/);
|
|
assert.match(out, /!\[\]\(photo\.png\)/);
|
|
assert.match(out, /\(Page\.md#some-heading\)/);
|
|
assert.match(out, /`\[\[kept\]\]`/);
|
|
assert.match(out, /\n\[\[kept too\]\]\n/);
|
|
});
|
|
|
|
test('a backup is a readable zip without history and trash', async () => {
|
|
const { zipFolder, backup, due, crc32 } = require('../electron/backup.cjs');
|
|
assert.equal(crc32(Buffer.from('123456789')), 0xcbf43926);
|
|
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'ink-bk-'));
|
|
const out = fs.mkdtempSync(path.join(os.tmpdir(), 'ink-bk-out-'));
|
|
fs.mkdirSync(path.join(root, 'A'), { recursive: true });
|
|
fs.mkdirSync(path.join(root, '.notes', 'history', 'A'), { recursive: true });
|
|
fs.writeFileSync(path.join(root, 'A.md'), '# Hello\n'.repeat(50));
|
|
fs.writeFileSync(path.join(root, 'A', 'Sub é.md'), 'x');
|
|
fs.writeFileSync(path.join(root, '.notes', 'history', 'A', '1.md'), 'old');
|
|
const file = path.join(out, 'x.zip');
|
|
assert.equal(await zipFolder(root, file), 2);
|
|
|
|
// read it back: end record -> central directory -> entries
|
|
const buf = fs.readFileSync(file);
|
|
const end = buf.length - 22;
|
|
assert.equal(buf.readUInt32LE(end), 0x06054b50);
|
|
const n = buf.readUInt16LE(end + 10);
|
|
let at = buf.readUInt32LE(end + 16);
|
|
const found = {};
|
|
for (let i = 0; i < n; i++) {
|
|
const method = buf.readUInt16LE(at + 10), crc = buf.readUInt32LE(at + 16), csize = buf.readUInt32LE(at + 20), size = buf.readUInt32LE(at + 24);
|
|
const nameLen = buf.readUInt16LE(at + 28), off = buf.readUInt32LE(at + 42);
|
|
const name = buf.toString('utf8', at + 46, at + 46 + nameLen);
|
|
const dataAt = off + 30 + buf.readUInt16LE(off + 26) + buf.readUInt16LE(off + 28);
|
|
const raw = buf.subarray(dataAt, dataAt + csize);
|
|
const data = method === 8 ? zlib.inflateRawSync(raw) : raw;
|
|
assert.equal(data.length, size);
|
|
assert.equal(crc32(data), crc);
|
|
found[name] = data.toString();
|
|
at += 46 + nameLen;
|
|
}
|
|
assert.deepEqual(Object.keys(found).sort(), ['A.md', 'A/Sub é.md']);
|
|
assert.equal(found['A/Sub é.md'], 'x');
|
|
|
|
// keeping only the newest few
|
|
for (const f of ['2020-01-01 0000', '2020-01-02 0000', '2020-01-03 0000']) fs.writeFileSync(path.join(out, `${path.basename(root)} ${f}.zip`), 'z');
|
|
await backup(root, out, 2);
|
|
assert.equal(fs.readdirSync(out).filter((f) => f.startsWith(path.basename(root))).length, 2);
|
|
|
|
assert.equal(due('off', 0), false);
|
|
assert.equal(due('daily', 0), true);
|
|
assert.equal(due('daily', Date.now() - 3600e3), false);
|
|
assert.equal(due('weekly', Date.now() - 3 * 864e5), false);
|
|
});
|
|
|
|
test('history limits can be changed', async () => {
|
|
const { Vault, setLimits } = require('../electron/vault.cjs');
|
|
const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'ink-hist-'));
|
|
const v = new Vault(dir);
|
|
setLimits({ historyKeep: 3, historyGapMin: 1 });
|
|
try {
|
|
for (let i = 0; i < 6; i++) {
|
|
await v.write('P', {}, 'v' + i);
|
|
await v.snapshot('P', 'text ' + i, { force: true });
|
|
}
|
|
assert.equal((await v.listHistory('P')).length, 3);
|
|
} finally {
|
|
setLimits({ historyKeep: 100, historyGapMin: 5 });
|
|
}
|
|
});
|