import { expect, test } from '@playwright/test'; import { contextForUser } from './helpers'; /** * Search UI pack (issue #50). Adds body content to a page through the editor * (indexed by #49 via the collab persistence hook), then opens the search * palette with the "/" shortcut and checks that the content is found, the match * is highlighted, the scope toggle works, and Enter opens the page. * Language-independent selectors (CSS classes + unique content). */ const BASE_URL = process.env.E2E_BASE_URL ?? 'http://localhost:5173'; type Ctx = Awaited>; async function personalPond(context: Ctx): Promise<{ id: string; slug: string }> { const ponds = await context.request.get('/api/v1/ponds'); const pond = (await ponds.json()).find((p: { type: string }) => p.type === 'personal'); return { id: pond.id, slug: pond.slug }; } test('search finds page content, highlights it, and is keyboard-operable', async ({ browser }) => { const context = await contextForUser(browser, BASE_URL, 'fixture-user'); const pond = await personalPond(context); const ts = Date.now(); const word = `srchword${ts}`; const title = `Search Page ${ts}`; const created = await ( await context.request.post(`/api/v1/ponds/${pond.id}/pages`, { data: { title } }) ).json(); const page = await context.newPage(); await page.goto(`/p/${pond.slug}/${created.slug}`); // Add body content through the editor, then reload to flush it to the index. await page.locator('.editor-page__mode-toggle').click(); const body = page.locator('.editor-content .ProseMirror'); await body.click(); await page.keyboard.type(`the unique ${word} lives in this body`); await page.reload(); await expect(page.locator('.editor-content')).toContainText(word); // The reload already landed back in read mode (the mode state resets), so // "/" acts as the global shortcut here. This spec used to click the mode // toggle again "to leave edit mode" — which actually RE-ENTERED it; that // passed only while entering edit mode left focus on the toggle button. // Since the editor grabs focus on entering edit mode (PR #140), "/" would // become ordinary editor input there, racing the deferred focus — the // intermittent-then-persistent failure of this pack. // Open search with the "/" shortcut. await page.keyboard.press('/'); const palette = page.locator('.search-palette'); await expect(palette).toBeVisible(); await palette.locator('.search-palette__input').fill(word); const result = page.locator('.search-result', { hasText: title }); await expect(result).toBeVisible(); // The matched word is highlighted in the snippet. await expect(page.locator('.search-result__snippet mark')).toBeVisible(); // Scope toggle is present and keeps the result (page is in the user's ponds). await palette.locator('.search-palette__scope input[type="checkbox"]').first().check(); await expect(page.locator('.search-result', { hasText: title })).toBeVisible(); // Enter opens the selected result. await palette.locator('.search-palette__input').press('Enter'); await expect(page).toHaveURL(new RegExp(`/p/${pond.slug}/${created.slug}$`)); await context.close(); });