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

flowsnap

v0.0.3

Published

Playwright reporter that captures E2E test flows as visual HTML documents with screenshots

Readme

flowsnap

Capture E2E test flows as visual documents.

npm version license CI

flowsnap is a Playwright reporter that turns your E2E tests into visual flow documents. It captures screenshots at each page navigation and connects them with arrows, producing a self-contained HTML report you can open anywhere -- no server required.


What It Does

When your Playwright tests run, flowsnap:

  1. Captures screenshots on every page navigation (or at test end, depending on mode)
  2. Records URL transitions and generates descriptive labels automatically
  3. Outputs a CTRF-compliant JSON report with flow data in test.extra.flow
  4. Generates a self-contained HTML report with an interactive sidebar, flow lanes, screenshot gallery, and search/filter

Installation

npm install flowsnap -D

Requires @playwright/test >= 1.40.0 as a peer dependency.


Quick Start

flowsnap offers two modes depending on how much detail you need.

Mode 1: Reporter Only (Zero Config)

Add flowsnap to your reporter array in playwright.config.ts. No other changes needed.

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

export default defineConfig({
  reporter: [
    ['list'],
    ['flowsnap'],
  ],
});

This mode captures Playwright's built-in end-of-test screenshots. You get one screenshot per test -- useful for a quick visual summary without modifying any test files.

Mode 2: Full Flow (Fixture)

Import test and expect from flowsnap/fixture instead of @playwright/test. This hooks into page navigation events and captures a screenshot at every URL change.

// tests/example.spec.ts

// Replace this:
// import { test, expect } from '@playwright/test';

// With this:
import { test, expect } from 'flowsnap/fixture';

test('user login flow', async ({ page }) => {
  await page.goto('https://example.com');
  await page.click('text=Sign In');
  await page.fill('#email', '[email protected]');
  await page.fill('#password', 'password');
  await page.click('button[type=submit]');
  await expect(page).toHaveURL('/dashboard');
});

Each navigation triggers a screenshot automatically. The final report shows every step connected by arrows, forming a visual flow of the user journey.

You still need the reporter in playwright.config.ts:

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

export default defineConfig({
  reporter: [
    ['list'],
    ['flowsnap'],
  ],
});

Configuration

Pass options as the second element of the reporter tuple:

reporter: [
  ['flowsnap', {
    outputDir: './flow-report',  // Output directory (default: './flow-report')
    generateHtml: true,          // Generate HTML report (default: true)
  }],
],

FlowReporterOptions

| Option | Type | Default | Description | |---|---|---|---| | outputDir | string | './flow-report' | Directory for the JSON report, HTML report, and screenshots | | generateHtml | boolean | true | Whether to auto-generate the HTML report after test run |


Output

After running npx playwright test, the output directory contains:

flow-report/
  ctrf-report.json        # CTRF-compliant test report with flow data
  index.html              # Self-contained HTML report (all screenshots inlined as base64)
  screenshots/            # Raw screenshot files
    test-name-a0-0.png
    test-name-a0-1.png
    ...

The HTML report is fully self-contained -- screenshots are embedded as base64 data URIs. You can share the single index.html file and it works offline.

HTML Report Features

  • Sidebar with project tree, test search, and status filters (pass/fail/skip)
  • Flow lanes showing each test as a horizontal strip of connected screenshots
  • Screenshot gallery modal with keyboard navigation (arrow keys, Escape)
  • Error display for failed tests with stack traces
  • Responsive layout with mobile sidebar toggle

CTRF Extension: extra.flow

flowsnap outputs standard CTRF (Common Test Report Format) JSON. Flow-specific data is stored in the extra.flow namespace on each test, keeping the report fully compatible with other CTRF tools.

{
  "reportFormat": "CTRF",
  "specVersion": "0.0.0",
  "results": {
    "tool": { "name": "playwright" },
    "summary": { "tests": 5, "passed": 4, "failed": 1, "..." : "..." },
    "tests": [
      {
        "name": "user login flow",
        "status": "passed",
        "duration": 3200,
        "extra": {
          "flow": {
            "screenshots": [
              {
                "id": "default-user-login-flow-0",
                "url": "https://example.com/",
                "previousUrl": null,
                "timestamp": 1700000000000,
                "screenshotPath": "screenshots/default-user-login-flow-a0-0.png",
                "label": "Start: /"
              },
              {
                "id": "default-user-login-flow-1",
                "url": "https://example.com/login",
                "previousUrl": "https://example.com/",
                "timestamp": 1700000001000,
                "screenshotPath": "screenshots/default-user-login-flow-a0-1.png",
                "label": "/login navigate"
              }
            ],
            "edges": [
              {
                "from": "default-user-login-flow-0",
                "to": "default-user-login-flow-1",
                "label": "/login navigate"
              }
            ]
          }
        }
      }
    ]
  }
}

Flow Data Types

  • FlowScreenshot -- id, url, previousUrl, timestamp, screenshotPath, label
  • FlowEdge -- from (screenshot id), to (screenshot id), optional label

This structure allows other tools to consume the CTRF report normally while ignoring the extra.flow extension, or to build custom visualizations on top of the flow data.


Retry Handling

flowsnap automatically merges retries. When a test is retried, only the final attempt's screenshots are kept. Previous attempt screenshots are cleaned up from disk to avoid clutter.


Programmatic HTML Generation

You can generate (or regenerate) the HTML report from an existing CTRF JSON file:

import { generateFlowHtml } from 'flowsnap';

await generateFlowHtml('./flow-report/ctrf-report.json', './flow-report/index.html');

Or from the command line by running the generate-html module directly.


Security Considerations

  • Sensitive data in screenshots: Screenshots may capture logged-in user info, API responses, or internal dashboards. Do not publish reports to public repositories or storage without review.
  • Error details: Failed test reports may include stack traces containing connection strings, API keys, or tokens. Always review reports before sharing externally.
  • Exclude output from version control: Add the output directory to .gitignore (e.g., flow-report/) to prevent accidental commits of sensitive screenshots and reports.

License

MIT