import { expect, test, type Page } from "@playwright/test"; import { installRoutes } from "./helpers"; // Alias suggestion chip in the search builder. The viewer fetches // /search-aliases.json (global merged with per-site at compose time); when a // typed term matches a known trigger, a non-forcing chip offers a better regex. const ALIASES = { aliases: [ { id: "loli", label: "loli", triggers: ["loli", "lolly", "loly"], suggestion: "\\blol(i|ly)", useRegex: true, note: "AI transcription often expands this.", }, { id: "platner", label: "Graham Platner", triggers: ["graham platner"], suggestion: "graham\\s+platner", useRegex: true, }, ], }; async function seedAliases(page: Page) { await installRoutes(page); // Registered after installRoutes so it wins over the empty default. await page.route("**/search-aliases.json", async (route) => { await route.fulfill({ status: 200, contentType: "application/json", body: JSON.stringify(ALIASES), }); }); } const firstLeaf = (page: Page) => page.locator('input[data-testid^="leaf-query-"]').first(); test.describe("search alias suggestions", () => { test.beforeEach(async ({ page }) => { await seedAliases(page); }); test("typing a known trigger offers the suggestion; Apply swaps in the regex", async ({ page, }) => { await page.goto("/"); await firstLeaf(page).fill("loli"); // The chip appears, labeled by concept and showing the suggested pattern. const chip = page.locator('[data-testid^="leaf-alias-suggestions-"]'); await expect(chip).toBeVisible(); await expect(chip).toContainText("loli"); await expect(chip.locator("code")).toHaveText("\\blol(i|ly)"); // Apply swaps the query and flips on regex mode. await page.locator('[data-testid^="leaf-alias-apply-"]').click(); await expect(firstLeaf(page)).toHaveValue("\\blol(i|ly)"); await expect( page.locator('[data-testid^="leaf-regex-"]').first(), ).toHaveAttribute("aria-checked", "true"); // In regex mode the suggestion is suppressed (the user owns their pattern). await expect(chip).toHaveCount(0); }); test("a multi-word trigger offers the suggestion; Apply swaps in the regex", async ({ page, }) => { await page.goto("/"); await firstLeaf(page).fill("graham platner"); const chip = page.locator('[data-testid^="leaf-alias-suggestions-"]'); await expect(chip).toBeVisible(); await expect(chip).toContainText("Graham Platner"); await expect(chip.locator("code")).toHaveText("graham\\s+platner"); await page.locator('[data-testid^="leaf-alias-apply-"]').click(); await expect(firstLeaf(page)).toHaveValue("graham\\s+platner"); await expect( page.locator('[data-testid^="leaf-regex-"]').first(), ).toHaveAttribute("aria-checked", "true"); // The applied pattern is not a bare literal, so it is not re-offered. await expect(chip).toHaveCount(0); }); test("does not fire on a mere substring (whole-token match only)", async ({ page, }) => { await page.goto("/"); await firstLeaf(page).fill("lolight"); await expect( page.locator('[data-testid^="leaf-alias-suggestions-"]'), ).toHaveCount(0); }); test("Dismiss hides the suggestion; a new term re-offers", async ({ page, }) => { await page.goto("/"); const leaf = firstLeaf(page); await leaf.fill("loli"); const chip = page.locator('[data-testid^="leaf-alias-suggestions-"]'); await expect(chip).toBeVisible(); await page.locator('[data-testid^="leaf-alias-dismiss-"]').click(); await expect(chip).toHaveCount(0); // A different trigger for the same concept re-offers it. await leaf.fill("lolly"); await expect(chip).toBeVisible(); }); });