# tape-six-puppeteer
> A helper for [tape-six](https://github.com/uhop/tape-six) that runs test files in a headless browser via Puppeteer. Each test file runs in its own iframe inside headless Chrome. The npm package name is `tape-six-puppeteer` and the CLI command is `tape6-puppeteer`.
- Real browser environment: tests run in headless Chrome with full DOM and browser API access
- Iframe isolation: each test file runs in its own iframe
- Cross-runtime: Node, Deno, and Bun with the same test files
- Drop-in companion for `tape6` (worker-thread runner) and `tape6-proc` (subprocess runner)
- Same configuration format as `tape-six`
- Parallel execution with configurable concurrency
- TAP, TTY (colored), JSONL, and minimal output formats
## Install
```bash
npm i -D tape-six-puppeteer
```
Puppeteer's bundled Chromium is installed automatically via `postinstall`.
## Quick start
Write a test (`tests/test-dom.js`):
```js
import test from 'tape-six'
test('DOM works', t => {
const el = document.createElement('div')
el.textContent = 'hello'
document.body.appendChild(el)
t.equal(document.body.lastChild.textContent, 'hello', 'element created')
})
```
Run all configured tests via Puppeteer:
```bash
tape6-puppeteer --start-server --flags FO
```
## CLI: tape6-puppeteer
Runs test files in parallel, each in its own iframe inside headless Chrome.
```bash
tape6-puppeteer [--flags FLAGS] [--par N] [--start-server] [--server-url URL] [--info] [--help] [--version] [tests...]
```
### Options
- `--flags FLAGS` (`-f`) — output control flags (see Supported flags below).
- `--par N` (`-p`) — number of parallel iframes. Default: all CPU cores (via `os.availableParallelism()` or `navigator.hardwareConcurrency`).
- `--start-server` — auto-start `tape6-server` if not already running.
- `--server-url URL` (`-u`) — server URL. Overrides `TAPE6_SERVER_URL` and `HOST`/`PORT`.
- `--self` — prints the absolute path to `tape6-puppeteer.js` and exits. Used in cross-runtime scripts.
- `--info` — prints runtime, reporter, flags, parallelism, and resolved test files, then exits. Does not require a running server.
- `--help` (`-h`) — shows help message with all options and flag descriptions, then exits.
- `--version` (`-v`) — prints version and exits.
- Positional arguments: test file glob patterns. If none given, resolved from configuration.
- Options accept `--flags FO` or `--flags=FO`. The `=` form does not support quoting.
### Examples
```bash
# Run all configured tests
tape6-puppeteer --start-server --flags FO
# Run specific test files
tape6-puppeteer --start-server tests/test-dom.js
# Limit parallelism
tape6-puppeteer --start-server --par 2 --flags FO
# Use with already-running server
tape6-puppeteer --flags FO
```
## Cross-runtime usage
`tape6-puppeteer` is a Node CLI by default. For Bun and Deno, use the `--self` flag to get the script path:
```json
{
"scripts": {
"test": "tape6-puppeteer --start-server --flags FO",
"test:bun": "bun run `tape6-puppeteer --self` --start-server --flags FO",
"test:deno": "deno run -A `tape6-puppeteer --self` --start-server --flags FO"
}
}
```
## Supported flags
Flags are a string of characters. Uppercase = enabled, lowercase = disabled.
- `F` — Failures only: show only failed tests.
- `T` — show Time for each test.
- `B` — show Banner with summary.
- `D` — show Data of failed tests.
- `O` — fail Once: stop at first failure.
- `N` — show assert Number.
- `M` — Monochrome: no colors.
- `C` — don't Capture console output.
- `H` — Hide streams and console output.
Usage:
```bash
tape6-puppeteer --start-server --flags FO
TAPE6_FLAGS=FO tape6-puppeteer --start-server
```
## Server
`tape6-puppeteer` requires `tape6-server` (from `tape-six`) to serve test files to the browser.
- `--start-server`: auto-starts the server before running tests.
- Without it: the server must already be running. The runner prints instructions if it's unreachable.
- Server URL: `TAPE6_SERVER_URL` env var, or `HOST`/`PORT`, or default `http://localhost:3000`.
- Server endpoints used: `GET /--tests` (test file list), `GET /--patterns?q=...` (filtered file list), `GET /--importmap` (import map).
## Configuration
Configuration is read from `tape6.json` or the `"tape6"` section of `package.json` (same format as `tape-six`):
```json
{
"tape6": {
"browser": ["/tests/test-*.html"],
"tests": ["/tests/test-*.*js"],
"importmap": {
"imports": {
"tape-six": "/node_modules/tape-six/index.js",
"tape-six/": "/node_modules/tape-six/src/"
}
}
}
}
```
The `importmap` section is served by `tape6-server` at `/--importmap` and injected into each iframe for module resolution.
## Environment variables
- `TAPE6_FLAGS` — flags string (combined with `--flags` CLI argument).
- `TAPE6_PAR` — number of parallel iframes (overridden by `--par`).
- `TAPE6_TAP` — force TAP reporter (any non-empty value).
- `TAPE6_JSONL` — force JSONL reporter (any non-empty value).
- `TAPE6_MIN` — force minimal reporter (any non-empty value).
- `TAPE6_SERVER_URL` — full server URL override (e.g. `http://localhost:4000`). Overridden by `--server-url`.
- `HOST` — server hostname (default: `localhost`).
- `PORT` — server port (default: `3000`).
## Architecture
### Entry point
`bin/tape6-puppeteer.js` is the CLI entry point:
- With `--self`: prints its own absolute path and exits.
- Otherwise: delegates to `bin/tape6-puppeteer-node.js`.
### Main CLI (`bin/tape6-puppeteer-node.js`)
1. Parses CLI arguments via `getOptions()` from `tape-six` (`--flags`, `--par`, `--start-server`, `--server-url`, `--info`, positional test patterns).
2. Initializes the reporter via `initReporter()` from `tape-six`.
3. Ensures `tape6-server` is reachable (auto-starts if `--start-server`).
4. Fetches test files from server via `GET /--patterns?q=...` (if patterns given) or `GET /--tests`.
5. Fetches importmap from `GET /--importmap`.
6. Creates a `TestWorker` instance and executes all test files.
7. Reports final results and exits with code 0 (success) or 1 (failures).
8. Kills auto-started server on exit.
### TestWorker (`src/TestWorker.js`)
Extends `EventServer` from `tape-six`. Manages Puppeteer browser and iframe execution:
- **`constructor(reporter, numberOfTasks, options)`** — launches headless Chrome, creates a page, exposes `__tape6_reporter` and `__tape6_error` as page globals.
- **`makeTask(fileName)`** — creates an iframe for the test file. Returns a task ID.
- **`destroyTask(id)`** — removes the iframe from the page.
- **`cleanup()`** — closes the browser.
### Iframe lifecycle
For `.html` files:
1. Set iframe `src` to the file URL with query parameters (`id`, `test-file-name`, `flags`).
2. The HTML file loads `tape-six` which auto-detects `window.parent.__tape6_reporter`.
For `.js`/`.mjs` files:
1. Create iframe, write an HTML document with `importmap` and a dynamic `