// Playwright configuration for end-to-end tests.
//
// What this covers vs. Vitest
// ───────────────────────────
// Vitest (in src/**/*.test.js) covers pure functions and the React
// hook-state portion of useDesignEditor — anything testable without
// mounting Konva. Playwright covers what Vitest can't: real Konva
// stages, the actual keyboard handler attached to window, persistence
// across reloads, the multi-component flows where state has to thread
// through App.jsx, the Sidebar, the canvas, and back.
//
// Test layout
// ───────────
//   /e2e/
//     fixtures/              ← shared setup helpers
//     text-editing.spec.js   ← adding/editing/deleting text elements
//     history.spec.js        ← undo/redo across operations
//     persistence.spec.js    ← state survives page reload
//     crop.spec.js           ← the headline May 22 bug — crop + Cmd-Z
//                              must restore the uncropped image
//
// Webserver
// ─────────
// `npm run dev` runs Vite (3000) + the Node server (3001) via
// concurrently. Playwright waits for the Vite URL to be reachable
// before starting tests. The 120-second timeout accommodates cold
// starts on first run (Vite optimizes deps, the Node server's
// dependencies are heavy).
//
// `reuseExistingServer: !CI` means if a dev server is already running
// locally, Playwright connects to that rather than starting a second
// one (which would fail on the port collision). In CI we always start
// a fresh one for hermetic runs.
//
// Browsers
// ────────
// Chromium only. The app's behaviour is engine-dependent in subtle
// places (Konva canvas pixel rounding, native EyeDropper API is
// Chromium-only), so Firefox/WebKit coverage would either flake or
// have to skip large chunks of the suite. Chromium is what the
// dominant user base will hit; adding more engines is a future
// quality decision once Chromium is solid.

import { defineConfig, devices } from '@playwright/test';

const PORT = 3000;
const BASE_URL = `http://localhost:${PORT}`;

export default defineConfig({
  testDir: './e2e',
  // The dev server is shared across tests in a file; running them in
  // parallel within a file would mean simultaneous localStorage
  // wipes and weird cross-test state. Within a file, tests run
  // sequentially (default). Across files, parallel is fine — each
  // file gets a fresh browser context.
  fullyParallel: true,
  // Hard fail in CI on .only(). Locally, .only() is a useful
  // workflow for iterating on a single failing test.
  forbidOnly: !!process.env.CI,
  // Retry once in CI for flakes (Konva mount timing, font load
  // races). Locally, no retries — a flake should fail and be
  // investigated, not papered over.
  retries: process.env.CI ? 1 : 0,
  // CI: single worker for hermetic runs. Local: Playwright picks
  // based on cores (typically 50% of available, capped at 8).
  workers: process.env.CI ? 1 : undefined,
  reporter: process.env.CI ? 'github' : 'list',

  use: {
    baseURL: BASE_URL,
    // Capture trace on first retry so flaky tests in CI leave us
    // breadcrumbs (full DOM snapshot, network log, screenshots).
    // Tracing is expensive — we don't want it on every run.
    trace: 'on-first-retry',
    // Screenshot on failure for the same reason. The screenshot is
    // attached to the test report automatically.
    screenshot: 'only-on-failure',
    // Don't record video by default — produces large files and is
    // rarely the right tool. Enable per-test if needed.
    video: 'off',
    // Default timeout for individual actions (click, fill, etc.).
    // The app's UI is responsive; 10s is a generous ceiling for
    // anything that should be near-instant.
    actionTimeout: 10_000,
    // Navigation timeout — `goto`/reload waits up to 30s. Cold
    // first paint can be slow when Vite is also compiling deps.
    navigationTimeout: 30_000,
  },

  projects: [
    {
      name: 'chromium',
      use: { ...devices['Desktop Chrome'] },
    },
  ],

  webServer: {
    command: 'npm run dev',
    url: BASE_URL,
    // 120s for cold starts (Vite optimizes deps, fonts load, etc).
    timeout: 120 * 1000,
    // Locally, if a dev server is already up, just connect to it.
    // In CI, always spin a fresh one.
    reuseExistingServer: !process.env.CI,
    // Pipe server output to stdout for debugging when tests fail —
    // a 500 from the API or a Vite compile error becomes visible
    // in the Playwright output rather than disappearing into the
    // background process.
    stdout: 'pipe',
    stderr: 'pipe',
  },
});
