@molecule/app-e2e-playwright
Provider bond · e2e · App (browser) · v1.0.2 · Apache-2.0
Real Playwright browsers for the e2e bond — the user's machine and CI
npm install @molecule/app-e2e-playwrightnpm · Source on GitHub · Implements @molecule/app-e2e
How it works
@molecule/app-e2e-playwright is a provider bond on the app (browser) side: it implements the e2e core interface (@molecule/app-e2e) with a concrete vendor or library behind it.
Your code calls the core; you wire this provider once at startup. Swapping vendors later is one line in that wiring, not a rewrite.
// e2e/bonds.ts (scaffolded)
import { resolveE2EProviderName, setProvider } from '@molecule/app-e2e'
import { provider as playwright } from '@molecule/app-e2e-playwright'
import { provider as preview } from '@molecule/app-e2e-preview'
setProvider(resolveE2EProviderName() === 'preview' ? preview : playwright)
// a script
import { connectPlaywright } from '@molecule/app-e2e-playwright'
const page = await connectPlaywright({
baseURL: 'http://localhost:3000',
viewport: { width: 390, height: 844 },
})
await page.goto('/')
await page.screenshot({ path: 'home-phone.png' })
await page.close() // closes the context and the browser tooWorks with: @molecule/app-bond, @molecule/app-e2e
Reference
E2E bond that opens real Playwright browsers — Chromium, Firefox or WebKit
with everything Playwright offers: screenshots, traces, videos, network
interception. It is the bond a molecule sandbox uses too: every sandbox
image bakes Playwright's Chromium (the headless shell, its system libraries
and fonts), so npm run test:e2e runs there exactly as it does on your own
machine and in CI, against the app's own dev server on localhost, with no
IDE tab involved. @molecule/app-e2e-preview remains the way to drive the
live preview the person is watching.
When the test runner picks the playwright provider, @molecule/app-e2e's
test IS Playwright's test, so this bond is only reached by scripts that
call connect() themselves (a measurement script, a smoke check outside the
runner). Under npx playwright test, Playwright's own fixtures launch the
browser as usual.
Quick Start
// e2e/bonds.ts (scaffolded)
import { resolveE2EProviderName, setProvider } from '@molecule/app-e2e'
import { provider as playwright } from '@molecule/app-e2e-playwright'
import { provider as preview } from '@molecule/app-e2e-preview'
setProvider(resolveE2EProviderName() === 'preview' ? preview : playwright)
// a script
import { connectPlaywright } from '@molecule/app-e2e-playwright'
const page = await connectPlaywright({
baseURL: 'http://localhost:3000',
viewport: { width: 390, height: 844 },
})
await page.goto('/')
await page.screenshot({ path: 'home-phone.png' })
await page.close() // closes the context and the browser too
Type
provider
Installation
npm install @molecule/app-e2e-playwright @molecule/app-bond @molecule/app-e2e @playwright/test
API
Interfaces
PlaywrightConnectOptions
Options for provider.connect() beyond the core's.
interface PlaywrightConnectOptions extends E2EConnectOptions {
/** Browser to launch; default `chromium` (also `MOL_E2E_BROWSER`). */
browser?: PlaywrightBrowserName
/** Show the browser window; default headless (also `MOL_E2E_HEADED=1`). */
headed?: boolean
/** Extra launch options passed through to Playwright. */
launchOptions?: LaunchOptions
}
Types
PlaywrightBrowserName
Which Playwright browser to launch.
type PlaywrightBrowserName = 'chromium' | 'firefox' | 'webkit'
Functions
connectPlaywright(options?)
Open a real browser page from any script.
function connectPlaywright(options?: PlaywrightConnectOptions): Promise<Page>
Constants
provider
The bond: setProvider(provider) in your e2e/bonds.ts.
const provider: E2EProvider
Core Interface
Implements @molecule/app-e2e interface.
Bond Wiring
Setup function to register this provider with the core interface:
import { setProvider } from '@molecule/app-e2e'
import { provider } from '@molecule/app-e2e-playwright'
export function setupE2ePlaywright(): void {
setProvider(provider)
}
Injection Notes
Requirements
Peer dependencies:
@molecule/app-bond^1.0.1@molecule/app-e2e^1.0.0@playwright/test^1.40.0
Runtime Dependencies
-
@molecule/app-bond -
@molecule/app-e2e -
@playwright/test -
On your own machine, browsers are installed once with
npx playwright install chromium(@playwright/testnever downloads them onnpm install). The launch error says so when they are missing. -
Inside a molecule sandbox nothing is installed by hand: the image ships Chromium where Playwright looks by default (
~/.cache/ms-playwrightof the sandbox user;PLAYWRIGHT_BROWSERS_PATHpoints there too), pinned to the same Playwright version the scaffold's@playwright/testuses. It is the headless shell, soheadless: falsehas no display to open, and thefirefox/webkitengines are not baked — Chromium is the sandbox engine. Chromium runs with Playwright's defaultchromiumSandbox: false(the container is the sandbox), and/tmpthere is a 256 MB tmpfs, which is where its per-launch profile goes. -
MOL_E2E_BROWSER=firefox|webkitpicks the engine;MOL_E2E_HEADED=1shows the window (both are for your own machine). -
Budget, measured inside a sandbox at the free tier's cap (1 CPU, 1280 MB, 2026-09-22): the browser launches in 0.5–0.8 s; a spec file of four to seven tests takes 4–13 s including the runner's startup, 0.1–3 s per test; Chromium's peak RSS is ~170 MB and the runner's ~190 MB. Run ONE spec file per command so a run never meets the sandbox's per-command cap.