import { randomUUID } from "node:crypto"; import path from "node:path"; import { defineConfig, devices } from "@playwright/test"; // The worker inherits this exact run path; never touch the default auth/data. const runDir = process.env.LH_E2E_RUN_DIR ?? path.resolve(".playwright-data", `run-${randomUUID()}`); if (path.dirname(runDir) !== path.resolve(".playwright-data") || !/^run-[a-f0-9-]{36}$/.test(path.basename(runDir))) { throw new Error("Unsafe Playwright data directory; expected a fixture-owned UUID path under .playwright-data."); } process.env.LH_E2E_RUN_DIR = runDir; export default defineConfig({ testDir: "./e2e", fullyParallel: false, workers: 1, retries: 0, timeout: 60_000, expect: { timeout: 15_000 }, globalSetup: "./e2e/fixtures.ts", outputDir: "test-results", reporter: [["list"], ["html", { open: "never" }]], use: { baseURL: "http://127.0.0.1:3005", trace: "retain-on-failure", screenshot: "only-on-failure", serviceWorkers: "block", locale: "en-US", launchOptions: { chromiumSandbox: true }, }, projects: [{ name: "chromium", use: { ...devices["Desktop Chrome"] } }], webServer: { command: "npm run dev -- --hostname 127.0.0.1 --port 3005", url: "http://127.0.0.1:3005", reuseExistingServer: false, timeout: 120_000, stdout: "pipe", stderr: "pipe", env: { LH_IGNORE_ENV_KEYS: "1", LH_DATA_DIR: path.join(runDir, "data"), LH_AUTH_FILE: path.join(runDir, "auth.json"), NEXT_TELEMETRY_DISABLED: "1", }, }, });