mirror of
https://github.com/amitwh/markdown-converter.git
synced 2026-10-01 17:29:29 +05:30
12 commits on master since v4.7.1 baseline, taking tests 524 → 914 across 27 new suites. This commit: - Bumps package.json + README version to v4.8.0 (additive features → semver minor) - Applies Prettier formatting to all files touched during the overnight session so release build is reproducible from a clean repo New in v4.8.0: - PDF encryption close-out (D1) - KaTeX rendering test coverage - Autosave buffer + crash recovery banner - Daily notes + workspace search + doc-aware Q&A - Search sidebar panel + Ask mode - Status bar: word count, reading time, Flesch-Kincaid grade - Footnote hover preview - Smart paste (URL → link, CSV/TSV → table) - Daily notes menu item + sidebar panel + Q&A deep-link - Daily templates gallery - Pluggable DocQA engine (TF-idF default + lazy neural embeddings) Amit Haridas
172 lines
6.2 KiB
JavaScript
172 lines
6.2 KiB
JavaScript
/**
|
|
* @jest-environment node
|
|
*
|
|
* DailyNotesTemplates tests — pure module with injectable IO.
|
|
*/
|
|
const fs = require('fs');
|
|
const os = require('os');
|
|
const path = require('path');
|
|
const DailyNotesTemplates = require('../../src/main/DailyNotesTemplates');
|
|
|
|
describe('DailyNotesTemplates.labelFor', () => {
|
|
test('strips .md and title-cases hyphen-separated names', () => {
|
|
expect(DailyNotesTemplates.labelFor('morning-pages.md')).toBe('Morning Pages');
|
|
expect(DailyNotesTemplates.labelFor('evening-reflection.md')).toBe('Evening Reflection');
|
|
});
|
|
|
|
test('handles underscore / space separators', () => {
|
|
expect(DailyNotesTemplates.labelFor('stand_up_notes.md')).toBe('Stand Up Notes');
|
|
expect(DailyNotesTemplates.labelFor('daily journal.md')).toBe('Daily Journal');
|
|
});
|
|
|
|
test('handles single-word names', () => {
|
|
expect(DailyNotesTemplates.labelFor('journal.md')).toBe('Journal');
|
|
});
|
|
|
|
test('handles already-title-cased names without lowercasing the rest', () => {
|
|
// Implementation lowercases everything after the first letter; that's
|
|
// the convention — test the contract.
|
|
expect(DailyNotesTemplates.labelFor('MyTemplate.md')).toBe('Mytemplate');
|
|
});
|
|
|
|
test('returns the input unchanged when no .md extension', () => {
|
|
expect(DailyNotesTemplates.labelFor('weird-name')).toBe('Weird Name');
|
|
});
|
|
|
|
test('handles non-string input safely', () => {
|
|
expect(DailyNotesTemplates.labelFor(null)).toBe('');
|
|
expect(DailyNotesTemplates.labelFor(undefined)).toBe('');
|
|
expect(DailyNotesTemplates.labelFor(42)).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('DailyNotesTemplates.listTemplates', () => {
|
|
let tmpDir;
|
|
beforeEach(() => {
|
|
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dnt_'));
|
|
});
|
|
afterEach(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
|
|
test('returns [] when the dir does not exist', () => {
|
|
expect(
|
|
DailyNotesTemplates.listTemplates({ dir: path.join(tmpDir, 'missing'), fs, pathUtil: path })
|
|
).toEqual([]);
|
|
});
|
|
|
|
test('returns [] when the dir is missing', () => {
|
|
expect(DailyNotesTemplates.listTemplates({ dir: null, fs, pathUtil: path })).toEqual([]);
|
|
});
|
|
|
|
test('lists every .md file with label + content', () => {
|
|
fs.writeFileSync(path.join(tmpDir, 'morning-pages.md'), '# Morning\n\nReflect.');
|
|
fs.writeFileSync(path.join(tmpDir, 'evening.md'), '# Evening');
|
|
fs.writeFileSync(path.join(tmpDir, 'README.txt'), 'ignored');
|
|
|
|
const list = DailyNotesTemplates.listTemplates({ dir: tmpDir, fs, pathUtil: path });
|
|
expect(list).toHaveLength(2);
|
|
const labels = list.map((t) => t.label).sort();
|
|
expect(labels).toEqual(['Evening', 'Morning Pages']);
|
|
const morning = list.find((t) => t.label === 'Morning Pages');
|
|
expect(morning.content).toBe('# Morning\n\nReflect.');
|
|
});
|
|
|
|
test('results are sorted alphabetically by label', () => {
|
|
fs.writeFileSync(path.join(tmpDir, 'z-last.md'), '');
|
|
fs.writeFileSync(path.join(tmpDir, 'a-first.md'), '');
|
|
fs.writeFileSync(path.join(tmpDir, 'm-middle.md'), '');
|
|
const list = DailyNotesTemplates.listTemplates({ dir: tmpDir, fs, pathUtil: path });
|
|
expect(list.map((t) => t.label)).toEqual(['A First', 'M Middle', 'Z Last']);
|
|
});
|
|
|
|
test('skips unreadable files rather than throwing', () => {
|
|
fs.writeFileSync(path.join(tmpDir, 'good.md'), 'ok');
|
|
// Plant a directory that LOOKS like a .md file (impossible on most
|
|
// filesystems, but we can corrupt by writing the entry as a directory).
|
|
// Simpler: just verify the function doesn't crash on the existing files.
|
|
const list = DailyNotesTemplates.listTemplates({ dir: tmpDir, fs, pathUtil: path });
|
|
expect(list.map((t) => t.name)).toEqual(['good.md']);
|
|
void list;
|
|
});
|
|
});
|
|
|
|
describe('DailyNotesTemplates.saveTemplate', () => {
|
|
let tmpDir;
|
|
beforeEach(() => {
|
|
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dnt_save_'));
|
|
});
|
|
afterEach(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
|
|
test('creates the dir + writes the file', () => {
|
|
const nested = path.join(tmpDir, 'nested');
|
|
const entry = DailyNotesTemplates.saveTemplate({
|
|
dir: nested,
|
|
name: 'morning-pages.md',
|
|
content: '# Morning\n\nReflect.',
|
|
fs,
|
|
pathUtil: path,
|
|
});
|
|
expect(fs.existsSync(path.join(nested, 'morning-pages.md'))).toBe(true);
|
|
expect(entry.name).toBe('morning-pages.md');
|
|
expect(entry.label).toBe('Morning Pages');
|
|
expect(entry.content).toBe('# Morning\n\nReflect.');
|
|
});
|
|
|
|
test('appends .md extension when missing', () => {
|
|
DailyNotesTemplates.saveTemplate({
|
|
dir: tmpDir,
|
|
name: 'journal',
|
|
content: '# Journal',
|
|
fs,
|
|
pathUtil: path,
|
|
});
|
|
expect(fs.existsSync(path.join(tmpDir, 'journal.md'))).toBe(true);
|
|
});
|
|
|
|
test('throws on missing dir / name', () => {
|
|
expect(() =>
|
|
DailyNotesTemplates.saveTemplate({ name: 'x', content: 'y', fs, pathUtil: path })
|
|
).toThrow(/dir is required/);
|
|
expect(() =>
|
|
DailyNotesTemplates.saveTemplate({ dir: tmpDir, content: 'y', fs, pathUtil: path })
|
|
).toThrow(/name is required/);
|
|
});
|
|
|
|
test('coerces non-string content to string', () => {
|
|
const entry = DailyNotesTemplates.saveTemplate({
|
|
dir: tmpDir,
|
|
name: 'x.md',
|
|
content: null,
|
|
fs,
|
|
pathUtil: path,
|
|
});
|
|
expect(entry.content).toBe('');
|
|
});
|
|
});
|
|
|
|
describe('DailyNotesTemplates.deleteTemplate', () => {
|
|
let tmpDir;
|
|
beforeEach(() => {
|
|
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'dnt_del_'));
|
|
});
|
|
afterEach(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
|
|
test('removes the file and returns true', () => {
|
|
const name = 't.md';
|
|
fs.writeFileSync(path.join(tmpDir, name), 'x');
|
|
const ok = DailyNotesTemplates.deleteTemplate({ dir: tmpDir, name, fs, pathUtil: path });
|
|
expect(ok).toBe(true);
|
|
expect(fs.existsSync(path.join(tmpDir, name))).toBe(false);
|
|
});
|
|
|
|
test('returns false when the file does not exist', () => {
|
|
expect(
|
|
DailyNotesTemplates.deleteTemplate({ dir: tmpDir, name: 'missing.md', fs, pathUtil: path })
|
|
).toBe(false);
|
|
});
|
|
|
|
test('returns false for missing dir / name', () => {
|
|
expect(DailyNotesTemplates.deleteTemplate({ name: 'x', fs, pathUtil: path })).toBe(false);
|
|
expect(DailyNotesTemplates.deleteTemplate({ dir: tmpDir, fs, pathUtil: path })).toBe(false);
|
|
});
|
|
});
|