import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; import { defineConfig } from "@playwright/test"; // Demo specs log in with the real dev credentials; pull them from the repo // .env so they never live in the test source. const repoEnv = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.env"); if (fs.existsSync(repoEnv)) { for (const line of fs.readFileSync(repoEnv, "utf8").split("\n")) { const m = line.match(/^([A-Z_]+)=["']?(.*?)["']?$/); if (m && !(m[1] in process.env)) process.env[m[1]] = m[2]; } } export default defineConfig({ testDir: "./e2e", outputDir: "./test-results", fullyParallel: false, // Demo runs synthesize narration and run several ffmpeg passes in save(); // that can exceed the 30s default, especially with many steps. timeout: process.env.PW_DEMO ? 120_000 : 30_000, reporter: [ ["list"], ["html", { outputFolder: "playwright-report", open: "never" }], ], use: { baseURL: "http://localhost:3000", // Demo runs (pnpm demo) pace every action so the recorded video is // watchable by a human; functional e2e runs stay at full speed. launchOptions: { slowMo: process.env.PW_DEMO ? 500 : 0, }, locale: "es-CR", timezoneId: "America/Costa_Rica", viewport: { width: 1920, height: 1080 }, // Retina-density rendering so doc screenshots stay crisp when zoomed. deviceScaleFactor: 2, // Full recordings are only useful for the paced demo. Keeping them off // for regular e2e avoids making test success depend on artifact uploads. video: process.env.PW_DEMO ? { mode: "on", size: { width: 1920, height: 1080 } } : "off", screenshot: "only-on-failure", trace: process.env.PW_DEMO ? "on" : "on-first-retry", }, webServer: { command: "pnpm dev", url: "http://localhost:3000", reuseExistingServer: true, stdout: "ignore", timeout: 60_000, }, });