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

casewright

v0.0.1

Published

Generate interactive HTML test documentation right from your Playwright test automation solution

Readme

Casewright

Generate interactive HTML test documentation right from your Playwright test automation solution. Transform code-level test cases into human-readable documentation.

Installation

npm install casewright

Quick Start

Add Casewright as a reporter in your playwright.config.ts:

// playwright.config.ts
import { defineConfig } from '@playwright/test'

export default defineConfig({
  reporter: [['html'], ['casewright']],
})

Run your tests and documentation will be generated automatically:

npx playwright test

Open ./casewright/documentation.html to view your test documentation.

Configuration

Create a configuration file for more control:

npx casewright init

This creates casewright.config.ts:

// casewright.config.ts
import type { CasewrightConfig } from 'casewright'

const config: Partial<CasewrightConfig> = {
  places: {
    // Patterns to identify Page Object Models
    patterns: [/Page$/, /Component$/, /View$/],
    mappings: {
      LoginPage: 'Login Screen',
    },
  },
  elements: {
    mappings: {
      submitBtn: 'Submit Button',
    },
  },
  actions: {
    // Method name → template. Use {target} for the element, {0}, {1} for arguments.
    mappings: {
      click: 'Tap {target}',
      fill: 'Input {0} into {target}',
    },
  },
  output: {
    dir: './casewright',
    filename: 'documentation.html',
  },
  title: 'Test Documentation',
}

export default config

Getting maximum value from Casewright

Casewright is an opinionated reporter. To bring the maximum possible value and to correctly convert your Playwright solution into test documentation, it expects (he-he 🥸) that you:

  1. Use folders inside your tests folder as global categories, for example, tests/admin, tests/seller, tests/buyer etc.
  2. Use test.describe as test suites, test as, well, tests, and test.step as test steps. Casewright ignores files as it's usually a strictly technical aspect of solution, not a semantical one.
  3. Try to avoid code outside of test.step. Lines outside of steps will still be parsed and added to documentation but it's gonna to feel weird to have steps along with orphaned lines.
  4. Separate semantically important actions from assertions and do not mix them within one custom function. If your POM functions signs in and expects to be signed in at the same time, you are doing something wrong. If some actions or assertions are not that important or are strictly technical, it's okay to hide them in this way.
  5. Thoroughly think about your naming convention and try to remain as declarative as you can.
  6. Use transparently named variable instead of literal for every semantically important value:
// ❌ NO
dashboardPage.searchBar.fill('Test user')
// ✅ YES
const searchedUserName = testData.dashboard.searchedUser.name
dashboardPage.searchBar.fill(searchedUserName)
  1. Remember that Casewright is still a custom reporter, so it can be called conditionally. The most easy way is to introduce an environment variable to control whether you want to re-create documentation:
// playwright.config.ts
import { defineConfig } from '@playwright/test'

const reporters: any[] = [['html']]

if (process.env.DOCS) {
  reporters.push(['casewright'])
}

export default defineConfig({
  reporter: reporters,
})

Features

Automatic Name Conversion

Casewright automatically converts code identifiers to human-readable text:

  • submitButton → "Submit Button"
  • dashboardPage.userProfile → "User Profile on Dashboard Page"
  • page.goto('/') → "Navigate to /"

Entity Types

Documentation recognizes four entity types:

  1. Places: Page Object Models or containers (matched by patterns like /Page$/)
  2. Elements: Locators on places (e.g., buttons, inputs)
  3. Actions: Playwright API calls or custom functions
  4. Variables: Named values passed to actions

Custom Function Documentation

Document custom functions with the @overwrite JSDoc tag:

/**
 * @overwrite Check that cards are sorted in {order} order
 */
async function assertCardSorting(page: Page, order: 'asc' | 'desc') {
  // implementation
}

The {order} placeholder will be replaced with the actual value at runtime.

Ignoring Items

Use the @ignore JSDoc tag to exclude suites, tests, steps, or custom functions from documentation:

/**
 * @ignore
 */
test.describe('Technical setup', () => {
  // this entire suite is hidden from docs
})

/**
 * @ignore
 */
async function internalSetup() {
  // calls to this function won't appear as steps
}

@ignore works on test.describe, test, test.step, and any custom function. When placed on a suite, all tests inside are ignored as well.

Marking Expectations

Use @expectation to mark a custom function as a verification step. Expectation steps are visually highlighted in the output:

/**
 * @overwrite Verify that user {name} is displayed
 * @expectation
 */
async function assertUserDisplayed(page: Page, name: string) {
  // implementation
}

Expectations are also auto-detected for:

  • Any expect() call
  • addDocumentationLine text starting with "check that"

Documentation Line Helper

Use addDocumentationLine to insert custom text steps that don't correspond to any code:

import { addDocumentationLine } from 'casewright'

test('checkout flow', async ({ page }) => {
  await test.step('Complete purchase', async () => {
    addDocumentationLine('User has items in cart from previous test')
    await checkoutPage.submit()
    addDocumentationLine('Check that order confirmation is displayed')
  })
})

Lines starting with "check that" (case-insensitive) are automatically marked as expectations.

Overwriting Step Documentation

Use overwriteDocumentationLines inside a test.step to replace all auto-detected steps with your own list:

import { overwriteDocumentationLines } from 'casewright'

await test.step('Process complex data', async () => {
  overwriteDocumentationLines([
    'Fetch data from external API',
    'Transform response into table format',
    'Check that all rows are valid',
  ])

  // actual implementation — ignored by Casewright
  const data = await api.fetch()
  const rows = transform(data)
  expect(rows.every((r) => r.valid)).toBe(true)
})

Documentation Screenshots

Use addDocumentationScreenshot to capture annotated screenshots that appear in the generated docs:

import { addDocumentationScreenshot } from 'casewright'

await test.step('Review dashboard', async () => {
  await addDocumentationScreenshot(page, 'dashboard-overview', {
    label: 'Dashboard with metrics',
    highlight: [{ locator: page.getByTestId('metrics-panel') }],
    notes: [
      {
        text: 'Key metrics section',
        target: page.getByTestId('metrics-panel'),
        angle: 270, // note above element
      },
    ],
  })
})

Options:

  • highlight — elements to outline (configurable border width/color/style)
  • notes — text annotations with arrows pointing to elements
  • fullPage — capture the full scrollable page
  • label — display text in documentation (defaults to the name)

Interactive HTML Output

Generated documentation includes:

  • Collapsible tree view (suites → tests → steps)
  • Search and filter functionality
  • Status indicators (passed/failed/skipped)
  • Dark/light theme toggle
  • Duration tracking
  • Print-friendly layout

API

Reporter Options

Pass options directly to the reporter:

;[
  'casewright',
  {
    title: 'My Test Documentation',
    output: {
      dir: './custom-dir',
      filename: 'tests.html',
    },
    places: {
      patterns: [/Page$/, /Screen$/],
    },
  },
]

Programmatic Usage

import { generateHtml, createDocModel } from 'casewright'

// Create and populate a doc model
const model = createDocModel()
// ... add suites and tests

// Generate HTML
const html = generateHtml(model, config)

CLI Commands

# Create configuration file
npx casewright init

# Show help
npx casewright help

# Show version
npx casewright --version

License

MIT