sync-alerts.spec.ts

2.9 KB · raw

1import { test, expect, BrowserContext } from "@playwright/test";2import { makeContext, setupVault } from "./helpers/vault";34// Device-trust alerts (DEVICE_REVOKED / DEVICE_KEY_ROTATED) carry peer-supplied5// device names. A long or unbreakable name must never widen the fixed-width6// extension shell — that regressed as a >1000px scroll surface in a 320px7// popup, clipping and distorting everything else in the shell.8test.describe.configure({ timeout: 120_000 });910test.describe("Sync Alerts", () => {11  let ctx: BrowserContext;12  test.afterEach(async () => { await ctx.close(); });1314  test("SA01 - long device names stay contained inside the shell", async () => {15    ctx = await makeContext();16    const { popup } = await setupVault(ctx);17    await expect(popup.locator(".peach-lock-btn[aria-label='Lock vault']")).toBeVisible();1819    const alerts = [20      {21        type: "DEVICE_REVOKED",22        entryId: "",23        entryTitle: "",24        deviceName: "June's MacBook Pro (16-inch, M4 Max, 2024, Work Profile)",25        timestamp: Date.now(),26      },27      {28        type: "DEVICE_KEY_ROTATED",29        entryId: "",30        entryTitle: "",31        deviceName: "Android-Backup-Device-With-An-Extremely-Long-Unbreakable-Identifier-0123456789",32        timestamp: Date.now(),33      },34    ];35    await popup.evaluate((a) => chrome.storage.local.set({ peach_pending_sync_alerts_v1: a }), alerts);3637    // The header sync refresh reloads the pending alert queue on this page,38    // so the banners render on the same steady-state 320px popup.39    await popup.locator(".peach-sync-btn").click();40    await expect(popup.locator(".peach-sync-alert")).toHaveCount(2, { timeout: 20000 });4142    const geo = await popup.evaluate(() => {43      const shell = document.querySelector(".peach-shell")!;44      const shellRect = shell.getBoundingClientRect();45      const rows = [...document.querySelectorAll(".peach-sync-alert")].map((r) => {46        const rrect = r.getBoundingClientRect();47        const text = r.querySelector(".peach-sync-alert-text") as HTMLElement;48        return {49          rowLeftDelta: rrect.left - shellRect.left,50          rowRightDelta: rrect.right - shellRect.right,51          textScrollW: text.scrollWidth,52          textClientW: text.clientWidth,53        };54      });55      return {56        shellClientW: shell.clientWidth,57        shellScrollW: shell.scrollWidth,58        rows,59      };60    });6162    // No horizontal scroll surface: the pre-fix blowout measured 1105 here.63    expect(geo.shellScrollW).toBeLessThanOrEqual(geo.shellClientW + 1);6465    // Every alert row stays inside the shell, and the nowrap text truncates66    // (ellipsis) instead of widening its row.67    for (const row of geo.rows) {68      expect(row.rowLeftDelta).toBeGreaterThanOrEqual(-1);69      expect(row.rowRightDelta).toBeLessThanOrEqual(1);70      expect(row.textScrollW).toBeGreaterThan(row.textClientW);71    }72  });73});