Files
tolaria/tests/smoke/exclude-trashed-from-search.spec.ts
lucaronin db66e7c9da fix: scope Playwright selectors to dialog overlays to avoid sidebar matches
The `span.truncate` selector was matching sidebar note titles in addition
to search results, causing false positives in the full-text search test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 12:59:57 +01:00

112 lines
4.3 KiB
TypeScript

import { test, expect } from '@playwright/test'
import { sendShortcut } from './helpers'
const QUICK_OPEN_INPUT = 'input[placeholder="Search notes..."]'
const SEARCH_INPUT = 'input[placeholder="Search in all notes..."]'
/** Known trashed note titles from mock data */
const TRASHED_TITLES = ['Old Draft Notes', 'Deprecated API Notes', 'Failed SEO Experiment']
/** Query specific enough to find a known active note */
const ACTIVE_QUERY = 'Laputa App'
async function openQuickOpen(page: import('@playwright/test').Page) {
await page.locator('body').click()
await sendShortcut(page, 'p', ['Control'])
await expect(page.locator(QUICK_OPEN_INPUT)).toBeVisible()
}
/** Get result titles scoped to a specific container (avoids matching sidebar items). */
function getResultTitles(container: import('@playwright/test').Locator) {
return container.locator('span.truncate').allTextContents()
}
/** The Quick Open dialog overlay */
function quickOpenPanel(page: import('@playwright/test').Page) {
return page.locator('.fixed.inset-0').filter({ has: page.locator(QUICK_OPEN_INPUT) })
}
/** The full-text search dialog overlay */
function searchPanel(page: import('@playwright/test').Page) {
return page.locator('.fixed.inset-0').filter({ has: page.locator(SEARCH_INPUT) })
}
test.describe('Exclude trashed notes from search and autocomplete', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/')
await page.waitForLoadState('networkidle')
})
test('trashed notes do not appear in Quick Open search', async ({ page }) => {
await openQuickOpen(page)
const panel = quickOpenPanel(page)
for (const title of TRASHED_TITLES) {
// Use a unique enough substring to trigger results
const query = title.split(' ')[0]
await page.locator(QUICK_OPEN_INPUT).fill(query)
await page.waitForTimeout(400)
const titles = await getResultTitles(panel)
expect(titles, `"${title}" should not appear for query "${query}"`).not.toContain(title)
}
})
test('active notes still appear in Quick Open search', async ({ page }) => {
await openQuickOpen(page)
const panel = quickOpenPanel(page)
await page.locator(QUICK_OPEN_INPUT).fill(ACTIVE_QUERY)
await page.waitForTimeout(400)
const titles = await getResultTitles(panel)
expect(titles.some(t => t.includes('Laputa App'))).toBe(true)
})
test('trashed notes do not appear in full-text search', async ({ page }) => {
// Full-text search panel opened via Ctrl/Cmd+Shift+F
const searchVisible = async () => {
await page.locator('body').click()
await sendShortcut(page, 'f', ['Control', 'Shift'])
try {
await expect(page.locator(SEARCH_INPUT)).toBeVisible({ timeout: 2000 })
return true
} catch { return false }
}
if (!await searchVisible()) {
// Retry with Meta (macOS Cmd key) in case Playwright routes it differently
await sendShortcut(page, 'f', ['Meta', 'Shift'])
try {
await expect(page.locator(SEARCH_INPUT)).toBeVisible({ timeout: 2000 })
} catch {
test.skip()
return
}
}
await page.locator(SEARCH_INPUT).fill('Old Draft')
await page.waitForTimeout(600)
const titles = await getResultTitles(searchPanel(page))
expect(titles).not.toContain('Old Draft Notes')
})
test('wikilink autocomplete does not suggest trashed notes', async ({ page }) => {
// Open any note first (click the first note in the sidebar)
const firstNote = page.locator('[data-testid="note-item"]').first()
if (await firstNote.isVisible()) {
await firstNote.click()
await page.waitForTimeout(300)
}
// Focus the editor and type [[ to trigger autocomplete
const editor = page.locator('.bn-editor').first()
if (await editor.isVisible()) {
await editor.click()
await page.keyboard.type('[[Old Draft')
await page.waitForTimeout(500)
// Check autocomplete suggestions - should not contain the trashed note
const suggestions = page.locator('.bn-suggestion-menu [class*="item"], .bn-suggestion-menu button, [data-testid="wikilink-suggestion"]')
const count = await suggestions.count()
for (let i = 0; i < count; i++) {
const text = await suggestions.nth(i).textContent()
expect(text).not.toContain('Old Draft Notes')
}
}
})
})