experiments in a post-browser web
10
fork

Configure Feed

Select the types of activity you want to include in your feed.

test(datastore): regression guard for inline hashtag extraction in note bodies

Adds desktop e2e coverage that addItem/updateItem with `#tag` content
applies tags via syncContentHashtags. Guards against regression of the
note-flow hashtag extraction; was reported broken before the unified
extraction fix landed.

+71
+71
tests/desktop/note-hashtag-extraction.spec.ts
··· 1 + /** 2 + * Regression coverage: typing `note buy milk #shopping #urgent` in the 3 + * cmd panel must extract `#shopping` and `#urgent` as tags on the new 4 + * text item. The user reported tags inside note bodies weren't picked 5 + * up; the fix lives in `syncContentHashtags` in datastore.ts (called 6 + * from addItem/updateItem). This guards against regressions if anyone 7 + * removes that call or breaks the regex. 8 + */ 9 + import { test, expect, DesktopApp } from '../fixtures/desktop-app'; 10 + import { Page } from '@playwright/test'; 11 + import { createPerDescribeApp } from '../helpers/test-app'; 12 + 13 + test.describe('note flow: inline hashtag extraction @desktop', () => { 14 + let app: DesktopApp; 15 + let bgWindow: Page; 16 + 17 + test.beforeAll(async () => { 18 + ({ app, bgWindow } = await createPerDescribeApp('note-hashtag')); 19 + }); 20 + 21 + test.afterAll(async () => { 22 + if (app) await app.close(); 23 + }); 24 + 25 + test('addItem with hashtag content extracts tags', async () => { 26 + const stamp = Date.now(); 27 + const tagA = `inline-shop-${stamp}`; 28 + const tagB = `inline-urge-${stamp}`; 29 + const content = `buy milk #${tagA} #${tagB}`; 30 + 31 + const addResult = await bgWindow.evaluate(async (c: string) => { 32 + return await (window as any).app.datastore.addItem('text', { content: c }); 33 + }, content); 34 + expect(addResult.success).toBe(true); 35 + const itemId = addResult.data?.id; 36 + expect(itemId).toBeTruthy(); 37 + 38 + // Tags should be applied synchronously by syncContentHashtags 39 + const tagsResult = await bgWindow.evaluate(async (id: string) => { 40 + return await (window as any).app.datastore.getItemTags(id); 41 + }, itemId); 42 + expect(tagsResult.success).toBe(true); 43 + const names: string[] = (tagsResult.data || []).map((t: { name: string }) => t.name); 44 + expect(names).toContain(tagA); 45 + expect(names).toContain(tagB); 46 + }); 47 + 48 + test('updateItem with new hashtag content extracts new tags', async () => { 49 + const stamp = Date.now(); 50 + const tagInitial = `init-${stamp}`; 51 + const tagAdded = `added-${stamp}`; 52 + 53 + const addResult = await bgWindow.evaluate(async (c: string) => { 54 + return await (window as any).app.datastore.addItem('text', { content: c }); 55 + }, `start #${tagInitial}`); 56 + expect(addResult.success).toBe(true); 57 + const itemId = addResult.data?.id; 58 + 59 + const updResult = await bgWindow.evaluate(async ({ id, c }: { id: string; c: string }) => { 60 + return await (window as any).app.datastore.updateItem(id, { content: c }); 61 + }, { id: itemId, c: `start #${tagInitial}\nlater #${tagAdded}` }); 62 + expect(updResult.success).toBe(true); 63 + 64 + const tagsResult = await bgWindow.evaluate(async (id: string) => { 65 + return await (window as any).app.datastore.getItemTags(id); 66 + }, itemId); 67 + const names: string[] = (tagsResult.data || []).map((t: { name: string }) => t.name); 68 + expect(names).toContain(tagInitial); 69 + expect(names).toContain(tagAdded); 70 + }); 71 + });