feat(lightpanda): add @e2e-dev/lightpanda, a browser provider for the Lightpanda headless browser
Draft
OK
11d ago+1031+1031+0123456789012345678901234567890123456789-8-8-0123456789
What and why
- New package
@e2e-dev/lightpanda:lightpanda()is aBrowserProviderfor the web engine that starts onelightpanda serveper worker slot on a free loopback port and stops its process group when the run ends. No vendor SDK; the binary is the dependency. - Lightpanda is an open-source headless browser without Chromium: instant start, a fraction of Chrome's memory, and CDP, so the engine attaches to it the way it attaches to Kernel.
- Binary discovery:
binary,LIGHTPANDA_PATH, thenlightpandaonPATH,~/.lightpanda/lightpanda,~/.local/bin/lightpanda(the places agent-browser looks). None found fails the lease before any test, naming the install page. - A server already running (the Docker image in CI) is a
web({ connect })target, so the provider has one lease shape and no attach mode. - Worker scope only: Lightpanda exposes no default context identity, so a per-attempt lease fails with
CDP recovery failed: the default context identity is unavailable. The option is not offered. - Docs page
docs/integrations/lightpanda.mdxwith setup, options, and a table of what Lightpanda cannot do yet (sessions, dialogs, downloads, iframes, drags, resize, scrolling) and why, each verified against the nightly. Testbed getse2e.lightpanda.config.tsandpnpm test:lightpandato re-check that table as Lightpanda ships fixes.
import { lightpanda } from '@e2e-dev/lightpanda';
export default {
targets: [{ name: 'lightpanda', engine: web({ browser: lightpanda({ loadResources: ['iframe'] }) }), app: { url } }],
} satisfies E2EConfig;
sequenceDiagram
participant R as runner (prepare)
participant P as lightpanda()
participant S as lightpanda serve
participant W as worker
R->>P: acquire(slot n)
P->>S: spawn --host 127.0.0.1 --port free, detached
P->>S: poll /json/version (10 s cap)
S-->>P: Lightpanda-Version
P-->>R: lease { id: ws://127.0.0.1:port/ }
W->>S: connectOverCDP, one context per attempt
R->>P: release(lease)
P->>S: SIGTERM group, SIGKILL after 5 s
Benchmark
Testbed, the six files that pass on both engines copied four times (96 tests), M4 Pro, mean of two runs. Baseline is web() Chromium on this branch; the candidate is lightpanda().
| Workers | Chromium wall | Lightpanda wall | Chromium peak RSS | Lightpanda peak RSS |
|---|---|---|---|---|
| 1 | 31.6 s | 21.8 s | 358 MB | 124 MB |
| 4 | 9.8 s | 6.6 s | 1.30 GB | 364 MB |
| 8 | 6.7 s | 5.0 s | 2.52 GB | 587 MB |
| 14 | 6.1 s | 4.1 s | 4.12 GB | 954 MB |
Per-test time grows 33 percent from 1 to 14 workers on Lightpanda and 77 percent on Chromium; Chromium stops gaining past 8 workers on 14 cores.
Verified
Ran it locally: yes
- testbed,
LIGHTPANDA_PATH=... pnpm test:lightpanda --workers 2: two servers leased on distinct ports, logged aslightpanda 1.1.0-nightly.10207 at ws://127.0.0.1:51165/, released at the end,pgrep lightpandaempty after. - Full testbed suite on the provider: 53 passed, 18 failed, 1 skipped; every failure is in the docs table and reproduced with a bare Playwright
connectOverCDPprobe, so none is engine-side. scope: 'attempt'tried live and fails as described, which is why it is absent.- Empty
PATHandHOME: the run fails before any test withlightpanda is not on PATH, in ~/.lightpanda, or in ~/.local/bin; install it (https://lightpanda.io/docs/open-source/installation) or set LIGHTPANDA_PATH. - Docs page rendered in
mint dev, sidebar icon and tables in place.
Checklist
- Changeset added (
pnpm changeset) for any change to a published package, or the change is testbed, docs, or CI only. - Breaking change: title carries
!, the changeset body names what breaks and what replaces it, and the deprecation warning landed a window earlier (stability policy in CONTRIBUTING.md). - Docs updated in the same PR: the
docs/**/*.mdxpage for the behavior, andskills/e2e/if the skill describes it. - Contract change: emitted
.d.tsreviewed,tests/types/sdk-types.tsupdated; wire change edits the schema and both fixtures. - Engine contract change (
e2e/engine): changesets fore2e,@e2e-dev/web, and@e2e-dev/mobile.