← All @molecule/* packages · App templates

@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-playwright

npm · 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 too

Works with: @molecule/app-bond, @molecule/app-e2e

Reference

Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit src/index.ts JSDoc, not this file.

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/test never downloads them on npm 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-playwright of the sandbox user; PLAYWRIGHT_BROWSERS_PATH points there too), pinned to the same Playwright version the scaffold's @playwright/test uses. It is the headless shell, so headless: false has no display to open, and the firefox/webkit engines are not baked — Chromium is the sandbox engine. Chromium runs with Playwright's default chromiumSandbox: false (the container is the sandbox), and /tmp there is a 256 MB tmpfs, which is where its per-launch profile goes.

  • MOL_E2E_BROWSER=firefox|webkit picks the engine; MOL_E2E_HEADED=1 shows 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.