From ed93b4b234d82fcbbb84939218d716e1d5a02f6a Mon Sep 17 00:00:00 2001 From: lucaronin Date: Thu, 16 Apr 2026 02:42:43 +0200 Subject: [PATCH] fix: stop defaulting new note status --- src/hooks/useNoteCreation.extra.test.ts | 12 ++++++++---- src/hooks/useNoteCreation.test.ts | 16 +++++++++++----- src/hooks/useNoteCreation.ts | 6 ++---- .../create-note-default-properties.spec.ts | 17 +++++++++++++++++ 4 files changed, 38 insertions(+), 13 deletions(-) create mode 100644 tests/smoke/create-note-default-properties.spec.ts diff --git a/src/hooks/useNoteCreation.extra.test.ts b/src/hooks/useNoteCreation.extra.test.ts index 7ad907ad..011226e1 100644 --- a/src/hooks/useNoteCreation.extra.test.ts +++ b/src/hooks/useNoteCreation.extra.test.ts @@ -259,14 +259,16 @@ describe('resolveNewNote', () => { const { entry, content } = resolveNewNote({ title: 'My Project', type: 'Project', vaultPath: '/my/vault' }) expect(entry.path).toBe('/my/vault/my-project.md') expect(entry.isA).toBe('Project') - expect(entry.status).toBe('Active') + expect(entry.status).toBeNull() expect(content).toContain('type: Project') - expect(content).toContain('status: Active') + expect(content).not.toContain('status:') }) it('creates custom type note at vault root', () => { - const { entry } = resolveNewNote({ title: 'First Recipe', type: 'Recipe', vaultPath: '/my/vault' }) + const { entry, content } = resolveNewNote({ title: 'First Recipe', type: 'Recipe', vaultPath: '/my/vault' }) expect(entry.path).toBe('/my/vault/first-recipe.md') + expect(entry.status).toBeNull() + expect(content).not.toContain('status:') }) it('omits status for Topic type', () => { @@ -281,8 +283,10 @@ describe('resolveNewNote', () => { }) it('uses provided vault path', () => { - const { entry } = resolveNewNote({ title: 'Test', type: 'Note', vaultPath: '/other/vault' }) + const { entry, content } = resolveNewNote({ title: 'Test', type: 'Note', vaultPath: '/other/vault' }) expect(entry.path).toBe('/other/vault/test.md') + expect(entry.status).toBeNull() + expect(content).not.toContain('status:') }) it('produces a valid path for custom types with special characters', () => { diff --git a/src/hooks/useNoteCreation.test.ts b/src/hooks/useNoteCreation.test.ts index 47e9650a..37bd3ef6 100644 --- a/src/hooks/useNoteCreation.test.ts +++ b/src/hooks/useNoteCreation.test.ts @@ -150,8 +150,9 @@ describe('resolveNewNote', () => { const { entry, content } = resolveNewNote({ title: 'My Project', type: 'Project', vaultPath: '/vault' }) expect(entry.path).toBe('/vault/my-project.md') expect(entry.isA).toBe('Project') - expect(entry.status).toBe('Active') + expect(entry.status).toBeNull() expect(content).toContain('type: Project') + expect(content).not.toContain('status:') }) it('omits status for Topic type', () => { @@ -159,10 +160,10 @@ describe('resolveNewNote', () => { expect(entry.status).toBeNull() }) - it('treats Journal as a regular type after removing the journaling flow', () => { + it('does not add a default status for other regular types', () => { const { entry, content } = resolveNewNote({ title: 'Reflection', type: 'Journal', vaultPath: '/vault' }) - expect(entry.status).toBe('Active') - expect(content).toContain('status: Active') + expect(entry.status).toBeNull() + expect(content).not.toContain('status:') }) }) @@ -215,6 +216,8 @@ describe('useNoteCreation hook', () => { const [createdEntry] = addEntry.mock.calls[0] expect(createdEntry.title).toBe('Test Note') expect(createdEntry.isA).toBe('Note') + expect(createdEntry.status).toBeNull() + expect(openTabWithContent.mock.calls[0][1]).toBe('---\ntitle: Test Note\ntype: Note\n---\n') }) it('handleCreateNoteImmediate generates timestamp-based title', () => { @@ -224,7 +227,8 @@ describe('useNoteCreation hook', () => { expect(addEntry).toHaveBeenCalledTimes(1) expect(addEntry.mock.calls[0][0].title).toBe('Untitled Note 1700000000') expect(addEntry.mock.calls[0][0].filename).toBe('untitled-note-1700000000.md') - expect(openTabWithContent.mock.calls[0][1]).toBe('---\ntype: Note\nstatus: Active\n---\n\n# \n\n') + expect(addEntry.mock.calls[0][0].status).toBeNull() + expect(openTabWithContent.mock.calls[0][1]).toBe('---\ntype: Note\n---\n\n# \n\n') vi.restoreAllMocks() }) @@ -294,6 +298,8 @@ describe('useNoteCreation hook', () => { const { result } = renderHook(() => useNoteCreation(makeConfig(), tabDeps)) act(() => { result.current.handleCreateNoteImmediate('Project') }) expect(addEntry.mock.calls[0][0].isA).toBe('Project') + expect(addEntry.mock.calls[0][0].status).toBeNull() + expect(openTabWithContent.mock.calls[0][1]).toBe('---\ntype: Project\n---\n\n# \n\n## Objective\n\n\n\n## Key Results\n\n\n\n## Notes\n\n') }) it('handleCreateNoteImmediate slugifies custom type names for filenames', () => { diff --git a/src/hooks/useNoteCreation.ts b/src/hooks/useNoteCreation.ts index a06986fe..8b0c5f88 100644 --- a/src/hooks/useNoteCreation.ts +++ b/src/hooks/useNoteCreation.ts @@ -63,8 +63,6 @@ export function entryMatchesTarget({ entry, target }: EntryMatchParams): boolean return resolveEntry([entry], target) === entry } -const NO_STATUS_TYPES = new Set(['Topic', 'Person']) - /** Default templates for built-in types. Used when the type entry has no custom template. */ export const DEFAULT_TEMPLATES: Record = { Project: '## Objective\n\n\n\n## Key Results\n\n\n\n## Notes\n\n', @@ -118,7 +116,7 @@ export interface NewNoteParams { export function resolveNewNote({ title, type, vaultPath, template }: NewNoteParams): { entry: VaultEntry; content: string } { const slug = slugify(title) - const status = NO_STATUS_TYPES.has(type) ? null : 'Active' + const status = null const entry = buildNewEntry({ path: `${vaultPath}/${slug}.md`, slug, title, type, status }) return { entry, content: buildNoteContent({ title, type, status, template }) } } @@ -234,7 +232,7 @@ function createNoteImmediate(deps: ImmediateCreateDeps, type?: string): void { const slug = generateUntitledFilename(deps.entries, noteType, deps.pendingSlugs) const title = slug_to_title(slug) const template = resolveTemplate({ entries: deps.entries, typeName: noteType }) - const status = NO_STATUS_TYPES.has(noteType) ? null : 'Active' + const status = null const entry = buildNewEntry({ path: `${deps.vaultPath}/${slug}.md`, slug, title, type: noteType, status }) const content = buildNoteContent({ title: null, type: noteType, status, template, initialEmptyHeading: true }) deps.openTabWithContent(entry, content) diff --git a/tests/smoke/create-note-default-properties.spec.ts b/tests/smoke/create-note-default-properties.spec.ts new file mode 100644 index 00000000..ba802b31 --- /dev/null +++ b/tests/smoke/create-note-default-properties.spec.ts @@ -0,0 +1,17 @@ +import { test, expect } from '@playwright/test' +import { executeCommand, openCommandPalette } from './helpers' + +test('keyboard-created notes omit default status metadata @smoke', async ({ page }) => { + await page.goto('/') + await page.waitForSelector('[data-testid="sidebar-top-nav"]', { timeout: 10_000 }) + + await page.keyboard.press('Meta+n') + await expect(page.getByTestId('breadcrumb-filename-trigger')).toContainText(/untitled-note-\d+/i, { timeout: 5_000 }) + + await openCommandPalette(page) + await executeCommand(page, 'Toggle Raw') + + const rawEditor = page.locator('.cm-content') + await expect(rawEditor).toContainText('type: Note') + await expect(rawEditor).not.toContainText('status:') +})