Playwright testing toolkit — scaffold projects and generate Page Objects.
Page Object Model · Typed fixtures · Data builders · Visual regression · CI/CD · Page scanner
A histrion is a dramatic actor — and the perfect companion for Playwright.
Run one command. Answer a few questions. Get a fully configured project with:
- Page Object Model architecture — layered separation of concerns
- Reusable components — Table, Modal, Form, Toast out of the box
- Type-safe fixtures — Page Objects injected into tests automatically
- Fluent data builders — chainable test data construction with optional Faker.js for realistic random data
- API helpers — setup/teardown without touching the UI
- Visual regression — screenshot comparison with smart masking
- Custom HTML reporter — dark-mode, filterable, tag-aware, auto-open on failure
- Structured logger — every action traced with color-coded timestamps, fully customizable theme
- Custom expect matchers — domain-specific assertions
- Biome — linting + formatting in one tool, zero config
- GitHub Actions — CI/CD with matrix strategy, manual dispatch
- Starter templates — Page Object, fixture & test boilerplate ready to fill in
- AI instructions — optional rules for Copilot, Claude Code, Cursor, or Windsurf so your AI assistant follows the architecture
- Page scanner — analyze any live page and generate a Page Object automatically, with
--headedand--authsupport for authenticated pages - Element extractor — copy any HTML element from DevTools, get every Playwright locator ranked by stability
- 20 documentation guides — from getting started to best practices, including a glossary
npx histrion create # interactive — prompts for project name
npx histrion create my-e2e-tests # create in a new folder
npx histrion create . # scaffold in current directoryThe CLI scaffolds the project, installs dependencies, downloads Playwright browsers, runs a lint check, and initializes git. You walk away with a ready-to-use test suite.
⚡ histrion create — scaffold a production-grade Playwright project
- Project name: my-e2e-tests
- Application base URL: https://your-app.com
- Include starter template files? Yes
- Install Faker.js? Yes
- Include visual regression tests? Yes
- Include API helpers for setup/teardown? Yes
- Include GitHub Actions CI/CD? Yes
- AI coding assistant instructions? GitHub Copilot, Claude Code
✓ Scaffolded 38 files
✓ Dependencies installed
✓ Playwright browsers installed
✓ All files pass lint & format
✓ Git repository initialized with first commit
✓ Project ready!
Get started:
cd my-e2e-tests
code .
Don't write Page Objects from scratch. Point the scanner at any page and get a ready-to-use file:
npx histrion scan https://myapp.com/login 🔍 histrion scan — analyze page & generate Page Object
✓ Page loaded — "Login"
✓ Found 5 interactive elements
Scan results:
Element Strategy
────────────────────────────────────
emailInput getByTestId
passwordInput getByTestId
loginButton getByTestId
forgotPasswordLink getByRole
navLogoLink locator(css)
✓ Page Object generated
File: src/pages/login.page.ts
Stable locators: 3/5 (60%)
The scanner prioritizes stable, language-independent locators (data-testid, id) over locale-dependent ones (getByRole, getByLabel). Works on any website — no Histrion project required.
See an element in DevTools? Copy it and get every possible Playwright locator ranked by stability:
- Right-click an element in Chrome DevTools > Copy > Copy element
- Run:
npx histrion extract 🔍 Analyzing element...
Root: <div> with text "You logged into a secure area!"
┌─────────────────────────────────────────────────────────────────────────────┐
│ # Strategy Locator Stability│
├─────────────────────────────────────────────────────────────────────────────┤
│ 1 locator#id locator("#flash") 🟢 │
│ 2 getByRole getByRole("alert", { name: "You logged in..." }) 🟡 │
│ 3 getByText getByText("You logged into a secure area!") 🔴 │
└─────────────────────────────────────────────────────────────────────────────┘
Select locator [1]: _
Copy-paste ready:
private readonly flash = this.page.locator("#flash");
The extractor reads your clipboard automatically (macOS, Linux, Windows). It also analyzes child elements — if you copy a parent <div>, any child <button> or <input> with meaningful attributes gets its own locator table. Pick any locator by number and get a copy-paste ready private readonly declaration.
Also accepts inline HTML: npx histrion extract '<button id="ok">OK</button>'
Need to scan a page behind login? Two options:
# Open a visible browser — log in manually, press Enter to scan
npx histrion scan https://myapp.com/settings --headed
# Use a saved auth state (cookies + localStorage)
npx histrion scan https://myapp.com/settings --auth auth/admin.json
# Both — pre-load auth, but open headed for manual navigation
npx histrion scan https://myapp.com/settings --headed --auth auth/admin.jsonTests never contain selectors. They read like specifications.
test('user can log in', async ({ loginPage }) => {
await loginPage.navigate();
await loginPage.fillCredentials({ username: 'user@test.com', password: 's3cret' });
await loginPage.submit();
await loginPage.expectDashboard();
});If you see a page.click() or a data-testid in a test file, something went wrong.
Every Page Object, Component, and API action is traced automatically:
14:32:01 ■ LoginPage │ 🔹 Filling credentials for user@test.com
14:32:01 ■ LoginPage │ ▸ Fill "username" with "user@test.com"
14:32:02 ■ LoginPage │ ▸ Fill "password" with "***"
14:32:02 ■ LoginPage │ 🔹 Submitting login form
14:32:03 ■ LoginPage │ ✓ Dashboard visible
Five log levels (step, action, success, warn, error) with customizable colors, icons, and formatting. Add your own levels in one file — see src/utils/logger.ts.
src/
├── core/ Abstract base classes (BasePage, BaseComponent, BaseAPI)
├── components/ Reusable UI components (Table, Modal, Form, Toast)
├── pages/ Page Objects — one per page of your app
├── fixtures/ Type-safe dependency injection into tests
├── api/ HTTP clients for test setup/teardown
├── data/
│ ├── builders/ Fluent test data builders (with Faker.js)
│ └── types/ Domain types
├── config/ Environment & user configuration
├── reporters/ Custom HTML reporter
└── utils/ Logger, visual helpers, custom matchers
tests/
├── e2e/ End-to-end test specs
└── visual/ Visual regression specs
docs/ Local documentation (20 guides, gitignored)
Dependencies flow down only. Tests → Fixtures → Pages → Components → Core → Config.
The scaffolded project includes ready-to-use boilerplate:
- Page Object —
src/pages/example.page.tswith locators, actions, and assertions sections - Test file —
tests/e2e/example.spec.tswith describe block, beforeEach, and test structure - Type definition —
src/data/types/example.tsfor your page's data shape - Fixture wiring —
src/fixtures/index.tspre-configured
Open example.page.ts and follow docs/15-writing-your-first-test.md to adapt them to your app.
During scaffolding, you can generate instruction files for your AI coding assistant. These encode the full POM architecture rules so the AI follows your conventions — private locators, fixtures, logger usage, naming patterns, and more.
Supported tools:
| Tool | Generated file |
|---|---|
| GitHub Copilot | .github/copilot-instructions.md |
| Claude Code | CLAUDE.md |
| Cursor | .cursorrules |
| Windsurf | .windsurfrules |
Select one or more during histrion create. The content is identical — same rules, different filenames.
1. Create the Page Object (src/pages/settings.page.ts):
export class SettingsPage extends BasePage {
readonly path = '/settings';
readonly pageTitle = /Settings/;
private readonly nameInput = this.page.getByTestId('settings-name');
private readonly saveButton = this.page.getByTestId('settings-save');
async updateName(name: string): Promise<void> {
await this.fill(this.nameInput, name, 'name');
await this.click(this.saveButton, 'Save');
}
}2. Register the fixture (src/fixtures/index.ts):
settingsPage: async ({ page }, use) => {
await use(new SettingsPage(page));
},3. Use in tests:
test('can update name', async ({ settingsPage }) => {
await settingsPage.navigate();
await settingsPage.updateName('New Name');
});| Script | Description |
|---|---|
npm test |
Run all tests |
npm run test:smoke |
Run @smoke tagged tests |
npm run test:regression |
Run @regression tagged tests |
npm run test:visual |
Visual regression tests |
npm run test:ui |
Open Playwright UI mode |
npm run test:debug |
Step-by-step debugger |
npm run test:staging |
Run against staging env |
npm run lint |
Check with Biome |
npm run lint:fix |
Auto-fix lint issues |
npm run codegen |
Playwright code generator |
TEST_ENV=staging npm test # staging environment
TEST_ENV=dev npm test # dev environment
BASE_URL=https://custom.url npm test # override URLEnvironments are defined in src/config/env.config.ts with per-env timeouts, retries, workers, and headless mode.
The scaffolded project includes 20 local documentation guides in docs/ (gitignored). They cover everything from architecture to best practices, written for developers new to the framework.
Open docs/00-index.md in VS Code or Obsidian to browse them.
| Package | Purpose |
|---|---|
@playwright/test |
E2E testing framework — browser automation, assertions, test runner |
typescript |
Type safety across Page Objects, builders, and fixtures |
@biomejs/biome |
Linting + formatting in one tool — replaces ESLint and Prettier |
dotenv |
Loads environment variables from .env for local configuration |
@faker-js/faker |
(optional) Generates realistic random test data in builders |
- Node.js 18+
- npm 8+
MIT