import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { defineConfig } from "@playwright/test"; // Use a dedicated port so e2e tests always start their own server in local_trusted mode, // even when the dev server is running on :3100 in authenticated mode. const PORT = Number(process.env.PAPERCLIP_E2E_PORT ?? 3199); const BASE_URL = `http://127.0.0.1:${PORT}`; const PAPERCLIP_HOME = fs.mkdtempSync(path.join(os.tmpdir(), "paperclip-e2e-home-")); const PLAYWRIGHT_CHANNEL = process.env.PAPERCLIP_PLAYWRIGHT_CHANNEL; export default defineConfig({ testDir: ".", testMatch: "**/*.spec.ts", // These suites target dedicated multi-user configurations/ports and are // intentionally not part of the default local_trusted e2e run. testIgnore: ["multi-user.spec.ts", "multi-user-authenticated.spec.ts"], timeout: 60_000, retries: 0, use: { baseURL: BASE_URL, headless: true, screenshot: "only-on-failure", trace: "on-first-retry", }, projects: [ { name: "chromium", use: { browserName: "chromium", ...(PLAYWRIGHT_CHANNEL ? { channel: PLAYWRIGHT_CHANNEL } : {}), }, }, ], // The webServer directive bootstraps a throwaway instance and then starts it. // `onboard --yes --run` works in a non-interactive temp PAPERCLIP_HOME. webServer: { command: `pnpm paperclipai onboard --yes --run`, url: `${BASE_URL}/api/health`, // Always boot a dedicated throwaway instance for e2e so browser tests // never attach to the developer's active Paperclip home/server. reuseExistingServer: false, timeout: 120_000, stdout: "pipe", stderr: "pipe", env: { ...process.env, PORT: String(PORT), PAPERCLIP_HOME, PAPERCLIP_INSTANCE_ID: "playwright-e2e", PAPERCLIP_BIND: "loopback", PAPERCLIP_DEPLOYMENT_MODE: "local_trusted", PAPERCLIP_DEPLOYMENT_EXPOSURE: "private", }, }, outputDir: "./test-results", reporter: [["list"], ["html", { open: "never", outputFolder: "./playwright-report" }]], });