From d5ebbab6a56228b86d2eb0ea30f172271e580651 Mon Sep 17 00:00:00 2001 From: th Date: Wed, 15 Apr 2026 21:53:49 +0200 Subject: [PATCH] tests: assert journal entries don't get the local pulse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Covers the board.js journal exemption on the 1× card-pulse-local flash. Creates two probe cards via the raw API, flags both as "just created locally" in state.recentlyCreatedIds, runs a render, then asserts that the journal-format one (title 9999-12-31 — a year we can't collide with real entries) skipped the pulse class while the __prefixed__ control card still got it. Both probes are deleted in a finally block so a failed assertion doesn't leave them behind for later suites. Co-Authored-By: Claude Opus 4.6 (1M context) --- public/plugins/tests/board.test.js | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/public/plugins/tests/board.test.js b/public/plugins/tests/board.test.js index 22df825..687947e 100644 --- a/public/plugins/tests/board.test.js +++ b/public/plugins/tests/board.test.js @@ -184,3 +184,50 @@ describe('Board: Focus restoration after overlay close', () => { expect(document.querySelector('#board .card-focused')).toExist(); }); }); + +describe('Board: new-card pulse', () => { + // Journal entries shouldn't get the 1× card-pulse-local flash — + // they're daily-log jottings, not "new thing" moments. We use + // title "9999-12-31" for the journal probe to ensure we can't + // collide with a real user entry; a control card with a + // __prefixed__ title verifies the pulse still fires for normal + // local creations. + + it('locally-created journal-format cards skip the pulse', async () => { + const token = csrf(); + const hJson = { 'Content-Type': 'application/json', 'X-CSRF-Token': token }; + const hCsrf = { 'X-CSRF-Token': token }; + let journal, control; + try { + journal = await fetch('api/cards', { method: 'POST', headers: hJson, body: JSON.stringify({ title: '9999-12-31', body: '' }) }).then(r => r.json()); + control = await fetch('api/cards', { method: 'POST', headers: hJson, body: JSON.stringify({ title: '__test_pulse_ctrl__', body: '' }) }).then(r => r.json()); + expect(journal?.id).toExist(); + expect(control?.id).toExist(); + + // Flag both as "just created locally" so renderBoard routes + // them through the local-pulse branch. The journal + // exemption then has to filter out the journal one. + window.state.recentlyCreatedIds.add(String(journal.id)); + window.state.recentlyCreatedIds.add(String(control.id)); + await window._reloadAll(); + // Wait past the rAF tick so pulse classes have been + // applied, but well within the 900ms lifetime so we + // can still observe them. + await sleep(150); + + const journalEl = document.querySelector(`.board-card[data-id="${journal.id}"]`); + const controlEl = document.querySelector(`.board-card[data-id="${control.id}"]`); + expect(journalEl).toExist(); + expect(controlEl).toExist(); + expect(journalEl.classList.contains('card-pulse-local')).toBe(false); + expect(controlEl.classList.contains('card-pulse-local')).toBe(true); + } finally { + // Clean up even on failure. Backup/restore would catch it + // eventually, but between tests we don't want a stray + // 9999-12-31 card floating around upsetting other suites. + if (journal?.id) await fetch(`api/cards/${journal.id}`, { method: 'DELETE', headers: hCsrf }); + if (control?.id) await fetch(`api/cards/${control.id}`, { method: 'DELETE', headers: hCsrf }); + await window._reloadAll?.(); + } + }); +});