1import { test, expect, BrowserContext } from "@playwright/test";2import { fileURLToPath } from "url";3import { dirname, join } from "path";4import os from "os";5import fs from "fs/promises";67const __filename = fileURLToPath(import.meta.url);8const __dirname = dirname(__filename);9const EXTENSION_PATH = join(__dirname, "..", "dist");1011async function makeContext() {12 const { chromium } = await import("playwright");13 const userDataDir = join(os.tmpdir(), `peach-set-${Date.now()}`);14 await fs.mkdir(userDataDir, { recursive: true });15 return chromium.launchPersistentContext(userDataDir, {16 headless: false,17 args: [`--load-extension=${EXTENSION_PATH}`, `--disable-extensions-except=${EXTENSION_PATH}`],18 });19}2021async function waitForSW(ctx: BrowserContext, maxWait = 15000): Promise<string> {22 const start = Date.now();23 let sw = ctx.serviceWorkers()[0];24 while (!sw && Date.now() - start < maxWait) {25 await new Promise(r => setTimeout(r, 500));26 sw = ctx.serviceWorkers()[0];27 }28 if (!sw) throw new Error(`No SW after ${maxWait}ms`);29 return new URL(sw.url()).host;30}3132async function setupVault(ctx: BrowserContext): Promise<{ popup: any, extId: string }> {33 const extId = await waitForSW(ctx);34 const popup = await ctx.newPage();35 await popup.goto(`chrome-extension://${extId}/src/popup/index.html`);36 await popup.waitForTimeout(3000);37 const pw = popup.locator("#master-password");38 if (await pw.isVisible()) {39 await pw.fill("password123");40 await popup.locator("#confirm-password").fill("password123");41 await popup.getByRole("button", { name: /create vault/i }).click();42 await popup.waitForTimeout(2000);43 }44 return { popup, extId };45}4647test.describe("Auto-Lock Configuration", () => {48 let ctx: BrowserContext;49 test.afterEach(async () => { await ctx.close(); });50 test.beforeEach(async () => { ctx = await makeContext(); });5152 test("AUL01 - auto-lock setting exists in settings", async () => {53 const { popup } = await setupVault(ctx);54 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();55 await popup.waitForTimeout(500);56 const autoLock = popup.locator("text=auto-lock").first();57 await expect(autoLock).toBeVisible();58 await ctx.close();59 });6061 test("AUL02 - auto-lock options: 1 minute", async () => {62 const { popup } = await setupVault(ctx);63 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();64 await popup.waitForTimeout(500);65 await popup.locator("text=auto-lock").click();66 await popup.waitForTimeout(300);67 const options = popup.locator("[role='option' i], [role='menuitem' i], .peach-select-option");68 const optionTexts = await options.allTextContents();69 const has1Min = optionTexts.some((t: string) => t.toLowerCase().includes("1 min") || t.toLowerCase().includes("1 minute"));70 expect(has1Min).toBeTruthy();71 await ctx.close();72 });7374 test("AUL03 - auto-lock options: 5 minutes", async () => {75 const { popup } = await setupVault(ctx);76 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();77 await popup.waitForTimeout(500);78 await popup.locator("text=auto-lock").click();79 await popup.waitForTimeout(300);80 const options = popup.locator("[role='option' i], [role='menuitem' i], .peach-select-option");81 const optionTexts = await options.allTextContents();82 const has5Min = optionTexts.some((t: string) => t.toLowerCase().includes("5 min") || t.toLowerCase().includes("5 minute"));83 expect(has5Min).toBeTruthy();84 await ctx.close();85 });8687 test("AUL04 - auto-lock options: 15 minutes", async () => {88 const { popup } = await setupVault(ctx);89 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();90 await popup.waitForTimeout(500);91 await popup.locator("text=auto-lock").click();92 await popup.waitForTimeout(300);93 const options = popup.locator("[role='option' i], [role='menuitem' i], .peach-select-option");94 const optionTexts = await options.allTextContents();95 const has15Min = optionTexts.some((t: string) => t.toLowerCase().includes("15 min") || t.toLowerCase().includes("15 minute"));96 expect(has15Min).toBeTruthy();97 await ctx.close();98 });99100 test("AUL05 - auto-lock options: 1 hour", async () => {101 const { popup } = await setupVault(ctx);102 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();103 await popup.waitForTimeout(500);104 await popup.locator("text=auto-lock").click();105 await popup.waitForTimeout(300);106 const options = popup.locator("[role='option' i], [role='menuitem' i], .peach-select-option");107 const optionTexts = await options.allTextContents();108 const has1Hr = optionTexts.some((t: string) => t.toLowerCase().includes("1 hour") || t.toLowerCase().includes("1 hr"));109 expect(has1Hr).toBeTruthy();110 await ctx.close();111 });112113 test("AUL06 - auto-lock options: never", async () => {114 const { popup } = await setupVault(ctx);115 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();116 await popup.waitForTimeout(500);117 await popup.locator("text=auto-lock").click();118 await popup.waitForTimeout(300);119 const options = popup.locator("[role='option' i], [role='menuitem' i], .peach-select-option");120 const optionTexts = await options.allTextContents();121 const hasNever = optionTexts.some((t: string) => t.toLowerCase().includes("never"));122 expect(hasNever).toBeTruthy();123 await ctx.close();124 });125126 test("AUL07 - selecting auto-lock option closes dropdown", async () => {127 const { popup } = await setupVault(ctx);128 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();129 await popup.waitForTimeout(500);130 await popup.locator("text=auto-lock").click();131 await popup.waitForTimeout(300);132 const option = popup.locator("[role='option' i], [role='menuitem' i], .peach-select-option").first();133 await option.click();134 await popup.waitForTimeout(300);135 const dropdown = popup.locator("[role='listbox' i], [role='menu' i], .peach-select-dropdown");136 const isHidden = await dropdown.isHidden().catch(() => true);137 expect(isHidden).toBeTruthy();138 await ctx.close();139 });140141 test("AUL08 - auto-lock selection persists after reopen", async () => {142 const { popup } = await setupVault(ctx);143 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();144 await popup.waitForTimeout(500);145 await popup.locator("text=auto-lock").click();146 await popup.waitForTimeout(300);147 const options = popup.locator("[role='option' i], [role='menuitem' i], .peach-select-option");148 await options.nth(2).click();149 await popup.waitForTimeout(300);150 await popup.keyboard.press("Escape");151 await popup.waitForTimeout(200);152 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();153 await popup.waitForTimeout(500);154 await popup.locator("text=auto-lock").click();155 await popup.waitForTimeout(300);156 const selectedOption = popup.locator("[role='option' i][aria-selected='true'], .peach-select-option.is-selected").first();157 await selectedOption.isVisible({ timeout: 2000 }).catch(() => false);158 await ctx.close();159 });160});161162test.describe("Clipboard Clear Settings", () => {163 let ctx: BrowserContext;164 test.afterEach(async () => { await ctx.close(); });165 test.beforeEach(async () => { ctx = await makeContext(); });166167 test("ACP01 - clipboard clear setting exists", async () => {168 const { popup } = await setupVault(ctx);169 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();170 await popup.waitForTimeout(500);171 await expect(popup.locator("text=clipboard clear")).toBeVisible();172 await ctx.close();173 });174175 test("ACP02 - clipboard clear options: 30 seconds", async () => {176 const { popup } = await setupVault(ctx);177 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();178 await popup.waitForTimeout(500);179 await popup.locator("text=clipboard clear").click();180 await popup.waitForTimeout(300);181 const options = popup.locator("[role='option' i], [role='menuitem' i]");182 const optionTexts = await options.allTextContents();183 const has30s = optionTexts.some((t: string) => t.includes("30") || t.includes("30s"));184 expect(has30s).toBeTruthy();185 await ctx.close();186 });187188 test("ACP03 - clipboard clear options: 60 seconds", async () => {189 const { popup } = await setupVault(ctx);190 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();191 await popup.waitForTimeout(500);192 await popup.locator("text=clipboard clear").click();193 await popup.waitForTimeout(300);194 const options = popup.locator("[role='option' i], [role='menuitem' i]");195 const optionTexts = await options.allTextContents();196 const has60s = optionTexts.some((t: string) => t.includes("60") || t.includes("1 min"));197 expect(has60s).toBeTruthy();198 await ctx.close();199 });200201 test("ACP04 - clipboard clear options: 90 seconds", async () => {202 const { popup } = await setupVault(ctx);203 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();204 await popup.waitForTimeout(500);205 await popup.locator("text=clipboard clear").click();206 await popup.waitForTimeout(300);207 const options = popup.locator("[role='option' i], [role='menuitem' i]");208 const optionTexts = await options.allTextContents();209 const has90s = optionTexts.some((t: string) => t.includes("90"));210 expect(has90s).toBeTruthy();211 await ctx.close();212 });213214 test("ACP05 - clipboard clear options: never", async () => {215 const { popup } = await setupVault(ctx);216 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();217 await popup.waitForTimeout(500);218 await popup.locator("text=clipboard clear").click();219 await popup.waitForTimeout(300);220 const options = popup.locator("[role='option' i], [role='menuitem' i]");221 const optionTexts = await options.allTextContents();222 const hasNever = optionTexts.some((t: string) => t.toLowerCase().includes("never"));223 expect(hasNever).toBeTruthy();224 await ctx.close();225 });226227 test("ACP06 - clipboard clear persists after close", async () => {228 const { popup } = await setupVault(ctx);229 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();230 await popup.waitForTimeout(500);231 await popup.locator("text=clipboard clear").click();232 await popup.waitForTimeout(300);233 const options = popup.locator("[role='option' i], [role='menuitem' i]");234 await options.first().click();235 await popup.waitForTimeout(300);236 await popup.keyboard.press("Escape");237 await popup.waitForTimeout(200);238 const counter = popup.locator(".peach-search-counter");239 const text = await counter.textContent();240 expect(text).toBeTruthy();241 await ctx.close();242 });243});244245test.describe("Lock on Close", () => {246 let ctx: BrowserContext;247 test.afterEach(async () => { await ctx.close(); });248 test.beforeEach(async () => { ctx = await makeContext(); });249250 test("ALC01 - lock on close setting exists", async () => {251 const { popup } = await setupVault(ctx);252 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();253 await popup.waitForTimeout(500);254 await expect(popup.locator("text=lock on close")).toBeVisible();255 await ctx.close();256 });257258 test("ALC02 - lock on close is a toggle switch", async () => {259 const { popup } = await setupVault(ctx);260 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();261 await popup.waitForTimeout(500);262 const toggle = popup.locator("text=lock on close").locator("..").locator("[role='switch' i], [type='checkbox']").first();263 await expect(toggle).toBeVisible();264 await ctx.close();265 });266267 test("ALC03 - lock on close toggle is off by default", async () => {268 const { popup } = await setupVault(ctx);269 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();270 await popup.waitForTimeout(500);271 const toggle = popup.locator("text=lock on close").locator("..").locator("[role='switch' i]").first();272 const isChecked = await toggle.getAttribute("aria-checked");273 expect(isChecked).not.toBe("true");274 await ctx.close();275 });276277 test("ALC04 - enabling lock on close changes toggle state", async () => {278 const { popup } = await setupVault(ctx);279 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();280 await popup.waitForTimeout(500);281 const toggle = popup.locator("text=lock on close").locator("..").locator("[role='switch' i]").first();282 await toggle.click();283 await popup.waitForTimeout(300);284 const isChecked = await toggle.getAttribute("aria-checked");285 expect(isChecked).toBe("true");286 await ctx.close();287 });288289 test("ALC05 - lock on close persists after settings close", async () => {290 const { popup } = await setupVault(ctx);291 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();292 await popup.waitForTimeout(500);293 const toggle = popup.locator("text=lock on close").locator("..").locator("[role='switch' i]").first();294 await toggle.click();295 await popup.waitForTimeout(300);296 await popup.keyboard.press("Escape");297 await popup.waitForTimeout(200);298 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();299 await popup.waitForTimeout(500);300 const toggle2 = popup.locator("text=lock on close").locator("..").locator("[role='switch' i]").first();301 const isChecked = await toggle2.getAttribute("aria-checked");302 expect(isChecked).toBe("true");303 await ctx.close();304 });305});306307test.describe("Breach Monitoring Settings", () => {308 let ctx: BrowserContext;309 test.afterEach(async () => { await ctx.close(); });310 test.beforeEach(async () => { ctx = await makeContext(); });311312 test("ABM01 - breach monitoring setting exists", async () => {313 const { popup } = await setupVault(ctx);314 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();315 await popup.waitForTimeout(500);316 await expect(popup.locator("text=breach monitoring")).toBeVisible();317 await ctx.close();318 });319320 test("ABM02 - breach monitoring is a toggle switch", async () => {321 const { popup } = await setupVault(ctx);322 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();323 await popup.waitForTimeout(500);324 const toggle = popup.locator("text=breach monitoring").locator("..").locator("[role='switch' i]").first();325 await expect(toggle).toBeVisible();326 await ctx.close();327 });328329 test("ABM03 - breach monitoring toggle changes state", async () => {330 const { popup } = await setupVault(ctx);331 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();332 await popup.waitForTimeout(500);333 const toggle = popup.locator("text=breach monitoring").locator("..").locator("[role='switch' i]").first();334 const beforeState = await toggle.getAttribute("aria-checked");335 await toggle.click();336 await popup.waitForTimeout(300);337 const afterState = await toggle.getAttribute("aria-checked");338 expect(beforeState).not.toEqual(afterState);339 await ctx.close();340 });341342 test("ABM04 - breach monitoring persists after close", async () => {343 const { popup } = await setupVault(ctx);344 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();345 await popup.waitForTimeout(500);346 const toggle = popup.locator("text=breach monitoring").locator("..").locator("[role='switch' i]").first();347 await toggle.click();348 await popup.waitForTimeout(300);349 await popup.keyboard.press("Escape");350 await popup.waitForTimeout(200);351 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();352 await popup.waitForTimeout(500);353 const toggle2 = popup.locator("text=breach monitoring").locator("..").locator("[role='switch' i]").first();354 const isChecked = await toggle2.getAttribute("aria-checked");355 expect(isChecked).toBe("true");356 await ctx.close();357 });358});359360test.describe("Accent Color Settings", () => {361 let ctx: BrowserContext;362 test.afterEach(async () => { await ctx.close(); });363 test.beforeEach(async () => { ctx = await makeContext(); });364365 test("AAC01 - accent color section exists in settings", async () => {366 const { popup } = await setupVault(ctx);367 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();368 await popup.waitForTimeout(500);369 const swatches = popup.locator(".peach-swatch");370 const count = await swatches.count();371 expect(count).toBeGreaterThan(0);372 await ctx.close();373 });374375 test("AAC02 - all swatches are clickable", async () => {376 const { popup } = await setupVault(ctx);377 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();378 await popup.waitForTimeout(500);379 const swatches = popup.locator(".peach-swatch");380 const count = await swatches.count();381 expect(count).toBeGreaterThanOrEqual(5);382 for (let i = 0; i < count; i++) {383 await swatches.nth(i).click();384 await popup.waitForTimeout(100);385 }386 await ctx.close();387 });388389 test("AAC03 - selected swatch shows active state", async () => {390 const { popup } = await setupVault(ctx);391 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();392 await popup.waitForTimeout(500);393 const swatch = popup.locator(".peach-swatch").nth(3);394 await swatch.click();395 await popup.waitForTimeout(200);396 const isActive = await swatch.evaluate((el: Element) => el.classList.contains("is-active"));397 expect(isActive).toBeTruthy();398 await ctx.close();399 });400401 test("AAC04 - only one swatch active at a time", async () => {402 const { popup } = await setupVault(ctx);403 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();404 await popup.waitForTimeout(500);405 await popup.locator(".peach-swatch").nth(0).click();406 await popup.waitForTimeout(200);407 await popup.locator(".peach-swatch").nth(2).click();408 await popup.waitForTimeout(200);409 const activeSwatches = popup.locator(".peach-swatch.is-active");410 const count = await activeSwatches.count();411 expect(count).toBe(1);412 await ctx.close();413 });414415 test("AAC05 - accent color persists after settings close", async () => {416 const { popup } = await setupVault(ctx);417 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();418 await popup.waitForTimeout(500);419 await popup.locator(".peach-swatch").nth(4).click();420 await popup.waitForTimeout(200);421 await popup.keyboard.press("Escape");422 await popup.waitForTimeout(200);423 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();424 await popup.waitForTimeout(500);425 const activeSwatch = popup.locator(".peach-swatch.is-active");426 const count = await activeSwatch.count();427 expect(count).toBe(1);428 await ctx.close();429 });430});431432test.describe("Entry Count & Vault Info", () => {433 let ctx: BrowserContext;434 test.afterEach(async () => { await ctx.close(); });435 test.beforeEach(async () => { ctx = await makeContext(); });436437 test("AEV01 - settings shows entry count", async () => {438 const { popup } = await setupVault(ctx);439 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();440 await popup.waitForTimeout(500);441 const entriesText = popup.locator("text=entries").first();442 await expect(entriesText).toBeVisible();443 await ctx.close();444 });445446 test("AEV02 - entry count updates when entries added", async () => {447 const { popup } = await setupVault(ctx);448 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();449 await popup.waitForTimeout(500);450 const initialCount = await popup.locator("text=entries").textContent();451 await popup.keyboard.press("Escape");452 await popup.waitForTimeout(200);453 await popup.locator('input[placeholder="search vault..."]').click();454 await popup.getByRole("button", { name: /new entry/i }).click();455 await popup.locator(".peach-new-name-input").fill("CountUpdate");456 await popup.locator('input[placeholder="domain.com"]').fill("https://count.com");457 await popup.locator('input[placeholder="username or email"]').fill("[email protected]");458 await popup.locator(".peach-new-field-input[placeholder='password']").fill("pass");459 await popup.getByRole("button", { name: /create/i }).click();460 await popup.waitForTimeout(1500);461 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();462 await popup.waitForTimeout(500);463 const newCount = await popup.locator("text=entries").textContent();464 expect(newCount).not.toEqual(initialCount);465 await ctx.close();466 });467468 test("AEV03 - version number shows in settings", async () => {469 const { popup } = await setupVault(ctx);470 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();471 await popup.waitForTimeout(500);472 const version = popup.locator("text=1.0.");473 const hasVersion = await version.isVisible({ timeout: 2000 }).catch(() => false);474 expect(hasVersion).toBeTruthy();475 await ctx.close();476 });477});478479test.describe("Settings Navigation", () => {480 let ctx: BrowserContext;481 test.afterEach(async () => { await ctx.close(); });482 test.beforeEach(async () => { ctx = await makeContext(); });483484 test("ASN01 - settings opens with gear icon", async () => {485 const { popup } = await setupVault(ctx);486 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();487 await popup.waitForTimeout(500);488 const title = popup.locator(".peach-overlay-title, text=settings").first();489 await expect(title).toBeVisible();490 await ctx.close();491 });492493 test("ASN02 - settings closes with back button", async () => {494 const { popup } = await setupVault(ctx);495 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();496 await popup.waitForTimeout(500);497 const backBtn = popup.locator("button[aria-label='Back']").first();498 await backBtn.click();499 await popup.waitForTimeout(300);500 const overlay = popup.locator(".peach-overlay-view");501 const isHidden = await overlay.isHidden().catch(() => true);502 expect(isHidden).toBeTruthy();503 await ctx.close();504 });505506 test("ASN03 - settings closes with escape key", async () => {507 const { popup } = await setupVault(ctx);508 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();509 await popup.waitForTimeout(500);510 await popup.keyboard.press("Escape");511 await popup.waitForTimeout(300);512 const overlay = popup.locator(".peach-overlay-view");513 const isHidden = await overlay.isHidden().catch(() => true);514 expect(isHidden).toBeTruthy();515 await ctx.close();516 });517518 test("ASN04 - lock vault button visible in settings", async () => {519 const { popup } = await setupVault(ctx);520 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();521 await popup.waitForTimeout(500);522 const lockBtn = popup.locator("text=lock vault").first();523 await expect(lockBtn).toBeVisible();524 await ctx.close();525 });526527 test("ASN05 - lock vault returns to lock screen", async () => {528 const { popup } = await setupVault(ctx);529 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();530 await popup.waitForTimeout(500);531 await popup.locator("text=lock vault").click();532 await popup.waitForTimeout(1500);533 const pwField = popup.locator("#master-password");534 await expect(pwField).toBeVisible({ timeout: 5000 });535 await ctx.close();536 });537538 test("ASN06 - export button visible in settings", async () => {539 const { popup } = await setupVault(ctx);540 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();541 await popup.waitForTimeout(500);542 const exportBtn = popup.getByRole("button", { name: /export/i }).first();543 await expect(exportBtn).toBeVisible();544 await ctx.close();545 });546547 test("ASN07 - import button visible in settings", async () => {548 const { popup } = await setupVault(ctx);549 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();550 await popup.waitForTimeout(500);551 const importBtn = popup.getByRole("button", { name: /import/i }).first();552 await expect(importBtn).toBeVisible();553 await ctx.close();554 });555556 test("ASN08 - generator button visible in settings", async () => {557 const { popup } = await setupVault(ctx);558 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();559 await popup.waitForTimeout(500);560 const genBtn = popup.getByRole("button", { name: /generator/i }).first();561 await expect(genBtn).toBeVisible();562 await ctx.close();563 });564});565566test.describe("Settings Persistence", () => {567 let ctx: BrowserContext;568 test.afterEach(async () => { await ctx.close(); });569 test.beforeEach(async () => { ctx = await makeContext(); });570571 test("ASP01 - all settings persist after vault lock/unlock", async () => {572 const { popup } = await setupVault(ctx);573 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();574 await popup.waitForTimeout(500);575 const swatch = popup.locator(".peach-swatch").nth(5);576 await swatch.click();577 await popup.waitForTimeout(200);578 await popup.keyboard.press("Escape");579 await popup.waitForTimeout(200);580 const lockBtn = popup.locator(".peach-lock-btn[aria-label='Lock vault']");581 await lockBtn.click();582 await popup.waitForTimeout(1500);583 await popup.locator("#master-password").fill("password123");584 await popup.getByRole("button", { name: /unlock/i }).click();585 await popup.waitForTimeout(2000);586 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();587 await popup.waitForTimeout(500);588 const activeSwatch = popup.locator(".peach-swatch.is-active");589 const count = await activeSwatch.count();590 expect(count).toBe(1);591 await ctx.close();592 });593594 test("ASP02 - accent color persists after new entry", async () => {595 const { popup } = await setupVault(ctx);596 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();597 await popup.waitForTimeout(500);598 await popup.locator(".peach-swatch").nth(2).click();599 await popup.waitForTimeout(200);600 await popup.keyboard.press("Escape");601 await popup.waitForTimeout(200);602 await popup.locator('input[placeholder="search vault..."]').click();603 await popup.getByRole("button", { name: /new entry/i }).click();604 await popup.locator(".peach-new-name-input").fill("PersistTest");605 await popup.locator('input[placeholder="domain.com"]').fill("https://persist.com");606 await popup.locator('input[placeholder="username or email"]').fill("[email protected]");607 await popup.locator(".peach-new-field-input[placeholder='password']").fill("pass");608 await popup.getByRole("button", { name: /create/i }).click();609 await popup.waitForTimeout(1500);610 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();611 await popup.waitForTimeout(500);612 const activeSwatch = popup.locator(".peach-swatch.is-active");613 const count = await activeSwatch.count();614 expect(count).toBe(1);615 await ctx.close();616 });617618 test("ASP03 - toggle settings persist after page navigation", async () => {619 const { popup } = await setupVault(ctx);620 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();621 await popup.waitForTimeout(500);622 const lockToggle = popup.locator("text=lock on close").locator("..").locator("[role='switch' i]").first();623 await lockToggle.click();624 await popup.waitForTimeout(200);625 await popup.keyboard.press("Escape");626 await popup.waitForTimeout(200);627 await popup.locator(".peach-entry-name-button").first().click();628 await popup.waitForTimeout(500);629 await popup.locator("button[aria-label='Back']").first().click();630 await popup.waitForTimeout(300);631 await popup.locator(".peach-icon-btn[aria-label='Settings']").click();632 await popup.waitForTimeout(500);633 const isChecked = await lockToggle.getAttribute("aria-checked");634 expect(isChecked).toBe("true");635 await ctx.close();636 });637});