npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

histrion

v4.6.0

Published

Scaffold a production-grade Playwright + TypeScript project with Page Object Model architecture

Readme

What you get

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 --headed and --auth support 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

Quick start

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 directory

The 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 .

Page scanner

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.

Element extractor

See an element in DevTools? Copy it and get every possible Playwright locator ranked by stability:

  1. Right-click an element in Chrome DevTools > Copy > Copy element
  2. 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>'

Scanning authenticated pages

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.json

The golden rule

Tests never contain selectors. They read like specifications.

test('user can log in', async ({ loginPage }) => {
  await loginPage.navigate();
  await loginPage.fillCredentials({ username: '[email protected]', 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.

Built-in structured logger

Every Page Object, Component, and API action is traced automatically:

14:32:01 ■ LoginPage       │ 🔹 Filling credentials for [email protected]
14:32:01 ■ LoginPage       │    ▸ Fill "username" with "[email protected]"
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.

Architecture

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.

Starter templates

The scaffolded project includes ready-to-use boilerplate:

  • Page Objectsrc/pages/example.page.ts with locators, actions, and assertions sections
  • Test filetests/e2e/example.spec.ts with describe block, beforeEach, and test structure
  • Type definitionsrc/data/types/example.ts for your page's data shape
  • Fixture wiringsrc/fixtures/index.ts pre-configured

Open example.page.ts and follow docs/15-writing-your-first-test.md to adapt them to your app.

AI coding assistant instructions

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.

Adding a new page — 3 steps

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');
});

Available scripts

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

Environment management

TEST_ENV=staging npm test    # staging environment
TEST_ENV=dev npm test        # dev environment
BASE_URL=https://custom.url npm test  # override URL

Environments are defined in src/config/env.config.ts with per-env timeouts, retries, workers, and headless mode.

Documentation

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.

What gets installed

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

Requirements

  • Node.js 18+
  • npm 8+

License

MIT