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

@reportforge/playwright-pdf

v0.0.1

Published

Enterprise-ready PDF reports for Playwright Test — minimal, detailed, and executive templates with CI/CD integrations

Readme

@reportforge/playwright-pdf

Playwright PDF reporter — generate branded PDF reports from Playwright Test results. Three templates (minimal, detailed, executive) for developers, QA teams, and stakeholders. CI-ready, self-contained, with embedded screenshots and charts.

Drop it into any Playwright project and get a PDF report on every CI run. No changes to your tests.

npm Node License

Docs · Pricing · Support


Report Gallery

Three templates, one reporter. Every PDF is fully offline — fonts, charts, and screenshots are embedded.


Features

  • 3 templatesminimal (developer), detailed (QA team), executive (stakeholders)
  • Detailed reports — KPI dashboard, suite breakdown, failure deep-dive with screenshots, CI/CD environment
  • Embedded Chart.js — pass-rate doughnut + per-suite bar chart, bundled inline (no CDN)
  • Self-contained PDFs — screenshots, fonts, logos all embedded; share or archive with confidence
  • Custom branding — logo, primary/accent colours, watermark, PDF password encryption
  • Dynamic filenames{date}, {branch}, {status} tokens in the output path
  • CI/CD snippets — GitHub Actions, GitLab CI, Bitbucket Pipelines, Jenkins, Azure DevOps
  • Shard merging — combine N Playwright JSON shard reports into one PDF via shardResults; accepts glob patterns or explicit paths
  • Webhook notifications — post pass/fail summaries to Slack, Teams, or Discord on every run; configurable per channel with on: 'always' | 'failure' | 'success'
  • Hybrid licensing — one short key unlocks it; reports keep rendering offline via a cached JWT between refreshes

Quick Start

npm install --save-dev @reportforge/playwright-pdf puppeteer-core
// playwright.config.ts
import { defineConfig } from '@playwright/test';
import { defineReporterConfig } from '@reportforge/playwright-pdf';

export default defineConfig({
  reporter: [
    ['@reportforge/playwright-pdf', defineReporterConfig({
      template: 'detailed',
      outputFile: 'reports/{date}-{branch}-{status}.pdf',
    })],
  ],
  use: { screenshot: 'only-on-failure' },
});

defineReporterConfig is an optional typed identity helper — it gives you IntelliSense and type-checking on the options object without a separate ReporterOptions import. You can also pass a plain object literal if you prefer.

npx playwright test
# → reports/2026-05-01-main-failed.pdf

License required. Start a 7-day free trial at reportforge.org/pricing — card required, no charge until day 8. Paste the resulting RFSU-… key into RF_LICENSE_KEY. Without a valid license the reporter logs a warning and skips PDF generation; your Playwright tests still run normally.


Installation

Requirements

  • Node.js ≥ 18
  • @playwright/test ≥ 1.40 (peer dependency)
  • puppeteer-core ≥ 21 (peer dependency)
  • Chrome or Chromium installed on the machine

Chrome setup

The reporter auto-detects Chrome via PUPPETEER_EXECUTABLE_PATH, then system Chrome, then chrome-finder. Full per-OS instructions: reportforge.org/docs#chrome-setup.

Windows

winget install Google.Chrome
$env:PUPPETEER_EXECUTABLE_PATH = "C:\Program Files\Google\Chrome\Application\chrome.exe"

Linux (Debian / Ubuntu)

wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | \
  sudo gpg --dearmor -o /usr/share/keyrings/google-chrome.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] \
  http://dl.google.com/linux/chrome/deb/ stable main" | \
  sudo tee /etc/apt/sources.list.d/google-chrome.list
sudo apt-get update -qq && sudo apt-get install -y google-chrome-stable
export PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable

Note: Do not use the chromium-browser apt package — it installs as a snap on Ubuntu and Puppeteer cannot drive it.

macOS

brew install --cask google-chrome
export PUPPETEER_EXECUTABLE_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"

Or set the path in playwright.config.ts:

