44a2d34bbddd
fix: contain device-trust alert banners inside the 320px shell (v4.8.7)
- time
- 2026-08-07 22:08 UTC · 2 months ago
- machine
- koh2
- parent
- 65feee9c1752
↓ peach-browser-44a2d34b.tar.gzatlas at this save
files changed5 files
manifest.firefox.json+1 −1manifest.json+1 −1package.json+1 −1src/popup/styles/popup.css+7 −0tests/sync-alerts.spec.ts+71 −0manifest.firefox.json+1 −1
@@ -1,7 +1,7 @@11 {22 "manifest_version": 3,33 "name": "Peach Password Manager",4- "version": "4.8.6",4+ "version": "4.8.7",55 "description": "Zero-knowledge password manager",66 "browser_specific_settings": {77 "gecko": {manifest.json+1 −1
@@ -2,7 +2,7 @@22 "manifest_version": 3,33 "minimum_chrome_version": "116",44 "name": "Peach Password Manager",5- "version": "4.8.6",5+ "version": "4.8.7",66 "description": "Zero-knowledge password manager",77 "action": {88 "default_popup": "src/popup/index.html",package.json+1 −1
@@ -1,6 +1,6 @@11 {22 "name": "peach",3- "version": "4.8.6",3+ "version": "4.8.7",44 "description": "Zero-knowledge password manager",55 "license": "GPL-3.0-only",66 "type": "module",src/popup/styles/popup.css+7 −0
@@ -671,6 +671,10 @@671671 flex-direction: column;672672 gap: 6px;673673 padding: 8px 12px 0;674+ /* Grid item of .peach-shell: without a zero min-width the nowrap alert text675+ sizes this item to its min-content, blowing the fixed-width shell past676+ 320px and clipping/distorting everything else in it. */677+ min-width: 0;674678 }675679 .peach-sync-alert {676680 display: flex;@@ -678,11 +682,14 @@678682 gap: 8px;679683 padding: 8px 10px;680684 border-radius: 7px;685+ min-width: 0;686+ max-width: 100%;681687 background: color-mix(in srgb, #C8A840 14%, transparent);682688 border: 1px solid color-mix(in srgb, #C8A840 38%, transparent);683689 }684690 .peach-sync-alert-text {685691 flex: 1;692+ min-width: 0;686693 font-family: "IBM Plex Mono", "SFMono-Regular", monospace;687694 font-size: 10px;688695 line-height: 1.45;tests/sync-alerts.spec.ts+71 −0
@@ -0,0 +1,71 @@1+import { test, expect, BrowserContext } from "@playwright/test";2+import { makeContext, setupVault, waitForSW } from "./helpers/vault";3+4+// 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.8+test.describe.configure({ timeout: 120_000 });9+10+test.describe("Sync Alerts", () => {11+ let ctx: BrowserContext;12+ test.afterEach(async () => { await ctx.close(); });13+14+ 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();18+19+ 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);36+37+ // A fresh popup boots unlocked and consumes the pending alert queue.38+ const extId = await waitForSW(ctx);39+ const p2 = await ctx.newPage();40+ await p2.goto(`chrome-extension://${extId}/src/popup/index.html`);41+ await expect(p2.locator(".peach-sync-alert")).toHaveCount(2, { timeout: 20000 });42+43+ const geo = await p2.evaluate(() => {44+ const shell = document.querySelector(".peach-shell")!;45+ const shellRect = shell.getBoundingClientRect();46+ const rows = [...document.querySelectorAll(".peach-sync-alert")].map((r) => {47+ const rrect = r.getBoundingClientRect();48+ const text = r.querySelector(".peach-sync-alert-text") as HTMLElement;49+ return {50+ rowLeftDelta: rrect.left - shellRect.left,51+ rowRightDelta: rrect.right - shellRect.right,52+ textScrollW: text.scrollWidth,53+ textClientW: text.clientWidth,54+ };55+ });56+ return { shellScrollW: shell.scrollWidth, rows };57+ });58+59+ // The shell is designed at 320px; the alert blowout stretched its scroll60+ // surface past 1000px. It must never exceed the design width.61+ expect(geo.shellScrollW).toBeLessThanOrEqual(320);62+63+ // Every alert row stays inside the shell, and the nowrap text truncates64+ // (ellipsis) instead of widening its row.65+ for (const row of geo.rows) {66+ expect(row.rowLeftDelta).toBeGreaterThanOrEqual(-1);67+ expect(row.rowRightDelta).toBeLessThanOrEqual(1);68+ expect(row.textScrollW).toBeGreaterThan(row.textClientW);69+ }70+ });71+});