Lightpanda
Extends CDPBrowser
Lightpanda drives Lightpanda, a headless browser written from scratch for automation, exposed over the Chrome DevTools Protocol. It executes real JavaScript in V8 and implements the DOM and Web APIs, but has no graphical rendering engine: nothing is ever painted, so there are no screenshots.
This helper is a thin CDPBrowser subclass: it changes nothing about how locating or acting on
elements works, it only pins the config presets Lightpanda requires and manages the
lightpanda serve process lifecycle, the same way Playwright manages its own browser process.
Lightpanda support is experimental. Pin the browser version in CI and keep a Playwright/WebDriver job for browser-compatibility coverage.
- ATTACH —
endpointis set explicitly in the config. The helper only connects to it; it never spawns or kills anything, no matter whatbinaryPath/portare set to. - SELF-LAUNCH —
endpointis unset and a binary can be resolved, in order:binaryPathin the config, then theLIGHTPANDA_PATHenvironment variable, thenlightpandaonPATH. The helper spawnslightpanda serve --host 127.0.0.1 --port <port>(portfrom the config, or a free port picked automatically), waits for it to answer, connects, and kills it in_finishTest. - COURTESY-ATTACH —
endpointis unset and no binary can be resolved, but something already answershttp://127.0.0.1:9222/json/version(e.g.lightpanda servestarted by hand, or thelightpanda/browserDocker image). The helper attaches to it and never kills it. If neither a binary nor a running server on :9222 can be found, the helper throws a loud, actionable error.
Install
Section titled “Install”Follow the official installation instructions,
then put lightpanda on your PATH, or point binaryPath/LIGHTPANDA_PATH at it. The helper
then launches and tears it down automatically.
Lightpanda sends usage telemetry by default. This helper always spawns it with
LIGHTPANDA_DISABLE_TELEMETRY=true; set that variable yourself when you start the server by hand.
Lightpanda is licensed under AGPL-3.0. It runs as a separate process that CodeceptJS talks to over a WebSocket, so it does not change the license of CodeceptJS or of your tests.
Config presets
Section titled “Config presets”These are set automatically and only need overriding for unusual setups:
| option | value | why |
|---|---|---|
input | synthetic | nothing is painted, so coordinates are not hit-tested; click always takes the forceClick path |
xpathPolyfill | auto | probed per binary/page |
capabilities.layout | real | Lightpanda computes visibility-related styles and element boxes without painting, which is enough for seeElement and the waitForVisible family; it is pinned because the runtime layout probe cannot run on Lightpanda’s about:blank |
capabilities.screenshot | false | there is no rendering engine |
Limitations
Section titled “Limitations”- No screenshots and no screencast:
saveScreenshotandsaveElementScreenshotdo nothing (a debug message is printed). - No frames or popups.
- No scrolling: scroll positions always stay at 0.
- Computed styles cover what visibility checks need (
display,visibility,opacity,pointer-events);grabCssPropertyFromandseeCssPropertiesOnElementsare unreliable for other properties. - No coordinate-based input (
clickXY). - No clipboard access.
- Some rich text editors (TinyMCE, Trix, Monaco) never finish initialising.
Configuration
Section titled “Configuration”This helper should be configured in codecept.conf.js
Type: object
Properties
Section titled “Properties”endpointstring? explicit CDP endpoint. Setting this switches the helper to ATTACH mode: it only connects, and never spawns or kills a process, no matter what else is configured. Leave it unset for SELF-MANAGED mode (see below).binaryPathstring? path to thelightpandaexecutable, used in SELF-MANAGED mode (endpointunset). Checked beforeLIGHTPANDA_PATHandPATH.portnumber? portlightpanda servelistens on, in SELF-MANAGED mode. When unset, a free port is picked automatically, which is what makesrun-workerscollision-free — every worker gets its own instance on its own port with zero config.serverStartTimeoutnumber? milliseconds to wait for a spawnedlightpanda serveto answer/json/versionbefore_connectgives up.
Example
Section titled “Example”// inside codecept.conf.js — SELF-LAUNCH mode (recommended): the helper finds/starts/stops// lightpanda serve on its own, on a free port. Ideal for run-workers: every worker gets its// own instance with no config.{ helpers: { Lightpanda: { url: 'http://localhost', } }}// ATTACH mode — connect to a Lightpanda instance you manage yourself (remote host, container, etc.){ helpers: { Lightpanda: { url: 'http://localhost', endpoint: 'http://127.0.0.1:9222', } }}Methods
Section titled “Methods”Parameters
Section titled “Parameters”configLightpandaConfig