twd-cli
v1.1.4
Published
CLI tool for running TWD tests with Puppeteer
Maintainers
Readme
twd-cli
CI/CD runner for TWD (Test while developing) — executes your in-browser TWD tests in a headless environment. Puppeteer is only used to open the page; all tests run inside the real browser context against real DOM.
Installation
npm install twd-cliOr use directly with npx:
npx twd-cli runUsage
Basic Usage
Run tests with default configuration:
npx twd-cli runConfiguration
Create a twd.config.json file in your project root:
{
"url": "http://localhost:5173",
"timeout": 10000,
"coverage": true,
"coverageDir": "./coverage",
"nycOutputDir": "./.nyc_output",
"headless": true,
"puppeteerArgs": ["--no-sandbox", "--disable-setuid-sandbox"],
"retryCount": 2
}Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| url | string | "http://localhost:5173" | The URL of your development server |
| timeout | number | 10000 | Timeout in milliseconds for page load |
| coverage | boolean | true | Enable/disable code coverage collection |
| coverageDir | string | "./coverage" | Directory to store coverage reports |
| nycOutputDir | string | "./.nyc_output" | Directory for NYC output |
| headless | boolean | true | Run browser in headless mode |
| puppeteerArgs | string[] | ["--no-sandbox", "--disable-setuid-sandbox"] | Additional Puppeteer launch arguments |
| retryCount | number | 2 | Number of attempts per test before reporting failure. Set to 1 to disable retries |
| contracts | array | — | OpenAPI contract validation specs (see Contract Validation) |
| contractReportPath | string | — | Path to write a markdown report for CI/PR integration |
How It Works
Important: Puppeteer is not used as a testing framework here. It simply provides a headless browser to load your application — the same way a user would open Chrome. Once the page loads, all test execution happens inside the real browser context through the TWD runner. Your tests interact with real DOM, real components, and real browser APIs — Puppeteer just opens the door and gets out of the way.
- Launches a headless browser via Puppeteer (the only thing Puppeteer does)
- Navigates to your dev server URL
- Waits for the app and TWD sidebar to be ready
- TWD's in-browser test runner executes all tests against the real DOM
- Collects and reports test results
- Validates collected mocks against OpenAPI contracts (if configured)
- Optionally collects code coverage data
- Exits with appropriate code (0 for success, 1 for failures)
CI/CD Integration
Using the GitHub Action (recommended)
The easiest way to run TWD tests in CI. Handles Puppeteer caching, Chrome installation, and optional contract report posting in a single step:
name: TWD Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
pull-requests: write # only needed if using contract-report
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- name: Install dependencies
run: npm ci
- name: Install mock service worker
run: npx twd-js init public --save
- name: Start dev server
run: |
nohup npm run dev > /dev/null 2>&1 &
npx wait-on http://localhost:5173
- name: Run TWD tests
uses: BRIKEV/twd-cli/.github/actions/run@main
with:
contract-report: 'true'Action Inputs
| Input | Default | Description |
|-------|---------|-------------|
| working-directory | . | Directory where twd.config.json lives |
| contract-report | false | Post contract validation summary as a PR comment |
With code coverage
The action runs in the same job, so coverage data is available for subsequent steps:
- name: Run TWD tests
uses: BRIKEV/twd-cli/.github/actions/run@main
- name: Display coverage
run: npm run collect:coverage:textCustom setup (without the action)
If you prefer full control, set up each step manually. Puppeteer 24+ no longer auto-downloads Chrome, so you need to install it explicitly:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 24
cache: npm
- name: Install dependencies
run: npm ci
- name: Install mock service worker
run: npx twd-js init public --save
- name: Start dev server
run: |
nohup npm run dev > /dev/null 2>&1 &
npx wait-on http://localhost:5173
- name: Cache Puppeteer browsers
uses: actions/cache@v4
with:
path: ~/.cache/puppeteer
key: ${{ runner.os }}-puppeteer-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-puppeteer-
- name: Install Chrome for Puppeteer
run: npx puppeteer browsers install chrome
- name: Run TWD tests
run: npx twd-cli run
- name: Display coverage
run: npm run collect:coverage:textContract Validation
Validate your test mocks against OpenAPI specs to catch drift between your mocks and the real API. When a mock response doesn't match the spec, you'll see errors like:
Source: ./contracts/users-3.0.json ERROR
✓ GET /users (200) — mock "getUsers"
✗ GET /users/{userId} (200) — mock "getUserBadAddress"
→ response.address.city: missing required property
→ response.address.country: missing required property
⚠ GET /users/{userId} (404) — mock "getUserNotFound"
Status 404 not documented for GET /users/{userId}Setup
- Add your OpenAPI specs to the project (JSON format, 3.0 or 3.1):
contracts/
users-3.0.json
posts-3.1.json- Configure contracts in
twd.config.json:
{
"url": "http://localhost:5173",
"contractReportPath": ".twd/contract-report.md",
"contracts": [
{
"source": "./contracts/users-3.0.json",
"baseUrl": "/api",
"mode": "error",
"strict": true
},
{
"source": "./contracts/posts-3.1.json",
"baseUrl": "/api",
"mode": "warn",
"strict": true
}
]
}Contract Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| source | string | — | Path to the OpenAPI spec file (JSON) |
| baseUrl | string | "/" | Base URL prefix to strip when matching mock URLs to spec paths |
| mode | "error" | "warn" | "warn" | error fails the test run, warn reports but doesn't fail |
| strict | boolean | true | When true, rejects unexpected properties not defined in the spec |
Supported Schema Validations
The validator checks all standard OpenAPI/JSON Schema constraints:
- Types:
string,number,integer,boolean,array,object - String:
minLength,maxLength,pattern,format(date, date-time, email, uuid, uri, hostname, ipv4, ipv6) - Number/Integer:
minimum,maximum,exclusiveMinimum,exclusiveMaximum,multipleOf - Array:
minItems,maxItems,uniqueItems - Object:
required,additionalProperties - Composition:
oneOf,anyOf,allOf - Enum: validates against allowed values
- Nullable: supports both OpenAPI 3.0 (
nullable: true) and 3.1 (type: ["string", "null"])
PR Reports
When contractReportPath is set and you use the action with contract-report: 'true', a summary table is posted as a PR comment:
| Spec | Passed | Failed | Warnings | Mode |
|------|--------|--------|----------|------|
| users-3.0.json | 2 | 3 | 1 | error |
| posts-3.1.json | 2 | 2 | 0 | warn |
Failed validations are included in a collapsible details section with a link to the full CI log.
Requirements
- Node.js >= 20.19.x
- A running development server with TWD tests