reporter: [['@reportforge/playwright-pdf', {
  puppeteerExecutablePath: '/usr/bin/google-chrome-stable',
}]]

Pricing

| Plan | INR | USD | Includes | |---|---|---|---| | Monthly | ₹999 / month | $12 / month | All three templates · custom branding · PDF encryption · up to 25 active machines · priority email support | | Yearly | ₹8,499 / year | $99 / year | Everything in Monthly · ~29–31% saving vs monthly |

Currency is auto-detected by region; toggle on the pricing page.


Configuration

All options are the second element of the reporter tuple.

| Option | Type | Default | Description | |---|---|---|---| | template | 'minimal' \| 'detailed' \| 'executive' or array | 'minimal' | Template(s) to generate. Pass an array to produce one PDF per template — the template name is appended automatically (e.g. report-detailed.pdf). | | outputFile | string | 'playwright-report/{date}-report.pdf' | Output path (supports tokens) | | reportTitle | string | 'Playwright Test Report' | Title in header and cover | | projectName | string | from package.json | Project name shown in report | | logo | string | — | Path to logo image (PNG / JPG / SVG) | | primaryColor | string | '#CC785C' | Brand colour (hex) | | accentColor | string | '#3F7D58' | Accent colour (hex) | | watermark | string | — | Diagonal watermark text (e.g. 'CONFIDENTIAL') | | pdfPassword | string | — | Password-protect the PDF (requires qpdf) | | licenseKey | string | env RF_LICENSE_KEY | Subscription key (format RFSU-…) | | compressionLevel | 'auto' \| 'none' \| 'balanced' \| 'max' | 'auto' | Screenshot JPEG quality + inline failure cap | | includeScreenshots | boolean | true | Embed screenshots in the PDF. Set to false to omit images — useful for exec-audience reports or reducing file size. | | maxInlineFailures | number | derived from compressionLevel | Cap on inline failures; overflow spills to {basename}-failures.json | | maxFileSizeMb | number | 8 | Soft cap; reporter re-renders with max compression once if exceeded | | serverUrl | string | 'https://reportforge.org' | Licensing server base URL (override only for self-hosting) | | open | boolean | false | Open PDF after generation (local only) | | shardResults | string \| string[] | — | Glob or path array of Playwright JSON shard files to merge into one PDF. | | notify | object | — | Webhook notification channels. See Webhook Notifications. | | historyFile | string | ~/.reportforge/{key}/history.json | Path to history JSON. Relative paths resolved from cwd at startup. | | historySize | number | 10 | Max run entries to keep (integer ≥ 2). | | showTrend | boolean | true | Set to false to disable history write and sparkline entirely. | | puppeteerExecutablePath | string | auto-detect | Path to Chrome / Chromium |

Full reference: reportforge.org/docs#configuration.

Shard Merging

Combine parallel Playwright shards into one PDF without re-running any tests.

Workflow:

  1. Run each shard with --reporter=json to produce a JSON output file.
  2. In a separate step, point shardResults at those files — accepts a glob or an explicit array.
// playwright.config.ts (merge step)
reporter: [
  ['@reportforge/playwright-pdf', {
    shardResults: 'results/shard-*.json',   // glob
    // or: shardResults: ['results/shard-1.json', 'results/shard-2.json'],
    outputFile: 'reports/{date}-report.pdf',
  }],
],

The merge step can run against a dummy test file with zero tests — shardResults takes precedence over live results.

Note: Timed-out tests are counted as failures in shard mode (Playwright JSON stats do not distinguish timedOut from failed).

Webhook Notifications

Post a summary message to Slack, Teams, or Discord after each run.

notify: {
  slack: {
    url: 'https://hooks.slack.com/services/...',
    enabled: true,               // required — defaults to false
    on: 'always',                // 'always' | 'failure' | 'success'  (default: 'always')
  },
  teams: {
    url: 'https://outlook.office.com/webhook/...',
    enabled: true,
    on: 'failure',
  },
  discord: {
    url: 'https://discord.com/api/webhooks/...',
    enabled: true,
  },
},

