settings.spec.ts

4.3 KB · raw

1import { test, expect, type BrowserContext, type Page } from "@playwright/test";2import { join } from "path";3import os from "os";4import fs from "fs/promises";5import { EXTENSION_PATH, addEntry, loadPopup, makeContext, openSettings, setupVault, waitForSW } from "./helpers/vault";67// Real vault creation runs Argon2id (≈12s with the recovery confirmation).8test.describe.configure({ timeout: 90_000 });910/** Settings is a card deck — only the active card's rows are on screen. */11async function openCard(popup: Page, id: string) {12  await popup.locator(`[data-settings-card-id="${id}"]`).click();13  await expect(popup.locator(`[data-settings-card-id="${id}"][data-active="true"]`)).toBeVisible();14}1516test.describe("Settings & Appearance", () => {17  let ctx: BrowserContext;18  test.afterEach(async () => { await ctx.close(); });19  test.beforeEach(async () => { ctx = await makeContext("peach-settings"); });2021  test("ST01 - settings panel opens from the chrome bar", async () => {22    const { popup } = await setupVault(ctx);23    await openSettings(popup);24    await expect(popup.locator(".stk-mast-title")).toHaveText("Settings");25  });2627  test("ST02 - the deck carries all seven cards", async () => {28    const { popup } = await setupVault(ctx);29    await openSettings(popup);30    await expect(popup.locator("[data-settings-card-id]")).toHaveCount(7);31    await expect(popup.locator(".stk-mast-counter")).toHaveText("1 / 7");32  });3334  test("ST03 - protection card carries lock-on-close, auto-lock and breach monitoring", async () => {35    const { popup } = await setupVault(ctx);36    await openSettings(popup);37    await openCard(popup, "protection");38    for (const label of ["Lock on close", "Auto-lock after", "Breach monitoring"]) {39      await expect(popup.locator(".peach-settings-row", { hasText: label })).toHaveCount(1);40    }41  });4243  test("ST04 - the vault card reports the entry count", async () => {44    const { popup } = await setupVault(ctx);45    await addEntry(popup, { title: "CountMe", url: "https://count.test", username: "u", password: "p" });46    await openSettings(popup);47    await expect(48      popup.locator('[data-settings-card-id="vault"]'),49    ).toContainText(/\d+ (entry|entries)/);50  });5152  test("ST05 - accent swatches are all clickable", async () => {53    const { popup } = await setupVault(ctx);54    await openSettings(popup);55    await openCard(popup, "appearance");56    const swatches = popup.locator(".peach-swatch");57    const count = await swatches.count();58    expect(count).toBeGreaterThanOrEqual(6);59    for (let i = 0; i < count; i++) {60      await swatches.nth(i).click();61      await popup.waitForTimeout(100);62    }63  });6465  test("ST06 - import passwords opens the import view", async () => {66    const { popup } = await setupVault(ctx);67    await openSettings(popup);68    await openCard(popup, "vault");69    await popup.locator(".peach-settings-row", { hasText: "Import passwords" }).getByRole("button").click();70    await expect(popup.locator(".peach-overlay-title")).toHaveText(/import/i, { timeout: 10000 });71  });7273  test("ST07 - export backup opens the export view", async () => {74    const { popup } = await setupVault(ctx);75    await openSettings(popup);76    await openCard(popup, "vault");77    await popup.locator(".peach-settings-row", { hasText: "Export backup" }).getByRole("button").click();78    await expect(popup.locator(".peach-overlay-title")).toHaveText(/export/i, { timeout: 10000 });79  });8081  test("ST08 - onboarding shows the peach wordmark", async () => {82    const { popup } = await loadPopup(ctx);83    await expect(popup.locator(".peach-wordmark-wrap").first()).toBeVisible();84    await expect(popup.locator(".peach-onboarding-card-headline")).toBeVisible();85  });86});8788test("ST09 - lock screen pre-rendered HTML is attached before JS runs", async () => {89  const { chromium } = await import("playwright");90  const userDataDir = join(os.tmpdir(), `peach-prelock-${Date.now()}`);91  await fs.mkdir(userDataDir, { recursive: true });92  const ctx = await chromium.launchPersistentContext(userDataDir, {93    headless: true,94    args: [`--load-extension=${EXTENSION_PATH}`, `--disable-extensions-except=${EXTENSION_PATH}`],95  });96  const extId = await waitForSW(ctx);97  const page = await ctx.newPage();98  await page.goto(`chrome-extension://${extId}/src/popup/index.html`);99  await expect(page.locator("#pre-lock")).toBeAttached();100  await ctx.close();101});