diff --git a/.gitignore b/.gitignore index a468692..d73cd0a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,9 @@ bun.lockb /.svelte-kit /build +# Local tests +/tests/ + # Nix /result diff --git a/tests/mixed-lists.test.mjs b/tests/mixed-lists.test.mjs deleted file mode 100644 index eb071af..0000000 --- a/tests/mixed-lists.test.mjs +++ /dev/null @@ -1,80 +0,0 @@ -import assert from 'node:assert/strict'; -import { readFile } from 'node:fs/promises'; -import test from 'node:test'; -import { Schema } from '@tiptap/pm/model'; -import { transformWithEsbuild } from 'vite'; - -const source = await readFile( - new URL('../src/lib/editor/mixedLists.ts', import.meta.url), - 'utf8' -); -const { code } = await transformWithEsbuild(source, 'mixedLists.ts', { - loader: 'ts', - format: 'esm', - target: 'esnext' -}); -const { convertListNode } = await import( - `data:text/javascript;base64,${Buffer.from(code).toString('base64')}` -); - -const schema = new Schema({ - nodes: { - doc: { content: 'block+' }, - paragraph: { content: 'text*', group: 'block' }, - text: { group: 'inline' }, - bulletList: { content: 'listItem+', group: 'block' }, - listItem: { content: 'paragraph block*' }, - taskList: { content: 'taskItem+', group: 'block' }, - taskItem: { - attrs: { checked: { default: false } }, - content: 'paragraph block*' - } - } -}); - -function paragraph(text) { - return schema.node('paragraph', null, [schema.text(text)]); -} - -test('converts every task item in a list to a bullet item', () => { - const sourceList = schema.node('taskList', null, [ - schema.node('taskItem', { checked: true }, [paragraph('First')]), - schema.node('taskItem', { checked: false }, [paragraph('Second')]) - ]); - - const converted = convertListNode(schema, sourceList, 'bulletList'); - - assert.equal(converted.type.name, 'bulletList'); - assert.deepEqual( - converted.content.content.map((item) => item.type.name), - ['listItem', 'listItem'] - ); - assert.equal(converted.textContent, 'FirstSecond'); - assert.equal(sourceList.type.name, 'taskList'); -}); - -test('converts bullet items to unchecked tasks without dropping nested blocks', () => { - const nestedBullets = schema.node('bulletList', null, [ - schema.node('listItem', null, [paragraph('Nested note')]) - ]); - const sourceList = schema.node('bulletList', null, [ - schema.node('listItem', null, [paragraph('Parent'), nestedBullets]) - ]); - - const converted = convertListNode(schema, sourceList, 'taskList'); - const taskItem = converted.firstChild; - - assert.equal(converted.type.name, 'taskList'); - assert.equal(taskItem.type.name, 'taskItem'); - assert.equal(taskItem.attrs.checked, false); - assert.equal(taskItem.lastChild.type.name, 'bulletList'); - assert.equal(taskItem.textContent, 'ParentNested note'); -}); - -test('leaves a list alone when it already has the requested type', () => { - const bullets = schema.node('bulletList', null, [ - schema.node('listItem', null, [paragraph('Unchanged')]) - ]); - - assert.equal(convertListNode(schema, bullets, 'bulletList'), null); -}); diff --git a/tests/note-drag.test.mjs b/tests/note-drag.test.mjs deleted file mode 100644 index 8680412..0000000 --- a/tests/note-drag.test.mjs +++ /dev/null @@ -1,28 +0,0 @@ -import assert from 'node:assert/strict'; -import { readFile } from 'node:fs/promises'; -import test from 'node:test'; -import { transformWithEsbuild } from 'vite'; - -const source = await readFile( - new URL('../src/lib/utils/note-drag.ts', import.meta.url), - 'utf8' -); -const { code } = await transformWithEsbuild(source, 'note-drag.ts', { - loader: 'ts', - format: 'esm', - target: 'esnext' -}); -const noteDrag = await import(`data:text/javascript;base64,${Buffer.from(code).toString('base64')}`); - -test('round-trips every selected note path in a drag payload', () => { - const paths = ['/vault/Alpha.md', '/vault/Projects/Beta.md']; - assert.deepEqual(noteDrag.decodeNoteDragPaths(noteDrag.encodeNoteDragPaths(paths)), paths); -}); - -test('keeps single-note and Windows path payloads compatible', () => { - assert.deepEqual(noteDrag.decodeNoteDragPaths('/vault/Alpha.md'), ['/vault/Alpha.md']); - assert.deepEqual( - noteDrag.decodeNoteDragPaths('C:\\Vault\\Alpha.md\r\nC:\\Vault\\Beta.md'), - ['C:\\Vault\\Alpha.md', 'C:\\Vault\\Beta.md'] - ); -}); diff --git a/tests/notebook-icons.test.mjs b/tests/notebook-icons.test.mjs deleted file mode 100644 index b7ceb9c..0000000 --- a/tests/notebook-icons.test.mjs +++ /dev/null @@ -1,27 +0,0 @@ -import assert from 'node:assert/strict'; -import test from 'node:test'; - -const source = await import(new URL('../src/lib/utils/notebook-icons.ts', import.meta.url)); - -const { - NOTEBOOK_ICON_OPTIONS, - decodeBuiltinNotebookIcon, - encodeBuiltinNotebookIcon -} = source; - -test('built-in notebook icons have stable unique storage values', () => { - assert.equal(NOTEBOOK_ICON_OPTIONS.length, 16); - assert.equal(new Set(NOTEBOOK_ICON_OPTIONS.map(({ id }) => id)).size, NOTEBOOK_ICON_OPTIONS.length); - - for (const { id } of NOTEBOOK_ICON_OPTIONS) { - const stored = encodeBuiltinNotebookIcon(id); - assert.equal(stored, `builtin:${id}`); - assert.equal(decodeBuiltinNotebookIcon(stored), id); - } -}); - -test('custom paths and unknown built-in values remain outside the icon codec', () => { - assert.equal(decodeBuiltinNotebookIcon('.helixnotes/attachments/notebook-icon.png'), null); - assert.equal(decodeBuiltinNotebookIcon('builtin:unknown'), null); - assert.equal(decodeBuiltinNotebookIcon(null), null); -}); diff --git a/tests/sidebar-mobile-actions.test.mjs b/tests/sidebar-mobile-actions.test.mjs deleted file mode 100644 index 342839e..0000000 --- a/tests/sidebar-mobile-actions.test.mjs +++ /dev/null @@ -1,31 +0,0 @@ -import assert from 'node:assert/strict'; -import { readFile } from 'node:fs/promises'; -import test from 'node:test'; - -const sidebar = await readFile( - new URL('../src/lib/components/Sidebar.svelte', import.meta.url), - 'utf8' -); - -test('mobile notebook rows expose an accessible actions button', () => { - assert.match(sidebar, /\{#if isMobile\}[\s\S]{0,500}class="notebook-actions-btn"/); - assert.match(sidebar, /aria-label=\{`Actions for \$\{nb\.name\}`\}/); - assert.match(sidebar, /onclick=\{\(e\) => openNotebookMenu\(e, nb\)\}/); -}); - -test('the notebook context menu receives its mobile styling outside the sidebar', () => { - assert.match(sidebar, /class="context-menu" class:mobile=\{isMobile\}/); - assert.match(sidebar, /\.context-menu\.mobile\s*\{/); -}); - -test('mobile action sheets stay inside every safe area and prevent tap-through', () => { - assert.match(sidebar, /class="context-menu-backdrop"/); - assert.match(sidebar, /safe-area-inset-left/); - assert.match(sidebar, /safe-area-inset-right/); - assert.match(sidebar, /safe-area-inset-top/); - assert.match(sidebar, /safe-area-inset-bottom/); -}); - -test('the actions button remains inside the notebook manual-sort drop target', () => { - assert.match(sidebar, /
/); -}); diff --git a/tests/startup-view.test.mjs b/tests/startup-view.test.mjs deleted file mode 100644 index 0e69fac..0000000 --- a/tests/startup-view.test.mjs +++ /dev/null @@ -1,60 +0,0 @@ -import assert from 'node:assert/strict'; -import { readFile } from 'node:fs/promises'; -import test from 'node:test'; -import { transformWithEsbuild } from 'vite'; - -const source = await readFile( - new URL('../src/lib/utils/startup-view.ts', import.meta.url), - 'utf8' -); -const { code } = await transformWithEsbuild(source, 'startup-view.ts', { - loader: 'ts', - format: 'esm', - target: 'esnext' -}); -const startup = await import(`data:text/javascript;base64,${Buffer.from(code).toString('base64')}`); - -test('normalizes every supported default view and falls back to All Notes', () => { - for (const view of ['all', 'quickaccess', 'tasks', 'daily']) { - assert.equal(startup.normalizeStartupView(view), view); - } - assert.equal(startup.normalizeStartupView('notebook'), 'all'); - assert.equal(startup.normalizeStartupView(undefined), 'all'); -}); - -test('uses the configured default when session restoration is disabled', () => { - assert.deepEqual(startup.resolveStartupTarget({ - startupView: 'tasks', - restoreLastSession: false, - lastViewMode: 'daily', - lastNotebook: null, - lastTag: null - }), { mode: 'tasks' }); -}); - -test('restores a supported previous list when restoration is enabled', () => { - assert.deepEqual(startup.resolveStartupTarget({ - startupView: 'daily', - restoreLastSession: true, - lastViewMode: 'quickaccess', - lastNotebook: null, - lastTag: null - }), { mode: 'quickaccess' }); -}); - -test('restores notebook and tag identifiers, otherwise uses the configured default', () => { - assert.deepEqual(startup.resolveStartupTarget({ - startupView: 'all', - restoreLastSession: true, - lastViewMode: 'notebook', - lastNotebook: 'Projects', - lastTag: null - }), { mode: 'notebook', notebookPath: 'Projects' }); - assert.deepEqual(startup.resolveStartupTarget({ - startupView: 'tasks', - restoreLastSession: true, - lastViewMode: 'tag', - lastNotebook: null, - lastTag: null - }), { mode: 'tasks' }); -});