import { test, expect, BrowserContext } from "@playwright/test"; import { makeContext, setupVault } from "./helpers/vault"; // Device-trust alerts (DEVICE_REVOKED / DEVICE_KEY_ROTATED) carry peer-supplied // device names. A long or unbreakable name must never widen the fixed-width // extension shell — that regressed as a >1000px scroll surface in a 320px // popup, clipping and distorting everything else in the shell. test.describe.configure({ timeout: 120_000 }); test.describe("Sync Alerts", () => { let ctx: BrowserContext; test.afterEach(async () => { await ctx.close(); }); test("SA01 - long device names stay contained inside the shell", async () => { ctx = await makeContext(); const { popup } = await setupVault(ctx); await expect(popup.locator(".peach-lock-btn[aria-label='Lock vault']")).toBeVisible(); const alerts = [ { type: "DEVICE_REVOKED", entryId: "", entryTitle: "", deviceName: "June's MacBook Pro (16-inch, M4 Max, 2024, Work Profile)", timestamp: Date.now(), }, { type: "DEVICE_KEY_ROTATED", entryId: "", entryTitle: "", deviceName: "Android-Backup-Device-With-An-Extremely-Long-Unbreakable-Identifier-0123456789", timestamp: Date.now(), }, ]; await popup.evaluate((a) => chrome.storage.local.set({ peach_pending_sync_alerts_v1: a }), alerts); // The header sync refresh reloads the pending alert queue on this page, // so the banners render on the same steady-state 320px popup. await popup.locator(".peach-sync-btn").click(); await expect(popup.locator(".peach-sync-alert")).toHaveCount(2, { timeout: 20000 }); const geo = await popup.evaluate(() => { const shell = document.querySelector(".peach-shell")!; const shellRect = shell.getBoundingClientRect(); const rows = [...document.querySelectorAll(".peach-sync-alert")].map((r) => { const rrect = r.getBoundingClientRect(); const text = r.querySelector(".peach-sync-alert-text") as HTMLElement; return { rowLeftDelta: rrect.left - shellRect.left, rowRightDelta: rrect.right - shellRect.right, textScrollW: text.scrollWidth, textClientW: text.clientWidth, }; }); return { shellClientW: shell.clientWidth, shellScrollW: shell.scrollWidth, rows, }; }); // No horizontal scroll surface: the pre-fix blowout measured 1105 here. expect(geo.shellScrollW).toBeLessThanOrEqual(geo.shellClientW + 1); // Every alert row stays inside the shell, and the nowrap text truncates // (ellipsis) instead of widening its row. for (const row of geo.rows) { expect(row.rowLeftDelta).toBeGreaterThanOrEqual(-1); expect(row.rowRightDelta).toBeLessThanOrEqual(1); expect(row.textScrollW).toBeGreaterThan(row.textClientW); } }); });