Each channel is independent. enabled: false (the default) lets you store a URL without activating it — useful for staging configs. Set enabled: true to activate.

The on trigger controls when the message fires:

| Value | Sends when | |---|---| | 'always' | Every run | | 'failure' | stats.failed > 0 or run timed out / interrupted | | 'success' | All tests passed |

The summary includes pass rate, test counts, duration, and the report filename. Notifications require a valid license and fire after PDF generation (or after a PDF generation failure — you still get the ping).

Test History Trending

After each run the reporter appends a summary entry to a local JSON file and renders a pass-rate sparkline + verdict row in the detailed template.

Local dev (zero config) — history is written automatically to ~/.reportforge/{projectKey}/history.json. The sparkline appears once two or more runs have been recorded.

CI with ephemeral runners — set historyFile to a project-relative path and cache it between runs:

// playwright.config.ts
reporter: [['@reportforge/playwright-pdf', {
  template: 'detailed',
  historyFile: '.reportforge/history.json',
}]]
# .github/workflows/test.yml
- uses: actions/cache@v4
  with:
    path: .reportforge/history.json
    key: reportforge-history-${{ github.ref }}
    # Omit restore-keys — cross-branch fallback causes misleading sparklines on PRs

Monorepo — each package needs a distinct historyFile (e.g. .reportforge/api-history.json, .reportforge/web-history.json) so runs do not overwrite each other.

Filename tokens

| Token | Replaced with | Example | |---|---|---| | {date} | YYYY-MM-DD (UTC) | 2026-04-21 | | {branch} | Git branch, sanitised | feature-auth | | {status} | Overall verdict | passed / failed / timedout / interrupted |


Templates

minimal — Developer-focused

Clean layout, KPI numbers, hierarchical test table, failure details with stack traces and embedded screenshots. Fast to generate. Good for local development and PR checks.

detailed — QA Team

Everything in minimal, plus Chart.js pass-rate + suite-results charts, a numbered defect log, a requirements traceability matrix derived from @TAG annotations, and the full CI/CD environment table.

executive — Stakeholder presentations

Full-page cover with verdict + KPI strip, followed by a compact dashboard with charts and a failures summary (titles only — no raw stack traces). Best for sprint reports and management dashboards.

Generating multiple templates in one run

Pass an array to template to generate one PDF per template from a single test run. The template name is appended to the output filename automatically:

// playwright.config.ts
reporter: [
  ['@reportforge/playwright-pdf', {
    template: ['detailed', 'executive'],
    outputFile: 'reports/{date}-report.pdf',
    licenseKey: process.env.RF_LICENSE_KEY,
  }],
]
# → reports/2026-04-28-report-detailed.pdf
# → reports/2026-04-28-report-executive.pdf

One license check, one data-collection pass — faster than multiple reporter instances. Duplicate entries are silently deduplicated.


CI/CD Integration

Full workflows for all four CI providers: reportforge.org/docs#ci-cd.

GitHub Actions

- name: Run Playwright tests
  run: npx playwright test
  env:
    RF_LICENSE_KEY: ${{ secrets.RF_LICENSE_KEY }}
    PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome-stable

