@apica-io/asm-playwright-runner
v1.0.0-dev.39
Published
CLI wrapper for Playwright collections or scripts with dynamic actions, config, and test result models.
Readme
@apica-io/asm-playwright-runner
A lightweight CLI wrapper around Playwright that executes browser automation from multiple input formats, captures a rich execution trace, and emits a structured, machine-readable result model.
It is designed to run a single "collection" — a Playwright script, a Playwright Test file, a Python pytest file, or a declarative JSON flow — and turn its execution into consistent artifacts (trace model, screenshots, sources, and a zipped bundle) that downstream tooling can consume.
Features
- Four input formats — declarative JSON flows, plain Playwright scripts, Playwright Test
(
@playwright/test) files, and PythonpytestPlaywright tests. - Automatic script-type detection — the correct execution strategy is chosen from the file extension and contents; no flag required.
- Multi-browser — Chromium, Firefox, and WebKit.
- Headless or headed execution.
- Structured trace model — every run produces a
trace-model.jsondescribing actions, events, console/stdio, network resources, timings, and errors. - Artifact generation — screenshots, source files, and a combined
artifacts.zip. - Custom Chromium/Chrome executable path.
- SSL client-certificate authentication (mutual TLS).
- Extra HTTP headers injection.
- Configurable timeouts and log levels.
- Pass-through of arbitrary Playwright CLI arguments via advanced options.
Requirements
- Node.js 18+
- Playwright browsers installed (
npx playwright install) - For Python pytest collections only:
- Python 3.8+
pytest-playwrightavailable onPATH(pip install pytest-playwright && playwright install)
Installation
Global
npm install -g @apica-io/asm-playwright-runnerAs a project dependency
npm install @apica-io/asm-playwright-runnerThen invoke it via npx asm-playwright-runner … or an npm script.
Usage
asm-playwright-runner <collection> [options]<collection> is the path to the file to execute. Its type is detected automatically:
| File pattern | Detected type | Execution strategy |
| ------------------------------------ | ------------------------ | ------------------------------------- |
| *.json | JSON flow | Built-in action runner |
| *.py | Python Playwright | pytest |
| contains test( | Playwright Test | npx playwright test |
| contains export default | Plain Playwright script | Direct invocation of the default export |
Options
| Option | Description | Default |
| ------------------------------------ | --------------------------------------------------------------- | ---------- |
| -b, --browser <browser> | Browser type (chromium, firefox, webkit) | chromium |
| -v, --verbose | Print collection information on stdout | false |
| --chromiumPath <path> | Custom Chromium/Chrome executable path | — |
| --headless | Run browser headless | true |
| --no-headless | Run browser with a visible UI | — |
| -r, --resultDir <dir> | Directory for result artifacts | result |
| -l, --logLevel <logLevel> | Log level (info, debug, error) | info |
| --extraHTTPHeaders <headers> | Extra HTTP headers as a JSON string | — |
| --timeout <timeout> | Test timeout in milliseconds | — |
| -op, --advancedOptions <args...> | Additional raw Playwright CLI arguments (Test/pytest only) | — |
| -rv, --returnResult | Print the full structured result object to stdout | false |
| -rs, --includeSource | Include source files in the extracted results | false |
| --sslClientCert <path> | Client certificate (PEM) | — |
| --sslClientKey <path> | Client certificate private key | — |
| --sslClientPassphrase <passphrase> | Client certificate passphrase | — |
Option applicability by collection type
The runner manages the browser directly for JSON flows and plain Playwright scripts, but delegates Playwright Test and pytest collections to their native CLIs. As a result, some options only apply to certain types:
| Option | JSON flow | Plain script | Playwright Test | pytest |
| --------------------- | :-------: | :----------: | :-------------: | :----: |
| --browser | ✅ | ✅ | ✅ | ✅ |
| --headless / --no-headless | ✅ | ✅ | ✅ (--headed) | — |
| --chromiumPath | ✅ | ✅ | — | — |
| --timeout | ✅ | ✅ | ✅ | — |
| --extraHTTPHeaders | ✅ | ✅ | — | — |
| --sslClient* | ✅ | ✅ | — | — |
| --advancedOptions | — | — | ✅ | ✅ |
| --resultDir, --logLevel, --verbose, --returnResult, --includeSource | ✅ | ✅ | ✅ | ✅ |
Examples
Run a plain Playwright script
asm-playwright-runner ./samples/playwright-script.spec.tsRun a Playwright Test file
asm-playwright-runner ./samples/playwright-test-script.spec.ts --browser chromium --headlessRun a Python pytest file
asm-playwright-runner ./samples/new-script-python.py --browser chromium -r resultpy -l debugRun a JSON flow
asm-playwright-runner ./samples/example.json --browser chromium -r resultsRun with Firefox
asm-playwright-runner ./scripts/test.spec.ts --browser firefoxRun with a visible browser
asm-playwright-runner ./scripts/test.spec.ts --no-headlessStore results in a specific directory
asm-playwright-runner ./scripts/test.spec.ts --resultDir ./resultsUse a custom Chromium binary
macOS:
asm-playwright-runner ./scripts/test.spec.ts \
--chromiumPath "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"Windows:
asm-playwright-runner ./scripts/test.spec.ts \
--chromiumPath "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"Inject extra HTTP headers
asm-playwright-runner ./scripts/test.spec.ts \
--extraHTTPHeaders '{"Authorization":"Bearer token","X-Test":"true"}'Configure a timeout
asm-playwright-runner ./scripts/test.spec.ts --timeout 120000SSL client-certificate (mutual TLS) authentication
asm-playwright-runner ./scripts/test.spec.ts \
--sslClientCert ./client-cert.pem \
--sslClientKey ./client-key.pem \
--sslClientPassphrase mypasswordPass raw arguments to the Playwright/pytest CLI
asm-playwright-runner ./tests/e2e.spec.ts --advancedOptions --workers=2 --retries=1Print the structured result to stdout
asm-playwright-runner ./scripts/test.spec.ts --returnResultInput formats
1. Plain Playwright script
A module that default-exports an async function receiving a Playwright Page. The
runner launches the browser, creates a page, and invokes the function.
import { expect, Page } from "playwright/test";
export default async function example(page: Page) {
await page.goto("https://playwright.dev/");
await expect(page).toHaveTitle(/Playwright/);
await page.getByRole("link", { name: "Get started" }).click();
await expect(page.getByRole("heading", { name: "Installation" })).toBeVisible();
}
.tsfiles are transpiled on the fly viatsx(falling back tots-nodeif present).
2. Playwright Test file
A standard @playwright/test file using test(...).
Executed through npx playwright test with tracing enabled.
import { test, expect } from '@playwright/test';
test('has title', async ({ page }) => {
await page.goto('https://apica.io/');
await expect(page).toHaveTitle(/Apica/);
});3. Python pytest file
A standard pytest-playwright test. Executed
through pytest with --tracing on.
import re
from playwright.sync_api import Page, expect
def test_has_title(page: Page):
page.goto("https://playwright.dev/")
expect(page).to_have_title(re.compile("Playwright"))4. JSON flow
A declarative collection of steps run by the built-in action runner — no code required.
{
"name": "example",
"steps": [
{ "action": "goto", "url": "https://playwright.dev/" },
{ "action": "assertTitle", "expected": "Playwright" },
{ "action": "click", "selector": "role=link[name='Get started']" },
{ "action": "waitForSelector", "selector": "role=heading[name='Installation']" },
{ "action": "assertVisible", "selector": "role=heading[name='Installation']" }
]
}Supported actions
| Action | Required fields | Description |
| ----------------- | ------------------------ | --------------------------------------------- |
| goto | url | Navigate to a URL |
| click | selector | Click an element |
| dblclick | selector | Double-click an element |
| hover | selector | Hover over an element |
| type | selector, value | Fill an input with a value |
| press | selector, key | Press a key while focused on an element |
| keyboardType | text | Type text via the keyboard |
| keyboardPress | key | Press a key via the keyboard |
| check | selector | Check a checkbox/radio |
| uncheck | selector | Uncheck a checkbox |
| selectOption | selector, value | Select an option in a <select> |
| uploadFile | selector, files | Set input files for an upload control |
| screenshot | path | Capture a screenshot to path |
| reload | — | Reload the current page |
| waitForSelector | selector | Wait for an element to appear |
| waitForTimeout | ms | Wait for a fixed duration (ms) |
| waitForResponse | urlPattern | Wait for a matching network response |
| assertText | selector, expected | Assert element text contains expected |
| assertTitle | expected | Assert page title contains expected |
| assertVisible | selector | Assert element is visible |
Output artifacts
When a run completes, the following are written under --resultDir (default result):
trace-model.json— the structured execution model (actions, events, stdio, network resources, timings, errors). For Playwright Test / pytest runs, a combined model keyed by run name is written at the top level, with per-run models in each subdirectory.trace.zip— the raw Playwright trace (JSON-flow and plain-script runs).screenshots/— screenshots/screencast frames extracted from the trace.source/— source files anderror-context.md(only when--includeSourceis set).artifacts.zip— a bundle of the screenshots and source directories.
When --logLevel debug is set, raw trace dumps (trace-raw-data.json,
test-trace-raw-data.json) are also written next to each trace for debugging.
With --returnResult, the combined model is additionally printed to stdout as JSON so a
calling process can capture it directly.
Exit codes
0— run completed successfully.1— the collection file was missing, script-type detection failed, a step/test failed, or a trace could not be processed.
Development
# Install dependencies
npm install
# Build (TypeScript -> dist/)
npm run build
# Type-check tests
npm run typecheck
# Run the test suite
npm test
npm run test:watch
npm run test:coverageConvenience scripts for running the bundled samples with ts-node are defined in
package.json (e.g. npm run test:playwright-script, npm run test:playwright-json,
npm run test:playwright-python).
License
ISC © Apica
