GenerateSaaS

End-to-end tests

Run the desktop Playwright harness that drives the built Electron app against a local backend, and the services and system libraries it needs.

The desktop app ships its own Playwright suite in apps/desktop/e2e/. One command builds it against a local backend, launches the real Electron binary, and drives the app through its own UI.

Running it

Start the services below with pnpm infra.
Run the suite. It builds the Electron bundles with the harness backend URL baked in, then runs Playwright.
Read the report in apps/desktop/playwright-report/ (pnpm --filter desktop exec playwright show-report).
pnpm infra                             # Postgres, Redis, Mailpit, Inngest, MinIO
pnpm --filter desktop e2e:desktop:ci   # build against the harness origin, then run every default spec
pnpm --filter desktop e2e:live         # the opt-in specs that drive a real coding CLI

pnpm --filter desktop desktop:build:e2e runs that build on its own.

Ports and build output

FactValue
Originhttp://127.0.0.1:<5100 + (checkout hash % 900)>; DESKTOP_E2E_ORIGIN overrides it
Web build directoryapps/web/.next-e2e-desktop, never the .next your pnpm dev uses
DatabaseA throwaway one per run, dropped on exit
ConcurrencySeparate ports and build directories from the web suite, so both can run at once

The app bakes its backend origin in at build time, so an override has to be set before the build, never after.

The harness targets the fullstack architecture. With a separate backend the API answers on another port, so repoint the origin at it or the seed 404s.

What the specs prove

SpecGateWhat it drives
login.spec.tsdefaultthe real device-authorization grant, from the app's own login screen
dashboard.spec.tsdefaulta profile holding a token boots signed in, not into onboarding
settings.spec.tsdefaultthe user menu opens General settings, and sign-out returns to login
terminal-panel.spec.tsdefaultthe terminal surface renders per your config flags
chat-composer.spec.ts, automations.spec.tsdefaultthe chat and automation surfaces against the local fake provider
chat-composer.live.spec.ts, automations.live.spec.ts, terminal-session.live.spec.tslivea real coding CLI completing a real turn

How they drive the app:

  • Real Electron, programmatically. Playwright launches the app's own binary and drives its DOM over the debugging bridge - it never moves the OS pointer, so a local run steals no focus.
  • Isolation without parallelism. One worker, a fresh --user-data-dir per launch, a uniquely seeded user per spec.
  • Gated on your flags. Specs read @repo/config and register conditionally, so the summary reports 0 skipped - see Writing tests.
  • Offline. The renderer's outbound requests are blocked at the Electron context, so the packaged support widget never reaches the network during a run.

Linux and CI

Electron needs a display and its GTK/NSS system libraries. That is an apt install, not playwright install - the suite launches the app's own Electron, so a downloaded Chromium would go unused.

sudo apt-get install -y xvfb libgtk-3-0t64 libnss3 libasound2t64 libgbm1 libatk1.0-0t64 \
  libatk-bridge2.0-0t64 libatspi2.0-0t64 libcups2t64 libdrm2 libxkbcommon0 libxcomposite1 \
  libxdamage1 libxfixes3 libxrandr2 libxtst6 libnotify4 libsecret-1-0 libpango-1.0-0 libcairo2
xvfb-run --auto-servernum pnpm --filter desktop e2e:desktop:ci

Your generated .github/workflows/ci.yml already carries this as a desktop-e2e job on a manual dispatch: an Electron build on top of a Next production build is too slow for every push.

Ubuntu 24.04 gave several of these a t64 suffix. On an older release, install the unsuffixed name (libgtk-3-0, libasound2, …).

On this page