- name: Upload PDF report
  if: always()
  uses: actions/upload-artifact@v4
  with:
    name: playwright-pdf-report
    path: reports/*.pdf

GitHub Actions — Sharded runs

Run shards in parallel with --reporter=json, then merge all JSON files into one PDF:

jobs:
  test:
    strategy:
      matrix:
        shard: [1, 2, 3, 4]
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npm ci
      - run: npx playwright test --shard=${{ matrix.shard }}/4 --reporter=json
        env:
          PLAYWRIGHT_JSON_OUTPUT_NAME: results/shard-${{ matrix.shard }}.json
      - uses: actions/upload-artifact@v4
        with:
          name: shard-json-${{ matrix.shard }}
          path: results/shard-${{ matrix.shard }}.json

  merge-pdf:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npm ci
      - uses: actions/download-artifact@v4
        with: { pattern: shard-json-*, merge-multiple: true, path: results }
      - run: npx playwright test --reporter=@reportforge/playwright-pdf tests/dummy.spec.ts
        env:
          RF_LICENSE_KEY: ${{ secrets.RF_LICENSE_KEY }}
          PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome-stable
          SHARD_RESULTS_GLOB: 'results/shard-*.json'
      - uses: actions/upload-artifact@v4
        with: { name: playwright-pdf-report, path: reports/*.pdf }

In playwright.config.ts set shardResults: process.env.SHARD_RESULTS_GLOB. tests/dummy.spec.ts can be a single skipped test — live results are ignored when shardResults is set.

GitLab CI

playwright-tests:
  image: mcr.microsoft.com/playwright:v1.49.0-jammy
  script:
    - npm ci && npx playwright test
  artifacts:
    paths: [reports/*.pdf]
    when: always
    expire_in: 30 days

Bitbucket Pipelines

image: mcr.microsoft.com/playwright:v1.49.0-jammy
pipelines:
  default:
    - step:
        name: Playwright Tests + PDF Report
        caches: [node]
        script:
          - npm ci
          - npx playwright test
        artifacts:
          - playwright-report/*.pdf

Set RF_LICENSE_KEY in Repository Settings → Repository variables.

Jenkins

stage('Playwright Tests') {
  withCredentials([string(credentialsId: 'rf-license', variable: 'RF_LICENSE_KEY')]) {
    sh 'npx playwright test'
  }
  archiveArtifacts artifacts: 'reports/*.pdf', allowEmptyArchive: true
}

Azure DevOps

- script: npx playwright test
  env: { RF_LICENSE_KEY: $(RF_LICENSE_KEY) }
- task: PublishPipelineArtifact@1
  inputs:
    targetPath: reports
    artifact: playwright-pdf-report

Licensing

ReportForge ships a hybrid offline-first model:

  1. Paste your RFSU-… key into the config once (or set RF_LICENSE_KEY).
  2. On first run the reporter activates against the license server, receives a short-lived Ed25519-signed JWT, and caches it at ~/.reportforge/license.json.
  3. Every subsequent run is fully offline — the cached JWT is verified locally against a public key bundled into the npm package. No network call.
  4. When the cache has less than 24 hours left, the reporter refreshes it in the background.
  5. Each subscription allows up to 25 active machines in any rolling 30-day window. Machines that haven't run in 30 days are pruned automatically.

Cancel the subscription and the reporter keeps working until the end of the current billing period, then stops generating PDFs until you restart. A license issue never aborts your test run — the reporter logs a warning and skips PDF generation; your Playwright tests still pass.

export RF_LICENSE_KEY=RFSU-XXXX-XXXX-XXXX-XXXX
npx playwright test

Full lifecycle + offline failure modes: reportforge.org/docs#license.


Requirements Traceability

The detailed template generates a requirements matrix from test tags. Tag tests to link them to requirements:

test('@REQ-101 user can login', async ({ page }) => { /* ... */ });
test.describe('@FEAT-payment', () => { /* ... */ });

The matrix rolls tests up per tag with pass count, fail count, and coverage percentage.


Troubleshooting

Set RF_DEBUG=1 to log the full activation flow and error stack traces:

RF_DEBUG=1 npx playwright test 2>&1 | grep '\[reportforge\]'

Common issues:

  • Chrome/Chromium not found → install Google Chrome Stable; don't use the Ubuntu chromium-browser snap.
  • Charts blank → ensure npm run bundle-chartjs ran at build; the reporter waits up to 30s for window.__chartsReady.
  • pdfPassword ignored → requires qpdf on PATH (apt install qpdf / brew install qpdf / choco install qpdf).
  • No PDF generated → verify RF_LICENSE_KEY is set and your subscription is active. RF_DEBUG=1 will show the activation result; missing key, expired subscription, network failure, or no JWT cache all skip PDF generation.

Full guide: reportforge.org/docs#troubleshooting.


Documentation

Full documentation at reportforge.org/docs:


Contributing

Questions and bug reports: email [email protected].

License

MIT — see LICENSE.