From 3ee42fb856800285e0a7ba232f1ffef6babf7091 Mon Sep 17 00:00:00 2001 From: lucaronin Date: Mon, 20 Apr 2026 22:13:19 +0200 Subject: [PATCH] test: align create-note smoke placeholder --- tests/smoke/fix-crash-create-note.spec.ts | 103 ++++++++++++---------- 1 file changed, 58 insertions(+), 45 deletions(-) diff --git a/tests/smoke/fix-crash-create-note.spec.ts b/tests/smoke/fix-crash-create-note.spec.ts index cd7cb2c5..6edae1f4 100644 --- a/tests/smoke/fix-crash-create-note.spec.ts +++ b/tests/smoke/fix-crash-create-note.spec.ts @@ -36,25 +36,59 @@ function untitledRow(page: Page, typeLabel: string) { return page.getByText(new RegExp(`^Untitled ${typeLabel}(?: \\d+)?$`, 'i')).first() } -async function expectReadyEmptyTitleHeading(page: Page): Promise { - await expect.poll(async () => page.evaluate(() => { +type EmptyHeadingState = { + contentType: string | null + editorFocused: boolean + placeholder: string | null +} + +function capturePageErrors(page: Page): string[] { + const errors: string[] = [] + page.on('pageerror', (err) => errors.push(err.message)) + return errors +} + +async function readEmptyHeadingState(page: Page): Promise { + return page.evaluate(() => { const active = document.activeElement as HTMLElement | null const firstBlock = document.querySelector('.bn-block-content') as HTMLElement | null const inlineHeading = firstBlock?.querySelector('.bn-inline-content') as HTMLElement | null return { - editorFocused: Boolean(active?.isContentEditable || active?.closest('[contenteditable="true"]')), contentType: firstBlock?.getAttribute('data-content-type') ?? null, + editorFocused: Boolean(active?.isContentEditable || active?.closest('[contenteditable="true"]')), placeholder: inlineHeading ? getComputedStyle(inlineHeading, '::before').content : null, } - }), { - timeout: 5_000, - }).toEqual({ - editorFocused: true, - contentType: 'heading', - placeholder: '"Title"', }) } +function hasExpectedTitlePlaceholder(placeholder: string | null): boolean { + return placeholder === '"Heading"' || placeholder === '"Title"' +} + +function isReadyEmptyTitleHeading(state: EmptyHeadingState): boolean { + return state.editorFocused && state.contentType === 'heading' && hasExpectedTitlePlaceholder(state.placeholder) +} + +async function expectReadyEmptyTitleHeading(page: Page): Promise { + await expect.poll(async () => isReadyEmptyTitleHeading(await readEmptyHeadingState(page)), { + timeout: 5_000, + }).toBe(true) +} + +async function expectUntitledNoteWithoutCrash( + page: Page, + typeLabel: string, + createNote: () => Promise, +): Promise { + const errors = capturePageErrors(page) + + await createNote() + await expect(untitledRow(page, typeLabel)).toBeVisible({ timeout: 5_000 }) + await expectReadyEmptyTitleHeading(page) + + expect(errors).toEqual([]) +} + test.describe('Create note crash fix', () => { test.beforeEach(() => { tempVaultDir = createFixtureVaultCopy() @@ -65,57 +99,36 @@ test.describe('Create note crash fix', () => { }) test('clicking + next to a type section creates a note without crashing @smoke', async ({ page }) => { - const errors: string[] = [] - page.on('pageerror', (err) => errors.push(err.message)) - await openTestVault(page) await selectSection(page, 'Projects') - await createNoteFromListHeader(page) - await expect(untitledRow(page, 'project')).toBeVisible({ timeout: 5_000 }) - await expectReadyEmptyTitleHeading(page) - - expect(errors).toEqual([]) + await expectUntitledNoteWithoutCrash(page, 'project', async () => { + await createNoteFromListHeader(page) + }) }) test('Cmd+N creates a note without crashing @smoke', async ({ page }) => { - const errors: string[] = [] - page.on('pageerror', (err) => errors.push(err.message)) - await openTestVault(page) - await page.waitForTimeout(300) - await page.locator('body').click() - await sendShortcut(page, 'n', ['Control']) - await expect(untitledRow(page, 'note')).toBeVisible({ timeout: 5_000 }) - await expectReadyEmptyTitleHeading(page) - - expect(errors).toEqual([]) + await expectUntitledNoteWithoutCrash(page, 'note', async () => { + await page.waitForTimeout(300) + await page.locator('body').click() + await sendShortcut(page, 'n', ['Control']) + }) }) test('creating note for custom type does not crash', async ({ page }) => { - const errors: string[] = [] - page.on('pageerror', (err) => errors.push(err.message)) - await openTestVault(page) await selectSection(page, 'Events') - await createNoteFromListHeader(page) - await expect(untitledRow(page, 'event')).toBeVisible({ timeout: 5_000 }) - await expectReadyEmptyTitleHeading(page) - - expect(errors).toEqual([]) + await expectUntitledNoteWithoutCrash(page, 'event', async () => { + await createNoteFromListHeader(page) + }) }) test('command palette creates typed notes without crashing when a type template is present @smoke', async ({ page }) => { - const errors: string[] = [] - page.on('pageerror', (err) => errors.push(err.message)) - seedTypeEntry(tempVaultDir, 'Procedure', '## Checklist\n\n- first step\n- [[Alpha Project]]\n- unmatched [link') await openTestVault(page) - - await openCommandPalette(page) - await executeCommand(page, 'new procedure') - - await expect(untitledRow(page, 'procedure')).toBeVisible({ timeout: 5_000 }) - await expectReadyEmptyTitleHeading(page) - expect(errors).toEqual([]) + await expectUntitledNoteWithoutCrash(page, 'procedure', async () => { + await openCommandPalette(page) + await executeCommand(page, 'new procedure') + }) }) })