@reportforge/playwright-pdf 0.13.0 → 0.13.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,11 +3,19 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
- ## [0.6.3] 2026-06-27
6
+ ## [0.13.1] - 2026-07-03
7
+
8
+ ### Changed
9
+
10
+ - **Metadata refresh, no functional change**: package description rewritten (dropped "Enterprise-ready" framing), `homepage` and `bugs` fields added, keywords expanded (`playwright-test`, `e2e`, `test-automation`, `qa`). README and this changelog had every em dash rewritten for plain punctuation; wording is unchanged.
11
+
12
+ ---
13
+
14
+ ## [0.6.3] - 2026-06-27
7
15
 
8
16
  ### Fixed
9
17
 
10
- - **Demo command now resolves under `npx`** the documented `npx @reportforge/playwright-pdf reportforge-demo` could never run: with two package bins and neither matching the package's unscoped name (`playwright-pdf`), npx aborted with `could not determine executable to run`. The package now ships a single dispatcher bin named `playwright-pdf`, so `npx @reportforge/playwright-pdf <command>` resolves correctly.
18
+ - **Demo command now resolves under `npx`**: the documented `npx @reportforge/playwright-pdf reportforge-demo` could never run: with two package bins and neither matching the package's unscoped name (`playwright-pdf`), npx aborted with `could not determine executable to run`. The package now ships a single dispatcher bin named `playwright-pdf`, so `npx @reportforge/playwright-pdf <command>` resolves correctly.
11
19
 
12
20
  ### Changed
13
21
 
@@ -18,37 +26,37 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
18
26
 
19
27
  ---
20
28
 
21
- ## [0.6.2] 2026-06-23
29
+ ## [0.6.2] - 2026-06-23
22
30
 
23
31
  ### Fixed
24
32
 
25
- - **Watermark no longer prints over content** the optional watermark sits behind charts, screenshots, and tables instead of across them (z-index + a body stacking context).
26
- - **Absent git metadata is hidden** local runs with no branch/commit no longer render "unknown · unknown" or a stray separator; the environment table shows "n/a".
27
- - **Failure errors render once** the message and stack are no longer printed twice; the formatted stack is shown when available (it already begins with the message).
28
- - **Executive analysis one-liner ordering** the one-line summary sits below the header instead of orphaning at the top of page 2.
29
- - **Retry attempts are 1-based** the retry history reads `#1`, `#2`… instead of a zero-based `#0`.
30
- - **Zero-count suite pill hidden** the "passed" pill no longer renders when its count is 0.
31
- - **Suite-bar labels stop clipping** long suite / describe labels are truncated and the axis gutter widened.
33
+ - **Watermark no longer prints over content**: the optional watermark sits behind charts, screenshots, and tables instead of across them (z-index + a body stacking context).
34
+ - **Absent git metadata is hidden**: local runs with no branch/commit no longer render "unknown · unknown" or a stray separator; the environment table shows "n/a".
35
+ - **Failure errors render once**: the message and stack are no longer printed twice; the formatted stack is shown when available (it already begins with the message).
36
+ - **Executive analysis one-liner ordering**: the one-line summary sits below the header instead of orphaning at the top of page 2.
37
+ - **Retry attempts are 1-based**: the retry history reads `#1`, `#2`… instead of a zero-based `#0`.
38
+ - **Zero-count suite pill hidden**: the "passed" pill no longer renders when its count is 0.
39
+ - **Suite-bar labels stop clipping**: long suite / describe labels are truncated and the axis gutter widened.
32
40
  - **Consistent footer copy** across all three templates.
33
41
 
34
42
  ---
35
43
 
36
- ## [0.6.1] 2026-06-22
44
+ ## [0.6.1] - 2026-06-22
37
45
 
38
46
  ### Documentation
39
47
 
40
- - **Expanded the Report Sections reference** per-section descriptions for all 13 block toggles, the 5 display modifiers, a per-template defaults matrix, and the dependency rules (`trend` needs `charts`, data-gated sections, render-layer only) in both the README and the docs site.
48
+ - **Expanded the Report Sections reference**: per-section descriptions for all 13 block toggles, the 5 display modifiers, a per-template defaults matrix, and the dependency rules (`trend` needs `charts`, data-gated sections, render-layer only) in both the README and the docs site.
41
49
  - Fixed the README documentation links to point at the real `/docs/<page>` routes instead of non-existent `/docs#<anchor>` anchors.
42
50
 
43
- _No runtime changes `@reportforge/playwright-pdf@0.6.1` is identical in behaviour to `0.6.0`._
51
+ _No runtime changes: `@reportforge/playwright-pdf@0.6.1` is identical in behaviour to `0.6.0`._
44
52
 
45
53
  ---
46
54
 
47
- ## [0.6.0] 2026-06-22
55
+ ## [0.6.0] - 2026-06-22
48
56
 
49
57
  ### Added
50
58
 
51
- - **Configurable report sections** a new `sections` option adds or removes any section in any built-in template (`minimal` / `detailed` / `executive`) straight from `playwright.config`. Flat keys set a baseline for every chosen template; per-template keys override per template. Covers every block (cover page, charts, trend, requirements traceability, CI/environment, suite breakdown, failures, failure analysis, slow tests, defect log, release gate) plus display modifiers (pass-rate, full environment table, retries, failure and stack-trace depth). Unknown keys are rejected with a clear configuration error. Reports render identically to before when the option is omitted.
59
+ - **Configurable report sections**: a new `sections` option adds or removes any section in any built-in template (`minimal` / `detailed` / `executive`) straight from `playwright.config`. Flat keys set a baseline for every chosen template; per-template keys override per template. Covers every block (cover page, charts, trend, requirements traceability, CI/environment, suite breakdown, failures, failure analysis, slow tests, defect log, release gate) plus display modifiers (pass-rate, full environment table, retries, failure and stack-trace depth). Unknown keys are rejected with a clear configuration error. Reports render identically to before when the option is omitted.
52
60
 
53
61
  ### Changed
54
62
 
@@ -56,78 +64,78 @@ _No runtime changes — `@reportforge/playwright-pdf@0.6.1` is identical in beha
56
64
 
57
65
  ---
58
66
 
59
- ## [0.5.1] 2026-06-19
67
+ ## [0.5.1] - 2026-06-19
60
68
 
61
69
  ### Security
62
70
 
63
- - **Chart labels escaped for inline-script safety** a suite / describe / file title containing `</script>` can no longer break out of the inline Chart.js data block in the rendered report (relevant when the reporter runs over untrusted test code, e.g. external-contributor CI).
71
+ - **Chart labels escaped for inline-script safety**: a suite / describe / file title containing `</script>` can no longer break out of the inline Chart.js data block in the rendered report (relevant when the reporter runs over untrusted test code, e.g. external-contributor CI).
64
72
 
65
73
  ### Changed
66
74
 
67
- - **Sharper failure-analysis classification** high-precision deterministic rules now label the error shapes the offline model struggles with: timed-out web-first assertions (`toHaveClass`/`toHaveText`/… with the element resolved) as **assertions**, connection/DNS/SSL errors as **network**, aborted/redirected/interrupted navigations as **navigation**, and resolved-to-0 / strict-mode locators as **locator-not-found**. Rules match the error header only, so call-log context and asserted values no longer cause mislabels (a navigation-wait timeout stays a timeout, a refused `page.goto` is network).
75
+ - **Sharper failure-analysis classification**: high-precision deterministic rules now label the error shapes the offline model struggles with: timed-out web-first assertions (`toHaveClass`/`toHaveText`/… with the element resolved) as **assertions**, connection/DNS/SSL errors as **network**, aborted/redirected/interrupted navigations as **navigation**, and resolved-to-0 / strict-mode locators as **locator-not-found**. Rules match the error header only, so call-log context and asserted values no longer cause mislabels (a navigation-wait timeout stays a timeout, a refused `page.goto` is network).
68
76
 
69
77
  ---
70
78
 
71
- ## [0.5.0] 2026-06-19
79
+ ## [0.5.0] - 2026-06-19
72
80
 
73
81
  ### Added
74
82
 
75
- - **Timed-out tests are first-class** surfaced as their own KPI card, pass-rate doughnut slice, and Suite Results bar segment instead of being folded into "Failed".
76
- - **Release gate on every template** the ship/hold verdict banner now appears in `minimal` and `detailed`, not just `executive`.
77
- - **Severity-ranked failures** failure cards are colour-coded and ordered critical-first (also drives defect-log numbering and sidecar-overflow priority).
78
- - **Describe-block Suite Results** a single-file run breaks down by describe block instead of rendering one bar.
79
- - **Threshold-coloured requirements coverage bars** red `<50%`, amber `<80%`, green `≥80%`.
83
+ - **Timed-out tests are first-class**: surfaced as their own KPI card, pass-rate doughnut slice, and Suite Results bar segment instead of being folded into "Failed".
84
+ - **Release gate on every template**: the ship/hold verdict banner now appears in `minimal` and `detailed`, not just `executive`.
85
+ - **Severity-ranked failures**: failure cards are colour-coded and ordered critical-first (also drives defect-log numbering and sidecar-overflow priority).
86
+ - **Describe-block Suite Results**: a single-file run breaks down by describe block instead of rendering one bar.
87
+ - **Threshold-coloured requirements coverage bars**: red `<50%`, amber `<80%`, green `≥80%`.
80
88
 
81
89
  ### Changed
82
90
 
83
- - **Compact page flow** large sections flow and break between rows instead of each starting on a fresh page; a typical `detailed` run drops ~2 pages.
91
+ - **Compact page flow**: large sections flow and break between rows instead of each starting on a fresh page; a typical `detailed` run drops ~2 pages.
84
92
  - The pass-rate verdict renders "TIMED OUT" instead of "TIMEDOUT".
85
93
 
86
94
  ### Fixed
87
95
 
88
- - **Pass rate could exceed 100%** on runs with flaky tests a passed-on-retry test was double-counted in both `passed` and `flaky`. It is now counted as flaky only, so the rate is correct and the KPI cards reconcile to the total.
96
+ - **Pass rate could exceed 100%** on runs with flaky tests: a passed-on-retry test was double-counted in both `passed` and `flaky`. It is now counted as flaky only, so the rate is correct and the KPI cards reconcile to the total.
89
97
  - The pass-rate doughnut centre now matches the KPI strip (single source of truth) rather than computing a second, divergent figure.
90
98
  - Timed-out status badges render with the correct styling, and timed-out tests are recovered in sharded (`shardResults`) runs instead of being reported as failures.
91
99
 
92
100
  ---
93
101
 
94
- ## [0.4.0] 2026-06-12
102
+ ## [0.4.0] - 2026-06-12
95
103
 
96
104
  ### Added
97
105
 
98
- - **Failure analysis** every failed test is classified into one of seven root-cause categories (assertion, timeout, selector/locator, network, and more) and failures that share a cause are grouped into clusters, rendered as a ranked breakdown in the `detailed` template. Classification runs fully offline no network call, no AI service. The classifier model refreshes from the licensing server in the background (offline-tolerant; the bundled model is always the floor), with optional privacy-preserving local feedback collection. See `docs/advanced/failure-analysis`.
106
+ - **Failure analysis**: every failed test is classified into one of seven root-cause categories (assertion, timeout, selector/locator, network, and more) and failures that share a cause are grouped into clusters, rendered as a ranked breakdown in the `detailed` template. Classification runs fully offline: no network call, no AI service. The classifier model refreshes from the licensing server in the background (offline-tolerant; the bundled model is always the floor), with optional privacy-preserving local feedback collection. See `docs/advanced/failure-analysis`.
99
107
 
100
108
  ---
101
109
 
102
- ## [0.3.1] 2026-06-09
110
+ ## [0.3.1] - 2026-06-09
103
111
 
104
112
  ### Security
105
113
 
106
- - **License gate hardened in `PdfGenerator`** JWT verification is now enforced at the PDF generator boundary, not only in the reporter entry point. Real licenses require a valid Ed25519-signed JWT (verified against the bundled public key) with a non-expired `exp` claim checked directly from the JWT payload.
107
- - **`DEMO_LICENSE_INFO` no longer exported** the demo fixture constant is now module-private; not accessible via deep import from the published package.
108
- - **Compile-time demo flag** the demo CLI bypass (`reportforge-demo`) is gated on a tsup `define` constant (`__RF_IS_DEMO__`) baked into `dist/demo/cli.js` at build time. The main library (`dist/pdf/PdfGenerator.js`) has the flag set to `false` and cannot be bypassed by constructing a `LicenseInfo` with `source: 'demo'` at runtime.
114
+ - **License gate hardened in `PdfGenerator`**: JWT verification is now enforced at the PDF generator boundary, not only in the reporter entry point. Real licenses require a valid Ed25519-signed JWT (verified against the bundled public key) with a non-expired `exp` claim checked directly from the JWT payload.
115
+ - **`DEMO_LICENSE_INFO` no longer exported**: the demo fixture constant is now module-private; not accessible via deep import from the published package.
116
+ - **Compile-time demo flag**: the demo CLI bypass (`reportforge-demo`) is gated on a tsup `define` constant (`__RF_IS_DEMO__`) baked into `dist/demo/cli.js` at build time. The main library (`dist/pdf/PdfGenerator.js`) has the flag set to `false` and cannot be bypassed by constructing a `LicenseInfo` with `source: 'demo'` at runtime.
109
117
 
110
118
  ---
111
119
 
112
- ## [0.3.0] 2026-06-08
120
+ ## [0.3.0] - 2026-06-08
113
121
 
114
122
  ### Added
115
123
 
116
- - **`reportforge-demo` instant demo report** run `npx @reportforge/playwright-pdf reportforge-demo` to generate a realistic sample PDF in under 60 seconds with no license key required. Supports `--template=minimal|detailed|executive` and `--output=<path>`. Lets evaluators see the exact report ReportForge produces before subscribing.
117
- - **`reportforge-demo` bin wired in `package.json`** available immediately after `npm install`; no global install required via `npx`.
124
+ - **`reportforge-demo` instant demo report**: run `npx @reportforge/playwright-pdf reportforge-demo` to generate a realistic sample PDF in under 60 seconds with no license key required. Supports `--template=minimal|detailed|executive` and `--output=<path>`. Lets evaluators see the exact report ReportForge produces before subscribing.
125
+ - **`reportforge-demo` bin wired in `package.json`**: available immediately after `npm install`; no global install required via `npx`.
118
126
 
119
127
  ### Changed
120
128
 
121
- - `src/collector/stats-utils.ts` (new) `statsFromTests` and `aggregateStats` extracted from `SuiteWalker` and `ShardMerger` to a shared utility; eliminates 3-way duplication.
129
+ - `src/collector/stats-utils.ts` (new): `statsFromTests` and `aggregateStats` extracted from `SuiteWalker` and `ShardMerger` to a shared utility; eliminates 3-way duplication.
122
130
  - GitHub Actions pinned to commit SHAs (supply-chain hardening).
123
131
 
124
132
  ---
125
133
 
126
- ## [0.0.1] 2026-05-26
134
+ ## [0.0.1] - 2026-05-26
127
135
 
128
136
  ### Changed
129
137
 
130
- - **Renamed npm package** from `pdf-report-forge` to `@reportforge/playwright-pdf` moved to the `@reportforge` npm org scope to make room for `@reportforge/cypress` and future framework adapters. Update your project:
138
+ - **Renamed npm package** from `pdf-report-forge` to `@reportforge/playwright-pdf`; moved to the `@reportforge` npm org scope to make room for `@reportforge/cypress` and future framework adapters. Update your project:
131
139
  - `npm install @reportforge/playwright-pdf puppeteer-core`
132
140
  - `reporter: [['@reportforge/playwright-pdf', { /* opts */ }]]`
133
141
  - `import { defineReporterConfig } from '@reportforge/playwright-pdf'`
@@ -136,7 +144,7 @@ _No runtime changes — `@reportforge/playwright-pdf@0.6.1` is identical in beha
136
144
 
137
145
  > **History note:** Entries below (`[1.4.3]` and earlier) document releases published under the previous package name `pdf-report-forge`. Feature set is identical at `[0.0.1]`.
138
146
 
139
- ## [1.4.3] 2026-05-14
147
+ ## [1.4.3] - 2026-05-14
140
148
 
141
149
  ### Fixed
142
150
 
@@ -145,16 +153,16 @@ _No runtime changes — `@reportforge/playwright-pdf@0.6.1` is identical in beha
145
153
 
146
154
  ### Changed
147
155
 
148
- - **`LicenseClient` internals refactored** `resolve()` decomposed into `_validateKey`, `_readCache`, and `_offlineFallback` helpers for clarity; no behaviour change.
149
- - **`PdfReporter.onEnd()` refactored** extracted `_collectData`, `_appendTrend`, and `_buildReportData` methods; history write failures now logged as warnings instead of propagating.
150
- - **One-time KV migration cron removed** `GET /api/cron/migrate-key-ttls` has completed its run; the route and cron entry are deleted. KV migration deadline dates updated to absolute dates in code comments.
151
- - **Docs and project layout** build scripts relocated to `scripts/build/`, internal docs to `docs/internal/`, user docs to `docs/user/`. Server setup helper at `scripts/setup-server.ts`.
156
+ - **`LicenseClient` internals refactored**: `resolve()` decomposed into `_validateKey`, `_readCache`, and `_offlineFallback` helpers for clarity; no behaviour change.
157
+ - **`PdfReporter.onEnd()` refactored**: extracted `_collectData`, `_appendTrend`, and `_buildReportData` methods; history write failures now logged as warnings instead of propagating.
158
+ - **One-time KV migration cron removed**: `GET /api/cron/migrate-key-ttls` has completed its run; the route and cron entry are deleted. KV migration deadline dates updated to absolute dates in code comments.
159
+ - **Docs and project layout**: build scripts relocated to `scripts/build/`, internal docs to `docs/internal/`, user docs to `docs/user/`. Server setup helper at `scripts/setup-server.ts`.
152
160
 
153
- ## [1.4.2] 2026-05-13
161
+ ## [1.4.2] - 2026-05-13
154
162
 
155
163
  ### Changed
156
164
 
157
- - **Detailed template trend chart redesign.** Replaced the two disconnected, unlabelled sparklines (pass-rate + duration) with a single, properly designed trend card:
165
+ - **Detailed template: trend chart redesign.** Replaced the two disconnected, unlabelled sparklines (pass-rate + duration) with a single, properly designed trend card:
158
166
  - Smart y-axis range: pads only around actual data instead of a fixed 0–100 axis, so a 96% pass-rate run no longer renders as a flat line at the top of a near-empty canvas.
159
167
  - Visible x-axis (formatted date labels) and y-axis (% gridlines with tick values).
160
168
  - Data points colored by verdict (green = passed, orange = partial, red = failed).
@@ -162,20 +170,20 @@ _No runtime changes — `@reportforge/playwright-pdf@0.6.1` is identical in beha
162
170
  - Gradient fill under the line.
163
171
  - Run history table below the chart (date · colored pass-rate · test count · duration) replacing the meaningless colored-dot row.
164
172
  - Delta badge ("↑ 2% vs previous run") in the card header.
165
- - **`ChartData.trend.entries` extended** `timestamp` (unix ms) and `total` are now forwarded alongside `runId`, `passRate`, `duration`, and `verdict`, enabling the chart to display real dates and test counts without parsing the runId string.
173
+ - **`ChartData.trend.entries` extended**: `timestamp` (unix ms) and `total` are now forwarded alongside `runId`, `passRate`, `duration`, and `verdict`, enabling the chart to display real dates and test counts without parsing the runId string.
166
174
 
167
- ## [1.4.1] 2026-05-13
175
+ ## [1.4.1] - 2026-05-13
168
176
 
169
177
  ### Changed
170
178
 
171
- - **Docs: corrected USD pricing** `$19/month` → `$12/month` and `$149/year` → `$99/year` in README and CHANGELOG. No code change.
179
+ - **Docs: corrected USD pricing** (`$19/month` → `$12/month` and `$149/year` → `$99/year`) in README and CHANGELOG. No code change.
172
180
  - **Docs: added CHANGELOG entry for v1.3.0** (test history trending) which was shipped but not recorded.
173
181
 
174
- ## [1.4.0] 2026-05-10
182
+ ## [1.4.0] - 2026-05-10
175
183
 
176
184
  ### Changed
177
185
 
178
- - **Dev machine fingerprint migration required.** The fingerprint for developer machines now uses a stable UUID persisted at `~/.reportforge/device.json` instead of the previous hostname + MAC address approach. This eliminates phantom seat consumption when running on VPN, Docker, or WSL2 (where MAC changes per session). **On upgrade, each dev machine will register as a new seat on first run.** The old seat will age out naturally within 30 days. Delete `~/.reportforge/device.json` to release the seat immediately if needed.
186
+ - **Dev machine fingerprint: migration required.** The fingerprint for developer machines now uses a stable UUID persisted at `~/.reportforge/device.json` instead of the previous hostname + MAC address approach. This eliminates phantom seat consumption when running on VPN, Docker, or WSL2 (where MAC changes per session). **On upgrade, each dev machine will register as a new seat on first run.** The old seat will age out naturally within 30 days. Delete `~/.reportforge/device.json` to release the seat immediately if needed.
179
187
 
180
188
  - **Atomic machine seat management.** Machine slot registration is now enforced by a Lua script executed atomically in Redis, closing a race condition where two concurrent CI activations could both bypass the 25-seat cap or silently lose each other's seat entry.
181
189
 
@@ -183,14 +191,14 @@ _No runtime changes — `@reportforge/playwright-pdf@0.6.1` is identical in beha
183
191
 
184
192
  ### Fixed
185
193
 
186
- - **Refund access revocation late webhook bypass.** A delayed `subscription.pending` or `subscription.halted` Razorpay webhook arriving after a refund could re-activate the license key index and overwrite the subscription status, allowing a refunded customer to re-activate. The webhook handlers now guard against overwriting refund status.
194
+ - **Refund access revocation: late webhook bypass.** A delayed `subscription.pending` or `subscription.halted` Razorpay webhook arriving after a refund could re-activate the license key index and overwrite the subscription status, allowing a refunded customer to re-activate. The webhook handlers now guard against overwriting refund status.
187
195
 
188
- - **Refund key expiry transient KV failure.** A transient KV read failure during Phase B of the refund flow could leave the license key permanently active despite a completed Razorpay refund. The TTL is now set unconditionally on refund success.
196
+ - **Refund key expiry: transient KV failure.** A transient KV read failure during Phase B of the refund flow could leave the license key permanently active despite a completed Razorpay refund. The TTL is now set unconditionally on refund success.
189
197
 
190
- ## [1.3.0] 2026-05-09
198
+ ## [1.3.0] - 2026-05-09
191
199
 
192
200
  ### Added
193
- - **Test history trending** the `detailed` template now renders a pass-rate sparkline and verdict row from a local run history file. Configure with `historyFile` (default `~/.reportforge/{key}/history.json`), `historySize` (default `10` entries), and `showTrend` (default `true`). In CI with ephemeral runners, set `historyFile` to a project-relative path and cache it between runs.
201
+ - **Test history trending**: the `detailed` template now renders a pass-rate sparkline and verdict row from a local run history file. Configure with `historyFile` (default `~/.reportforge/{key}/history.json`), `historySize` (default `10` entries), and `showTrend` (default `true`). In CI with ephemeral runners, set `historyFile` to a project-relative path and cache it between runs.
194
202
  ```ts
195
203
  reporter: [['pdf-report-forge', {
196
204
  template: 'detailed',
@@ -198,12 +206,12 @@ _No runtime changes — `@reportforge/playwright-pdf@0.6.1` is identical in beha
198
206
  historySize: 10,
199
207
  }]]
200
208
  ```
201
- The history file is local it is never sent to the licensing server.
209
+ The history file is local; it is never sent to the licensing server.
202
210
 
203
- ## [1.2.16] 2026-05-02
211
+ ## [1.2.16] - 2026-05-02
204
212
 
205
213
  ### Added
206
- - **Webhook notifications** post pass/fail summaries to Slack, Teams, or Discord after each run.
214
+ - **Webhook notifications**: post pass/fail summaries to Slack, Teams, or Discord after each run.
207
215
  Configure per channel with `url`, `enabled: true`, and `on: 'always' | 'failure' | 'success'`.
208
216
  ```ts
209
217
  notify: {
@@ -212,122 +220,122 @@ _No runtime changes — `@reportforge/playwright-pdf@0.6.1` is identical in beha
212
220
  ```
213
221
  Notifications fire after PDF generation (even if PDF fails). Requires a valid license.
214
222
 
215
- ## [1.2.15] 2026-05-01
223
+ ## [1.2.15] - 2026-05-01
216
224
 
217
225
  ### Added
218
- - **Shard merging** configure `shardResults` in the reporter options with paths or glob patterns
226
+ - **Shard merging**: configure `shardResults` in the reporter options with paths or glob patterns
219
227
  pointing at Playwright JSON shard files to produce a single merged PDF covering all shards.
220
228
  ```ts
221
229
  // playwright.config.ts
222
230
  reporter: [['pdf-report-forge', { shardResults: 'results/shard-*.json' }]]
223
231
  ```
224
232
 
225
- ## [1.2.14] 2026-05-01
233
+ ## [1.2.14] - 2026-05-01
226
234
 
227
235
  ### Added
228
- - **`logger.debug()`** new debug method on the internal logger, gated on `RF_DEBUG=1`. Logs license cache-hits, network responses, and POST requests with non-sensitive metadata (sha256 fingerprint hashes, expiry timestamps, machine counts). No license key values are logged.
229
- - **Trial countdown badge** subscription dashboard now shows a colour-coded days-left badge during trial periods (`text-red-600` ≤1d, `text-orange-500` ≤3d, `text-terracotta-600` otherwise).
236
+ - **`logger.debug()`**: new debug method on the internal logger, gated on `RF_DEBUG=1`. Logs license cache-hits, network responses, and POST requests with non-sensitive metadata (sha256 fingerprint hashes, expiry timestamps, machine counts). No license key values are logged.
237
+ - **Trial countdown badge**: subscription dashboard now shows a colour-coded days-left badge during trial periods (`text-red-600` ≤1d, `text-orange-500` ≤3d, `text-terracotta-600` otherwise).
230
238
 
231
239
  ### Fixed
232
- - **`open: true` error surfacing** `openPdf()` now checks file existence before spawning the OS viewer and emits a `logger.warn` if the PDF is not found. Spawn errors on Linux/macOS (e.g. `xdg-open` not installed) are also surfaced via `logger.warn`.
240
+ - **`open: true` error surfacing**: `openPdf()` now checks file existence before spawning the OS viewer and emits a `logger.warn` if the PDF is not found. Spawn errors on Linux/macOS (e.g. `xdg-open` not installed) are also surfaced via `logger.warn`.
233
241
 
234
- ## [1.2.13] 2026-05-01
242
+ ## [1.2.13] - 2026-05-01
235
243
 
236
244
  ### Changed
237
- - **README** added `defineReporterConfig` to Quick Start example; prominent badge CTA for the free trial; license note converted to blockquote.
238
- - **CHANGELOG** backfilled entries for v1.2.4 – v1.2.12.
245
+ - **README**: added `defineReporterConfig` to Quick Start example; prominent badge CTA for the free trial; license note converted to blockquote.
246
+ - **CHANGELOG**: backfilled entries for v1.2.4 – v1.2.12.
239
247
 
240
- ## [1.2.12] 2026-05-01
248
+ ## [1.2.12] - 2026-05-01
241
249
 
242
250
  ### Fixed
243
- - **Stable machine fingerprint across VPN / Docker / WSL** `os.networkInterfaces()` enumeration order is not stable across network-state changes on Windows. The MAC selection now sorts interface names and prefers physical adapters (Ethernet, Wi-Fi) over virtual ones (vethernet, Docker, WSL, VPN tap). Same physical machine always produces the same fingerprint hash regardless of which virtual adapters are active.
251
+ - **Stable machine fingerprint across VPN / Docker / WSL**: `os.networkInterfaces()` enumeration order is not stable across network-state changes on Windows. The MAC selection now sorts interface names and prefers physical adapters (Ethernet, Wi-Fi) over virtual ones (vethernet, Docker, WSL, VPN tap). Same physical machine always produces the same fingerprint hash regardless of which virtual adapters are active.
244
252
 
245
- ## [1.2.11] 2026-05-01
253
+ ## [1.2.11] - 2026-05-01
246
254
 
247
255
  ### Added
248
- - **`defineReporterConfig` helper** typed identity function exported from `pdf-report-forge`. Wrap your reporter options object with it in `playwright.config.ts` to get full IntelliSense and type checking without a separate import of `ReporterOptions`.
256
+ - **`defineReporterConfig` helper**: typed identity function exported from `pdf-report-forge`. Wrap your reporter options object with it in `playwright.config.ts` to get full IntelliSense and type checking without a separate import of `ReporterOptions`.
249
257
 
250
258
  ### Fixed
251
- - **Server: silent email failures surfaced** Resend SDK v3 changed from throwing to returning `{ data, error }`. All four send paths now check the error field and throw, so failures appear in logs and trigger Razorpay webhook retries.
252
- - **Server: Razorpay customer-fetch errors now logged** `resolveCustomerEmail` was catching all errors silently. Errors now emit a `webhook.customer_fetch_failed` log entry with the customer ID and error message.
259
+ - **Server: silent email failures surfaced.** Resend SDK v3 changed from throwing to returning `{ data, error }`. All four send paths now check the error field and throw, so failures appear in logs and trigger Razorpay webhook retries.
260
+ - **Server: Razorpay customer-fetch errors now logged.** `resolveCustomerEmail` was catching all errors silently. Errors now emit a `webhook.customer_fetch_failed` log entry with the customer ID and error message.
253
261
 
254
- ## [1.2.10] 2026-04-30
262
+ ## [1.2.10] - 2026-04-30
255
263
 
256
264
  ### Fixed
257
- - **Server: accept raw base64 DER keys** `LICENSE_SIGNING_PRIVATE_KEY` / `LICENSE_SIGNING_PUBLIC_KEY` can now be pasted into Vercel as raw base64-encoded DER (no PEM headers required). The server auto-detects the format and constructs the correct `KeyObject`.
258
- - **Server: strip surrounding quotes from PEM env vars** Vercel UI sometimes wraps values in quotes; the key parser now trims them before attempting PEM or DER decode.
265
+ - **Server: accept raw base64 DER keys.** `LICENSE_SIGNING_PRIVATE_KEY` / `LICENSE_SIGNING_PUBLIC_KEY` can now be pasted into Vercel as raw base64-encoded DER (no PEM headers required). The server auto-detects the format and constructs the correct `KeyObject`.
266
+ - **Server: strip surrounding quotes from PEM env vars.** Vercel UI sometimes wraps values in quotes; the key parser now trims them before attempting PEM or DER decode.
259
267
 
260
- ## [1.2.9] 2026-04-30
268
+ ## [1.2.9] - 2026-04-30
261
269
 
262
270
  ### Fixed
263
- - **Windows libuv teardown crash** (`Assertion failed: !(handle->flags & UV_HANDLE_CLOSING)`) a 5xx response body left open across Playwright's async teardown kept a libuv handle alive. The 5xx path now drains and cancels the response body before throwing.
264
- - **PEM env var newlines normalised** `\n` literal sequences in Vercel / CI env vars are expanded to real newlines before passing to `createPrivateKey`.
271
+ - **Windows libuv teardown crash** (`Assertion failed: !(handle->flags & UV_HANDLE_CLOSING)`): a 5xx response body left open across Playwright's async teardown kept a libuv handle alive. The 5xx path now drains and cancels the response body before throwing.
272
+ - **PEM env var newlines normalised**: `\n` literal sequences in Vercel / CI env vars are expanded to real newlines before passing to `createPrivateKey`.
265
273
 
266
- ## [1.2.8] 2026-04-29
274
+ ## [1.2.8] - 2026-04-29
267
275
 
268
276
  ### Changed
269
277
  - Added `beta` dist-tag support to the publish pipeline so pre-release builds can be installed with `npm install pdf-report-forge@beta` without affecting the `latest` tag.
270
278
 
271
- ## [1.2.7] 2026-04-29
279
+ ## [1.2.7] - 2026-04-29
272
280
 
273
281
  ### Fixed
274
- - **Windows libuv teardown crash (definitive fix)** v1.2.6 used `AbortSignal.timeout()` to cancel the license fetch, but `AbortSignal.timeout()` internally schedules a timer that keeps Node's event loop alive through Playwright's async teardown, recreating the same `UV_HANDLE_CLOSING` assertion. Reverted to `AbortController` + explicit `clearTimeout` with eager `controller.abort()` in a `finally` block, which is safe across all Node versions and teardown paths.
282
+ - **Windows libuv teardown crash (definitive fix)**: v1.2.6 used `AbortSignal.timeout()` to cancel the license fetch, but `AbortSignal.timeout()` internally schedules a timer that keeps Node's event loop alive through Playwright's async teardown, recreating the same `UV_HANDLE_CLOSING` assertion. Reverted to `AbortController` + explicit `clearTimeout` with eager `controller.abort()` in a `finally` block, which is safe across all Node versions and teardown paths.
275
283
 
276
- ## [1.2.6] 2026-04-29
284
+ ## [1.2.6] - 2026-04-29
277
285
 
278
286
  ### Fixed
279
- - **JWT signature validation now clears the cache** a stale cached JWT with an invalid signature previously fell through to a misleading "unreachable" log path and silently kept the bad token. The validation path now clears the cache on any signature mismatch and surfaces a clear error.
287
+ - **JWT signature validation now clears the cache**: a stale cached JWT with an invalid signature previously fell through to a misleading "unreachable" log path and silently kept the bad token. The validation path now clears the cache on any signature mismatch and surfaces a clear error.
280
288
  - **Misleading "unreachable" log warning** removed from the license refresh path.
281
- - **Windows libuv teardown crash (initial fix via `AbortSignal.timeout()`)** see v1.2.7 for the definitive approach.
289
+ - **Windows libuv teardown crash (initial fix via `AbortSignal.timeout()`)**: see v1.2.7 for the definitive approach.
282
290
 
283
- ## [1.2.5] 2026-04-29
291
+ ## [1.2.5] - 2026-04-29
284
292
 
285
293
  ### Fixed
286
- - **`RF_LICENSE_KEY` full-assignment paste** if a user accidentally pastes the full shell assignment (`RF_LICENSE_KEY=RFSU-…`) as the env value, the reporter now strips the `RF_LICENSE_KEY=` prefix and uses the key value correctly.
294
+ - **`RF_LICENSE_KEY` full-assignment paste**: if a user accidentally pastes the full shell assignment (`RF_LICENSE_KEY=RFSU-…`) as the env value, the reporter now strips the `RF_LICENSE_KEY=` prefix and uses the key value correctly.
287
295
 
288
- ## [1.2.4] 2026-04-29
296
+ ## [1.2.4] - 2026-04-29
289
297
 
290
298
  ### Fixed
291
- - **License key env var empty-string fallback** an empty `RF_LICENSE_KEY=""` was treated as a set key, bypassing the "no key" path and sending an empty string to the server. Empty strings are now treated as unset.
299
+ - **License key env var empty-string fallback**: an empty `RF_LICENSE_KEY=""` was treated as a set key, bypassing the "no key" path and sending an empty string to the server. Empty strings are now treated as unset.
292
300
 
293
- ## [1.2.3] 2026-04-28
301
+ ## [1.2.3] - 2026-04-28
294
302
 
295
303
  ### Changed
296
- - **Removed postinstall script entirely.** `npm install` runs no lifecycle hook. License validation happens at test-run time only the reporter logs a warning and skips PDF generation if no valid key is found. No behaviour change for users with `RF_LICENSE_KEY` set.
304
+ - **Removed postinstall script entirely.** `npm install` runs no lifecycle hook. License validation happens at test-run time only: the reporter logs a warning and skips PDF generation if no valid key is found. No behaviour change for users with `RF_LICENSE_KEY` set.
297
305
 
298
- ## [1.2.2] 2026-04-28
306
+ ## [1.2.2] - 2026-04-28
299
307
 
300
308
  ### Fixed
301
- - **Package size reduced by 57%** source maps (`dist/*.map`) are no longer published. Packed size: 648 KB (was 1.4 MB). Unpacked: 1.7 MB (was 4.2 MB). No runtime behaviour change.
309
+ - **Package size reduced by 57%**: source maps (`dist/*.map`) are no longer published. Packed size: 648 KB (was 1.4 MB). Unpacked: 1.7 MB (was 4.2 MB). No runtime behaviour change.
302
310
 
303
- ## [1.2.1] 2026-04-28
311
+ ## [1.2.1] - 2026-04-28
304
312
 
305
313
  ### Fixed
306
- - **postinstall no longer fails `npm install`** on Windows (and non-TTY environments). Removed the interactive prompt and TTY gate; postinstall now prints a one-line notice and exits 0 unconditionally. License enforcement is unchanged the reporter itself checks at test-run time.
314
+ - **postinstall no longer fails `npm install`** on Windows (and non-TTY environments). Removed the interactive prompt and TTY gate; postinstall now prints a one-line notice and exits 0 unconditionally. License enforcement is unchanged: the reporter itself checks at test-run time.
307
315
 
308
- ## [1.2.0] 2026-04-28
316
+ ## [1.2.0] - 2026-04-28
309
317
 
310
318
  ### Added
311
- - **Multi-template output** `template` now accepts `TemplateId | TemplateId[]`. Pass an array to generate one PDF per template in a single run. The template name is automatically appended to the output filename (e.g. `report-detailed.pdf`, `report-executive.pdf`). One license check, one data-collection pass. Single-element arrays produce the same output as a plain string (no suffix). Duplicate entries are silently deduplicated.
319
+ - **Multi-template output**: `template` now accepts `TemplateId | TemplateId[]`. Pass an array to generate one PDF per template in a single run. The template name is automatically appended to the output filename (e.g. `report-detailed.pdf`, `report-executive.pdf`). One license check, one data-collection pass. Single-element arrays produce the same output as a plain string (no suffix). Duplicate entries are silently deduplicated.
312
320
 
313
321
  ## [Unreleased]
314
322
 
315
323
  ### Changed (BREAKING)
316
- - **Renamed npm package** from `playwright-pdf-reporter` to `pdf-report-forge` the bare name was already taken on npm. Update install commands and reporter array entries:
324
+ - **Renamed npm package** from `playwright-pdf-reporter` to `pdf-report-forge` (the bare name was already taken on npm). Update install commands and reporter array entries:
317
325
  - `npm install pdf-report-forge puppeteer-core`
318
326
  - `reporter: [['pdf-report-forge', { /* opts */ }]]`
319
327
  - Log prefix changed from `[playwright-pdf-reporter]` to `[reportforge]` to match the new brand-aligned identity. Update any CI grep filters accordingly.
320
328
  - PDF footer text changed from "Generated by playwright-pdf-reporter" to "Generated by ReportForge" across all three templates.
321
- - **Removed the free tier.** A valid subscription is now required to generate any PDF; the reporter logs a single warning and skips PDF generation when no license is available (no key, invalid key, expired sub, denied by server, or offline with no cache). Playwright tests still run normally only the PDF artifact is missing.
329
+ - **Removed the free tier.** A valid subscription is now required to generate any PDF; the reporter logs a single warning and skips PDF generation when no license is available (no key, invalid key, expired sub, denied by server, or offline with no cache). Playwright tests still run normally; only the PDF artifact is missing.
322
330
  - `LicenseClient.resolve()` now returns `LicenseInfo | null` (was `LicenseInfo` always); deleted `FREE_LICENSE` constant.
323
331
  - `LicensePlan` type narrowed to `'subscription'` only (was `'free' | 'subscription'`).
324
- - Deleted `FeatureGate` and the `showCommunityBadge` plumbing every feature is available with a valid license, none with an invalid one.
332
+ - Deleted `FeatureGate` and the `showCommunityBadge` plumbing: every feature is available with a valid license, none with an invalid one.
325
333
  - 4xx denial path no longer leaks the just-cleared cache through the offline fallback.
326
334
 
327
335
  ### Marketing
328
336
  - Pricing page, homepage, and dashboards now sell a single subscription plan with a 7-day free trial. Removed all "Free forever" surfaces.
329
337
 
330
- ## [1.0.0] 2026-04-21
338
+ ## [1.0.0] - 2026-04-21
331
339
 
332
340
  First public release. Subscription model replaces the former one-time tiers.
333
341
  (Note: this release still shipped a free tier on the marketing site; that was
@@ -335,12 +343,12 @@ removed in the unreleased breaking change above.)
335
343
 
336
344
  ### Added
337
345
  - Subscription licensing: **$19/mo** or **$149/yr** (~35% savings), 7-day free trial with no card.
338
- - Hybrid offline-first activation short `RFSU-…` handoff key exchanges for an Ed25519-signed JWT cached at `~/.reportforge/license.json`. Subsequent runs verify the JWT locally with a bundled public key, so reports render with no network access.
346
+ - Hybrid offline-first activation: short `RFSU-…` handoff key exchanges for an Ed25519-signed JWT cached at `~/.reportforge/license.json`. Subsequent runs verify the JWT locally with a bundled public key, so reports render with no network access.
339
347
  - Automatic JWT refresh in the background when the cache has < 24h remaining.
340
348
  - **25-machine** sliding 30-day cap per subscription, enforced by a stable hash of `(provider:repo)` in CI or `(hostname:mac)` on dev machines. Stale machines auto-prune after 30 days.
341
349
  - Customer self-service portal (cancel, switch plan, update card) via Stripe Customer Portal.
342
350
  - Claude design refresh across all three templates: cream `#FAF9F5` canvases, Source Serif Pro headings, Inter body, JetBrains Mono code, terracotta primary `#CC785C`, forest accent `#3F7D58`.
343
- - Fonts (Source Serif Pro, Inter, JetBrains Mono) bundled into the PDF no web font fetch at render time.
351
+ - Fonts (Source Serif Pro, Inter, JetBrains Mono) bundled into the PDF; no web font fetch at render time.
344
352
  - Bulk-run performance: 1 500-test report renders to ~0.65 MB (was ~10.4 MB).
345
353
 
346
354
  ### Changed
@@ -352,19 +360,19 @@ removed in the unreleased breaking change above.)
352
360
  ### Removed
353
361
  - One-time license tiers Professional (`RFPR-…`, $199/yr) and Enterprise (`RFEN-…`, $999/yr).
354
362
  - CLI generation of legacy `RFPR-`/`RFEN-` keys from `scripts/generate-license.ts`.
355
- - Standalone token-management dashboard (`/dashboard/tokens`, `/api/tokens/…`) superseded by the subscription dashboard at `/dashboard`.
363
+ - Standalone token-management dashboard (`/dashboard/tokens`, `/api/tokens/…`); superseded by the subscription dashboard at `/dashboard`.
356
364
 
357
365
  ### Migration
358
- No existing customers clean cutover. New installs get the subscription flow.
366
+ No existing customers; clean cutover. New installs get the subscription flow.
359
367
 
360
- ## [0.1.0] 2026-04-13
368
+ ## [0.1.0] - 2026-04-13
361
369
 
362
370
  ### Added
363
371
  - Initial release of `pdf-report-forge`
364
372
  - Three configurable report templates: `minimal`, `detailed`, `executive`
365
373
  - Sections: Executive Summary + KPIs, Suite Breakdown, Failure Deep-Dive, CI/CD & Environment
366
374
  - Embedded Chart.js charts (doughnut pass-rate, bar suite results) in `detailed` and `executive` templates
367
- - Screenshot embedding failures with screenshots are embedded inline (base64) in the PDF
375
+ - Screenshot embedding: failures with screenshots are embedded inline (base64) in the PDF
368
376
  - Requirements traceability matrix built from test tags in `detailed` template
369
377
  - Defect log table in `detailed` template
370
378
  - Cover page with verdict in `executive` template
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @reportforge/playwright-pdf
2
2
 
3
- > Playwright PDF reporter generate branded PDF reports from [Playwright Test](https://playwright.dev/) results. Three templates (minimal, detailed, executive) for developers, QA teams, and stakeholders. CI-ready, self-contained, with embedded screenshots and charts.
3
+ > Playwright PDF reporter: generate branded PDF reports from [Playwright Test](https://playwright.dev/) results. Three templates (minimal, detailed, executive) for developers, QA teams, and stakeholders. CI-ready, self-contained, with embedded screenshots and charts.
4
4
 
5
5
  Drop it into any Playwright project and get a PDF report on every CI run. No changes to your tests.
6
6
 
@@ -21,7 +21,7 @@ Drop it into any Playwright project and get a PDF report on every CI run. No cha
21
21
 
22
22
  ## Report Gallery
23
23
 
24
- Three templates, one reporter. Every PDF is fully offline fonts, charts, and screenshots are embedded.
24
+ Three templates, one reporter. Every PDF is fully offline: fonts, charts, and screenshots are embedded.
25
25
 
26
26
  <table>
27
27
  <tr>
@@ -45,23 +45,23 @@ Three templates, one reporter. Every PDF is fully offline — fonts, charts, and
45
45
 
46
46
  ## Features
47
47
 
48
- - **3 templates** `minimal` (developer), `detailed` (QA team), `executive` (stakeholders)
49
- - **Detailed reports** KPI dashboard, suite breakdown with inline failure detail (error, screenshot, root-cause chip) under each failed test, CI/CD environment
50
- - **Embedded Chart.js** pass-rate doughnut + per-suite bar chart, bundled inline (no CDN)
51
- - **Self-contained PDFs** screenshots, fonts, logos all embedded; share or archive with confidence
52
- - **Custom branding** logo, primary/accent colours, watermark, PDF password encryption
53
- - **Dynamic filenames** `{date}`, `{branch}`, `{status}` tokens in the output path
54
- - **Instant demo report** `npx @reportforge/playwright-pdf demo` generates a realistic sample PDF before subscribing no license key required
55
- - **CI/CD snippets** GitHub Actions, GitLab CI, Bitbucket Pipelines, Jenkins, Azure DevOps
56
- - **Live runs** opt-in `live` streams per-test progress to an unguessable watch link printed at run start; all shards of one CI run converge on a single live dashboard while tests execute. The PDF is still produced at the end, unchanged
57
- - **Shard merging** combine N Playwright JSON shard reports into one PDF via `shardResults`; accepts glob patterns or explicit paths
58
- - **Notifications** post pass/fail summaries to Slack, Teams, Discord, or email after each run; configurable trigger (`always` / `failure` / `success`) per channel; email and Discord support optional PDF attachment via `attachPdf`
59
- - **Flakiness trend** top-N flakiest tests table with per-test dot sparkline across stored history runs in the `detailed` template; `flakinessTopN` option (default 5, `0` disables)
60
- - **Offline failure analysis** sorts each failure into one of 7 root-cause buckets and renders a per-test root-cause chip inline under the failed test in the `detailed` PDF (dominant-cause one-liner in `executive`). No network, no AI service a small embedded classifier that updates itself safely over your existing license refresh; pin it any time. Full details at [reportforge.org/docs/advanced/failure-analysis](https://reportforge.org/docs/advanced/failure-analysis).
61
- - `npx @reportforge/playwright-pdf export-feedback` exports locally-collected unrecognized failures (tokenized, local-only) for optional manual sharing.
62
- - **Rich execution capture** opt-in "Steps to Reproduce" outline (a nested, copy-pasteable Markdown list of your `test.step`s and assertions add `apiSteps` for the full click/fill/check action trail), Node console tail, and trace/video links under each failed test in the defect log, read straight from the Playwright step tree no fixtures, no test-code changes. Enable via `capture` (`steps` / `apiSteps` / `console` / `evidence`); off by default.
63
- - **Configurable sections** add or remove any report section per template via `sections`.
64
- - **Hybrid licensing** one short key unlocks it; reports keep rendering offline via a cached JWT between refreshes
48
+ - **3 templates**: `minimal` (developer), `detailed` (QA team), `executive` (stakeholders)
49
+ - **Detailed reports**: KPI dashboard, suite breakdown with inline failure detail (error, screenshot, root-cause chip) under each failed test, CI/CD environment
50
+ - **Embedded Chart.js**: pass-rate doughnut + per-suite bar chart, bundled inline (no CDN)
51
+ - **Self-contained PDFs**: screenshots, fonts, logos all embedded; share or archive with confidence
52
+ - **Custom branding**: logo, primary/accent colours, watermark, PDF password encryption
53
+ - **Dynamic filenames**: `{date}`, `{branch}`, `{status}` tokens in the output path
54
+ - **Instant demo report**: `npx @reportforge/playwright-pdf demo` generates a realistic sample PDF before subscribing, no license key required
55
+ - **CI/CD snippets**: GitHub Actions, GitLab CI, Bitbucket Pipelines, Jenkins, Azure DevOps
56
+ - **Live runs**: opt-in `live` streams per-test progress to an unguessable watch link printed at run start; all shards of one CI run converge on a single live dashboard while tests execute. The PDF is still produced at the end, unchanged
57
+ - **Shard merging**: combine N Playwright JSON shard reports into one PDF via `shardResults`; accepts glob patterns or explicit paths
58
+ - **Notifications**: post pass/fail summaries to Slack, Teams, Discord, or email after each run; configurable trigger (`always` / `failure` / `success`) per channel; email and Discord support optional PDF attachment via `attachPdf`
59
+ - **Flakiness trend**: top-N flakiest tests table with per-test dot sparkline across stored history runs in the `detailed` template; `flakinessTopN` option (default 5, `0` disables)
60
+ - **Offline failure analysis**: sorts each failure into one of 7 root-cause buckets and renders a root-cause chip under each failed test in the `detailed` PDF (dominant-cause one-liner in `executive`). No network, no AI service: a small embedded classifier that updates over your existing license refresh; pin it any time. Full details at [reportforge.org/docs/advanced/failure-analysis](https://reportforge.org/docs/advanced/failure-analysis).
61
+ - `npx @reportforge/playwright-pdf export-feedback`: exports locally-collected unrecognized failures (tokenized, local-only) for optional manual sharing.
62
+ - **Rich execution capture**: opt-in "Steps to Reproduce" outline (a nested, copy-pasteable Markdown list of your `test.step`s and assertions; add `apiSteps` for the full click/fill/check trail), Node console tail, and trace/video links under each failed test in the defect log. Read straight from the Playwright step tree: no fixtures, no test-code changes. Enable via `capture` (`steps` / `apiSteps` / `console` / `evidence`); off by default.
63
+ - **Configurable sections**: add or remove any report section per template via `sections`.
64
+ - **Hybrid licensing**: one short key unlocks it; reports keep rendering offline via a cached JWT between refreshes
65
65
 
66
66
  ---
67
67
 
@@ -87,16 +87,16 @@ export default defineConfig({
87
87
  });
88
88
  ```
89
89
 
90
- `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.
90
+ `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.
91
91
 
92
92
  ```bash
93
93
  npx playwright test
94
94
  # → reports/2026-05-01-main-failed.pdf
95
95
  ```
96
96
 
97
- > **See it first.** Run `npx @reportforge/playwright-pdf demo` to generate a realistic sample PDF in under 60 seconds no license key required. Supports `--template=minimal|detailed|executive` and `--output=<path>`.
97
+ > **See it first.** Run `npx @reportforge/playwright-pdf demo` to generate a realistic sample PDF in under 60 seconds, no license key required. Supports `--template=minimal|detailed|executive` and `--output=<path>`.
98
98
 
99
- > **License required.** Start a **[7-day free trial at reportforge.org/pricing](https://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.
99
+ > **License required.** Start a **[7-day free trial at reportforge.org/pricing](https://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.
100
100
 
101
101
  ---
102
102
 
@@ -132,7 +132,7 @@ sudo apt-get update -qq && sudo apt-get install -y google-chrome-stable
132
132
  export PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable
133
133
  ```
134
134
 
135
- > **Note:** Do not use the `chromium-browser` apt package it installs as a snap on Ubuntu and Puppeteer cannot drive it.
135
+ > **Note:** Do not use the `chromium-browser` apt package: it installs as a snap on Ubuntu and Puppeteer cannot drive it.
136
136
 
137
137
  **macOS**
138
138
 
@@ -173,37 +173,37 @@ Currency is auto-detected by region; toggle on the pricing page.
173
173
 
174
174
  All options are the second element of the reporter tuple.
175
175
 
176
- <!-- AUTOGEN:options-table START edit scripts/docs/options-meta.ts, then run npm run docs:gen -->
176
+ <!-- AUTOGEN:options-table START: edit scripts/docs/options-meta.ts, then run npm run docs:gen -->
177
177
  | Option | Type | Default | Description |
178
178
  |---|---|---|---|
179
179
  | `outputFile` | `string` | `'playwright-report/{date}-report.pdf'` | Output path. Supports tokens: `{date}`, `{datetime}`, `{branch}`, `{status}`, `{total}`, `{passed}`, `{failed}`, `{project}`. Directory is created if absent. |
180
- | `template` | `'minimal' \| 'detailed' \| 'executive'` or array | `'minimal'` | Template(s) to generate. Pass an array to produce one PDF per template in one run the template name is appended to each output filename automatically (e.g. `report-detailed.pdf`). |
180
+ | `template` | `'minimal' \| 'detailed' \| 'executive'` or array | `'minimal'` | Template(s) to generate. Pass an array to produce one PDF per template in one run: the template name is appended to each output filename automatically (e.g. `report-detailed.pdf`). |
181
181
  | `licenseKey` | `string` | env `RF_LICENSE_KEY` | Subscription key (format `RFSU-…`). Falls back to the `RF_LICENSE_KEY` environment variable. PDF generation is skipped when absent or invalid. |
182
- | `logo` | `string` | | Path to a logo image (PNG, JPG, or SVG) to embed in the report header. Supports absolute and relative paths. |
182
+ | `logo` | `string` | n/a | Path to a logo image (PNG, JPG, or SVG) to embed in the report header. Supports absolute and relative paths. |
183
183
  | `primaryColor` | `string` | `'#CC785C'` | Primary brand colour (3-, 6-, or 8-digit hex). Used for headers and accent bars. |
184
184
  | `accentColor` | `string` | `'#3F7D58'` | Accent brand colour (hex). Used for highlights and badges. |
185
- | `watermark` | `string` | | Text to render as a diagonal watermark overlay on every page e.g. `'CONFIDENTIAL'`, `'DRAFT'`. |
186
- | `pdfPassword` | `string` | | Password-protect the generated PDF. Requires `qpdf` installed on the system. |
185
+ | `watermark` | `string` | n/a | Text to render as a diagonal watermark overlay on every page, e.g. `'CONFIDENTIAL'` or `'DRAFT'`. |
186
+ | `pdfPassword` | `string` | n/a | Password-protect the generated PDF. Requires `qpdf` installed on the system. |
187
187
  | `reportTitle` | `string` | `'Playwright Test Report'` | Custom title for the report cover page and running header. |
188
188
  | `projectName` | `string` | from `package.json` | Project or application name. Inferred from the `package.json` `name` field if absent. |
189
- | `open` | `boolean` | `false` | Open the generated PDF automatically after generation. For local use only ignored in CI. |
189
+ | `open` | `boolean` | `false` | Open the generated PDF automatically after generation. For local use only; ignored in CI. |
190
190
  | `puppeteerExecutablePath` | `string` | auto-detect | Full path to a Chrome or Chromium binary. Falls back to `PUPPETEER_EXECUTABLE_PATH` env, then system Chrome discovery. |
191
191
  | `serverUrl` | `string` | `'https://reportforge.org'` | Base URL for the ReportForge licensing server. Override only for self-hosting or local development. |
192
192
  | `compressionLevel` | `'auto' \| 'none' \| 'balanced' \| 'max'` | `'auto'` | Screenshot JPEG quality preset. `'auto'` picks based on failure volume; `'none'` keeps original PNGs; `'balanced'` uses JPEG q85; `'max'` uses JPEG q70. |
193
- | `includeScreenshots` | `boolean` | `true` | Embed Playwright screenshots in the PDF. Set to `false` to omit images useful for exec-audience reports or reducing file size. |
193
+ | `includeScreenshots` | `boolean` | `true` | Embed Playwright screenshots in the PDF. Set to `false` to omit images; useful for exec-audience reports or reducing file size. |
194
194
  | `maxInlineFailures` | `number` | derived from `compressionLevel` | Cap on failure entries rendered inline in the PDF. Overflow is written to a sibling `{basename}-failures.json` sidecar file. |
195
195
  | `maxFileSizeMb` | `number` | `8` | Soft cap on the final PDF size in MB. If exceeded, the report is re-rendered once with the `'max'` compression preset. |
196
- | `shardResults` | `string \| string[]` | | Glob or path array of Playwright JSON shard report files to merge into one PDF. See the Shard Merging docs. |
197
- | `notify` | `object` | | Notification channels: `slack`, `teams` (each `{ url, enabled, on }`), `discord` (`{ url, enabled, on, attachPdf }`), `email` (`{ to, enabled, on, attachPdf }`). See the Notifications docs. |
196
+ | `shardResults` | `string \| string[]` | n/a | Glob or path array of Playwright JSON shard report files to merge into one PDF. See the Shard Merging docs. |
197
+ | `notify` | `object` | n/a | Notification channels: `slack`, `teams` (each `{ url, enabled, on }`), `discord` (`{ url, enabled, on, attachPdf }`), `email` (`{ to, enabled, on, attachPdf }`). See the Notifications docs. |
198
198
  | `failureAnalysis` | `object` | `{ enabled: true }` | Offline failure root-cause analysis (embedded Naive Bayes; no runtime network). Fields: `enabled` (default `true`), `maxClusters` (default `10`), `minStrength` (`weak`\|`moderate`\|`strong`, default `weak`), `maxFailuresToAnalyse` (default `500`), `collectUnclassified` (default `true`), `autoUpdateModel` (default `true`). See the Failure Analysis docs. |
199
- | `capture` | `object` | `{}` (off) | Opt-in rich execution capture for the defect log (reporter-side; no fixtures, no test-code changes). Fields: `steps` (a copy-pasteable "Steps to Reproduce" outline built from the Playwright step tree each row a Markdown list line indented under its parent `test.step`, default `false`), `apiSteps` (include every top-level `pw:api` action (click/fill/check/goto) in the outline for a full action trail; off by default the outline shows only `test.step` intent + `expect` assertions, default `false`), `console` (Node stdout/stderr tail, default `false`), `evidence` (trace/video file links, default `false`), `maxSteps` (default `50`), `maxConsoleLines` (default `50`). Renders in the Defect Log section of the `detailed` template. |
200
- | `live` | `object` | `{}` (off) | Opt-in live test-execution streaming. When `enabled`, the reporter prints an unguessable watch link to the CI logs at run start and streams per-test progress to the hosted dashboard while tests run all shards of one CI run converge on a single live view. Fields: `enabled` (default `false`), `runId` (override the auto-derived run id), `serverUrl` (override the streaming server), `steps` (`none`\|`failed`\|`intent`\|`all`, default `failed`; `intent` shows only your `test.step` names plus any failing step), `console` (stream stdout/stderr tails, default `false`), `flushMs` (batch debounce 500–10000, default `2000`). The PDF at the end of the run is unaffected. Requires an active subscription with the `live` entitlement. See the Live Runs docs. |
199
+ | `capture` | `object` | `{}` (off) | Opt-in rich execution capture for the defect log (reporter-side; no fixtures, no test-code changes). Fields: `steps` (a copy-pasteable "Steps to Reproduce" outline built from the Playwright step tree; each row is a Markdown list line indented under its parent `test.step`, default `false`), `apiSteps` (include every top-level `pw:api` action (click/fill/check/goto) in the outline for a full action trail; without it the outline shows only `test.step` intent + `expect` assertions, default `false`), `console` (Node stdout/stderr tail, default `false`), `evidence` (trace/video file links, default `false`), `maxSteps` (default `50`), `maxConsoleLines` (default `50`). Renders in the Defect Log section of the `detailed` template. |
200
+ | `live` | `object` | `{}` (off) | Opt-in live test-execution streaming. When `enabled`, the reporter prints an unguessable watch link to the CI logs at run start and streams per-test progress to the hosted dashboard while tests run; all shards of one CI run converge on a single live view. Fields: `enabled` (default `false`), `runId` (override the auto-derived run id), `serverUrl` (override the streaming server), `steps` (`none`\|`failed`\|`intent`\|`all`, default `failed`; `intent` shows only your `test.step` names plus any failing step), `console` (stream stdout/stderr tails, default `false`), `flushMs` (batch debounce 500–10000, default `2000`). The PDF at the end of the run is unaffected. Requires an active subscription with the `live` entitlement. See the Live Runs docs. |
201
201
  | `historyFile` | `string` | `~/.reportforge/{key}/history.json` | Path to the history JSON file. Relative paths resolve from `cwd`. Enables pass-rate trending charts in the `detailed` template. |
202
202
  | `historySize` | `number` | `10` | Maximum number of test runs to keep in the history file (integer ≥ 2). Older runs are pruned on append. |
203
203
  | `showTrend` | `boolean` | `true` | Show the pass-rate sparkline and delta badge in the `detailed` template. Set to `false` to disable history tracking entirely. |
204
204
  | `flakinessTopN` | `number` | `5` | Maximum flaky tests to show in the flakiness table (`detailed` template). Set to `0` to disable the table entirely. |
205
- | `slowTestThreshold` | `number` | `10` | Minimum timed-test count before `SLOW` badges appear in the suite breakdown below this, every test is trivially the "slowest" so badges stay hidden. On larger runs only genuine outliers (at least 2× the median test duration) are badged, so the badge stays rare. Set to `0` to drop the run-size gate (outliers still required). |
206
- | `templatePath` | `string \| string[]` | | Path to a custom Handlebars (`.hbs`) template file. Takes precedence over `template`. Pass an array to generate one PDF per custom template. See the Custom Templates docs. |
205
+ | `slowTestThreshold` | `number` | `10` | Minimum timed-test count before `SLOW` badges appear in the suite breakdown: below this, every test is trivially the "slowest" so badges stay hidden. On larger runs only genuine outliers (at least 2× the median test duration) are badged, so the badge stays rare. Set to `0` to drop the run-size gate (outliers still required). |
206
+ | `templatePath` | `string \| string[]` | n/a | Path to a custom Handlebars (`.hbs`) template file. Takes precedence over `template`. Pass an array to generate one PDF per custom template. See the Custom Templates docs. |
207
207
  | `sections` | `object` | per-template | Override which report sections appear, on top of the chosen template's defaults. Flat keys are the baseline for every chosen template; per-template keys (`minimal`\|`detailed`\|`executive`) override per template. Block toggles: `coverPage`, `analysisOneliner`, `releaseGate`, `summary`, `charts`, `trend`, `requirementsMatrix`, `ciEnvironment`, `suiteBreakdown`, `failureDeepDive`, `failureAnalysis`, `slowTests`, `defectLog`. Display modifiers: `passRate`, `fullEnvironment`, `retries`, `fullFailures`, `stackTraces`. See the Report Sections docs. |
208
208
  <!-- AUTOGEN:options-table END -->
209
209
 
@@ -211,9 +211,9 @@ Full reference: [reportforge.org/docs/configuration](https://reportforge.org/doc
211
211
 
212
212
  ### Live Runs
213
213
 
214
- Watch a run as it happens. With `live` enabled, the reporter prints an unguessable watch link boxed under a `Live Tracker` heading to your CI logs at run start and streams per-test progress to a hosted dashboard while tests execute. All shards of one CI run converge on a single live view, each test shows its own steps and assertions as sub-lines beneath its row each step once, as it settles, indented under its parent `test.step` and read in source order (Playwright's hooks, fixtures, and teardown are filtered out) and the PDF is still generated at the end, unchanged.
214
+ Watch a run as it happens. With `live` enabled, the reporter prints an unguessable watch link (boxed under a `Live Tracker` heading) to your CI logs at run start and streams per-test progress to a hosted dashboard while tests execute. All shards of one CI run converge on a single live view. Each test shows its steps and assertions as sub-lines beneath its row: each step once, as it settles, indented under its parent `test.step` in source order (Playwright's hooks, fixtures, and teardown are filtered out). The PDF is still generated at the end, unchanged.
215
215
 
216
- > The watch link is entitlement-gated. If you enable `live` but see no `Live Tracker` line, the reporter logs why (missing `RF_LICENSE_KEY`, or a cached token without the `live` entitlement delete `~/.reportforge/license.json` to force re-activation).
216
+ > The watch link is entitlement-gated. If you enable `live` but see no `Live Tracker` line, the reporter logs why (missing `RF_LICENSE_KEY`, or a cached token without the `live` entitlement; delete `~/.reportforge/license.json` to force re-activation).
217
217
 
218
218
  ```typescript
219
219
  // playwright.config.ts
@@ -223,20 +223,20 @@ reporter: [
223
223
  live: {
224
224
  enabled: true,
225
225
  steps: 'failed', // 'none' | 'failed' | 'intent' | 'all'
226
- // console: false, // stream stdout/stderr tails (off by default see note)
226
+ // console: false, // stream stdout/stderr tails (off by default; see note)
227
227
  // flushMs: 2000, // batch debounce (500–10000)
228
228
  },
229
229
  }],
230
230
  ],
231
231
  ```
232
232
 
233
- `steps: 'intent'` shows only your `test.step` names (plus any failing step) the cleanest, most readable trail; `'all'` adds every action and assertion beneath its parent step, `'failed'` (default) keeps intent + assertions + failures.
233
+ `steps: 'intent'` shows only your `test.step` names (plus any failing step): the cleanest, most readable trail. `'all'` adds every action and assertion beneath its parent step; `'failed'` (default) keeps intent + assertions + failures.
234
234
 
235
- Sharded runs need no extra config the run id is derived from the run-shared CI identifier (e.g. `GITHUB_RUN_ID`), identical across every matrix shard. Set `RF_LIVE_RUN_ID` to override when your CI is not auto-detected.
235
+ Sharded runs need no extra config: the run id is derived from the run-shared CI identifier (e.g. `GITHUB_RUN_ID`), identical across every matrix shard. Set `RF_LIVE_RUN_ID` to override when your CI is not auto-detected.
236
236
 
237
237
  Live streaming is best-effort and entitlement-gated: if the server is unreachable the run is unaffected, and an active subscription with the `live` feature is required. If you've configured Slack/Teams/Discord notifications, the watch link is also posted to those channels when the run starts.
238
238
 
239
- > **Security:** the watch link exposes test titles + statuses (and step titles when `steps` is on). Leaving `console: false` is recommended enabling it streams your tests' stdout/stderr to anyone holding the link. Full details at [reportforge.org/docs/advanced/live](https://reportforge.org/docs/advanced/live).
239
+ > **Security:** the watch link exposes test titles + statuses (and step titles when `steps` is on). Leaving `console: false` is recommended: enabling it streams your tests' stdout/stderr to anyone holding the link. Full details at [reportforge.org/docs/advanced/live](https://reportforge.org/docs/advanced/live).
240
240
 
241
241
  ### Shard Merging
242
242
 
@@ -245,7 +245,7 @@ Combine parallel Playwright shards into one PDF without re-running any tests.
245
245
  **Workflow:**
246
246
 
247
247
  1. Run each shard with `--reporter=json` to produce a JSON output file.
248
- 2. In a separate step, point `shardResults` at those files accepts a glob or an explicit array.
248
+ 2. In a separate step, point `shardResults` at those files; it accepts a glob or an explicit array.
249
249
 
250
250
  ```typescript
251
251
  // playwright.config.ts (merge step)
@@ -258,7 +258,7 @@ reporter: [
258
258
  ],
259
259
  ```
260
260
 
261
- The merge step can run against a dummy test file with zero tests `shardResults` takes precedence over live results.
261
+ The merge step can run against a dummy test file with zero tests: `shardResults` takes precedence over live results.
262
262
 
263
263
  > **Note:** Timed-out tests are counted as failures in shard mode (Playwright JSON stats do not distinguish `timedOut` from `failed`).
264
264
 
@@ -293,7 +293,7 @@ notify: {
293
293
  },
294
294
  ```
295
295
 
296
- Each channel is independent. `enabled: false` (the default) lets you store a URL without activating it useful for staging configs.
296
+ Each channel is independent. `enabled: false` (the default) lets you store a URL without activating it; useful for staging configs.
297
297
 
298
298
  The `on` trigger controls when the message fires:
299
299
 
@@ -303,19 +303,19 @@ The `on` trigger controls when the message fires:
303
303
  | `'failure'` | `stats.failed > 0` or run timed out / interrupted |
304
304
  | `'success'` | All tests passed |
305
305
 
306
- **Email** requires `RESEND_API_KEY` in the environment (get one at [resend.com](https://resend.com)). Sender defaults to `noreply@reportforge.org`; override with `RESEND_FROM`. Store webhook URLs and API keys as CI secrets never commit them.
306
+ **Email** requires `RESEND_API_KEY` in the environment (get one at [resend.com](https://resend.com)). Sender defaults to `noreply@reportforge.org`; override with `RESEND_FROM`. Store webhook URLs and API keys as CI secrets; never commit them.
307
307
 
308
- **PDF attachment** (`attachPdf: true`) is available on `email` and `discord` Slack and Teams webhooks cannot carry file uploads. On Discord the PDF is uploaded with the message; if the upload fails or the PDF exceeds Discord's file-size cap, the summary still posts without the attachment. With multiple templates, the first PDF is attached.
308
+ **PDF attachment** (`attachPdf: true`) is available on `email` and `discord`: Slack and Teams webhooks cannot carry file uploads. On Discord the PDF is uploaded with the message; if the upload fails or the PDF exceeds Discord's file-size cap, the summary still posts without the attachment. With multiple templates, the first PDF is attached.
309
309
 
310
- 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 failure you still get the ping).
310
+ 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 failure; you still get the ping).
311
311
 
312
312
  ### Test History Trending
313
313
 
314
314
  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.
315
315
 
316
- **Local dev (zero config)** history is written automatically to `~/.reportforge/{projectKey}/history.json`. The sparkline appears once two or more runs have been recorded.
316
+ **Local dev (zero config)**: history is written automatically to `~/.reportforge/{projectKey}/history.json`. The sparkline appears once two or more runs have been recorded.
317
317
 
318
- **CI with ephemeral runners** set `historyFile` to a project-relative path and cache it between runs:
318
+ **CI with ephemeral runners**: set `historyFile` to a project-relative path and cache it between runs:
319
319
 
320
320
  ```typescript
321
321
  // playwright.config.ts
@@ -331,10 +331,10 @@ reporter: [['@reportforge/playwright-pdf', {
331
331
  with:
332
332
  path: .reportforge/history.json
333
333
  key: reportforge-history-${{ github.ref }}
334
- # Omit restore-keys cross-branch fallback causes misleading sparklines on PRs
334
+ # Omit restore-keys; cross-branch fallback causes misleading sparklines on PRs
335
335
  ```
336
336
 
337
- **Monorepo** each package needs a distinct `historyFile` (e.g. `.reportforge/api-history.json`, `.reportforge/web-history.json`) so runs do not overwrite each other.
337
+ **Monorepo**: each package needs a distinct `historyFile` (e.g. `.reportforge/api-history.json`, `.reportforge/web-history.json`) so runs do not overwrite each other.
338
338
 
339
339
  ### Flakiness Trend Table
340
340
 
@@ -343,11 +343,11 @@ The `detailed` template includes a **Top flaky tests** table showing which tests
343
343
  ```typescript
344
344
  reporter: [['@reportforge/playwright-pdf', {
345
345
  template: 'detailed',
346
- flakinessTopN: 5, // default show top 5; set 0 to disable
346
+ flakinessTopN: 5, // default: show top 5; set 0 to disable
347
347
  }]]
348
348
  ```
349
349
 
350
- The table is gated behind `showTrend: true` (the default) and appears automatically once history entries are present. Runs written before the flakiness feature was added are excluded from the denominator the table fills in correctly as newer runs accumulate. Set `flakinessTopN: 0` to hide the table entirely.
350
+ The table is gated behind `showTrend: true` (the default) and appears automatically once history entries are present. Runs written before the flakiness feature was added are excluded from the denominator; the table fills in correctly as newer runs accumulate. Set `flakinessTopN: 0` to hide the table entirely.
351
351
 
352
352
  ### Filename tokens
353
353
 
@@ -361,21 +361,21 @@ The table is gated behind `showTrend: true` (the default) and appears automatica
361
361
 
362
362
  ## Templates
363
363
 
364
- ### `minimal` Developer-focused
364
+ ### `minimal`: Developer-focused
365
365
 
366
366
  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.
367
367
 
368
- ### `detailed` QA Team
368
+ ### `detailed`: QA Team
369
369
 
370
370
  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.
371
371
 
372
- ### `executive` Stakeholder presentations
372
+ ### `executive`: Stakeholder presentations
373
373
 
374
- 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.
374
+ 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.
375
375
 
376
376
  ### Shared across all three
377
377
 
378
- Every report leads with a **release-gate** ship/hold banner derived from the run verdict, surfaces **timed-out** tests as their own KPI card and pass-rate chart slice, and lists failures **most-severe first** (with severity-coloured card borders in `minimal` and `detailed`). Pages **pack compactly** large sections flow and break between rows instead of each starting on a fresh page. The Suite Results chart breaks a single-file run down by **describe block** so it never collapses to one bar. Requirements coverage bars are coloured by threshold (red &lt;50%, amber &lt;80%, green ≥80%).
378
+ Every report leads with a **release-gate** ship/hold banner derived from the run verdict, surfaces **timed-out** tests as their own KPI card and pass-rate chart slice, and lists failures **most-severe first** (with severity-coloured card borders in `minimal` and `detailed`). Pages **pack compactly**: large sections flow and break between rows instead of each starting on a fresh page. The Suite Results chart breaks a single-file run down by **describe block** so it never collapses to one bar. Requirements coverage bars are coloured by threshold (red &lt;50%, amber &lt;80%, green ≥80%).
379
379
 
380
380
  ### Generating multiple templates in one run
381
381
 
@@ -397,11 +397,11 @@ reporter: [
397
397
  # → reports/2026-04-28-report-executive.pdf
398
398
  ```
399
399
 
400
- One license check, one data-collection pass faster than multiple reporter instances. Duplicate entries are silently deduplicated.
400
+ One license check, one data-collection pass: faster than multiple reporter instances. Duplicate entries are silently deduplicated.
401
401
 
402
402
  ### Report Sections
403
403
 
404
- Each built-in template ships a curated set of sections. The `sections` option lets you **add a section a template hides or remove one it shows per template** without writing a custom template.
404
+ Each built-in template ships a curated set of sections. The `sections` option lets you **add a section a template hides or remove one it shows, per template**, without writing a custom template.
405
405
 
406
406
  ```ts
407
407
  reporter: [['@reportforge/playwright-pdf', {
@@ -416,7 +416,7 @@ reporter: [['@reportforge/playwright-pdf', {
416
416
 
417
417
  **Resolution order** (lowest → highest): the template's defaults → flat keys (baseline for all chosen templates) → per-template keys (`minimal` / `detailed` / `executive`). An unknown key throws a configuration error (typo-safe).
418
418
 
419
- #### Block toggles which sections appear
419
+ #### Block toggles: which sections appear
420
420
 
421
421
  | Key | Renders |
422
422
  |---|---|
@@ -434,7 +434,7 @@ reporter: [['@reportforge/playwright-pdf', {
434
434
  | `slowTests` | `SLOW` badge on the duration-ranked slowest tests, shown inline in the breakdown |
435
435
  | `defectLog` | `DEF-####` numbered failure table (severity, duration) + opt-in repro detail (`capture`) |
436
436
 
437
- #### Display modifiers tune a section that's on
437
+ #### Display modifiers: tune a section that's on
438
438
 
439
439
  | Key | Effect |
440
440
  |---|---|
@@ -471,11 +471,11 @@ Omit `sections` entirely and each template renders exactly this (✓ = on):
471
471
 
472
472
  #### Dependencies & gotchas
473
473
 
474
- - **`trend` needs `charts`.** The trend line, run-history, and flakiness table live inside the charts block, so `trend: true` does nothing with `charts: false` (it's coerced off). It also needs history data keep the top-level `showTrend` option on.
475
- - **Inline failure detail needs `suiteBreakdown`.** `failureDeepDive` (failure detail), `failureAnalysis` (root-cause chip), and `slowTests` (`SLOW` badge) now render *inside* the suite breakdown, so they show nothing when `suiteBreakdown` is off. The chip (`failureAnalysis`) also needs `failureDeepDive` it lives inside the failure detail, so it's coerced off without it.
476
- - **Data-gated sections** `failureAnalysis`, `requirementsMatrix`, `slowTests`, `defectLog` render only when there's matching data (classified failures, tagged tests, a meaningful slow set, failures). Toggling them on with no data shows nothing.
477
- - **Render-layer only.** `sections` controls what's drawn, never what's collected the data switches stay separate: `showTrend` (history), `flakinessTopN` (flaky-table size), `failureAnalysis.enabled` (classifier), `includeScreenshots` (images).
478
- - **Custom templates.** `sections` applies to the built-in templates; a custom `templatePath` controls its own layout (every section available) and ignores `sections` — you'll get a warning if both are set.
474
+ - **`trend` needs `charts`.** The trend line, run-history, and flakiness table live inside the charts block, so `trend: true` does nothing with `charts: false` (it's coerced off). It also needs history data; keep the top-level `showTrend` option on.
475
+ - **Inline failure detail needs `suiteBreakdown`.** `failureDeepDive` (failure detail), `failureAnalysis` (root-cause chip), and `slowTests` (`SLOW` badge) now render *inside* the suite breakdown, so they show nothing when `suiteBreakdown` is off. The chip (`failureAnalysis`) also needs `failureDeepDive`: it lives inside the failure detail, so it's coerced off without it.
476
+ - **Data-gated sections**: `failureAnalysis`, `requirementsMatrix`, `slowTests`, `defectLog` render only when there's matching data (classified failures, tagged tests, a meaningful slow set, failures). Toggling them on with no data shows nothing.
477
+ - **Render-layer only.** `sections` controls what's drawn, never what's collected; the data switches stay separate: `showTrend` (history), `flakinessTopN` (flaky-table size), `failureAnalysis.enabled` (classifier), `includeScreenshots` (images).
478
+ - **Custom templates.** `sections` applies to the built-in templates; a custom `templatePath` controls its own layout (every section available) and ignores `sections`. You'll get a warning if both are set.
479
479
 
480
480
  ---
481
481
 
@@ -500,7 +500,7 @@ Full workflows for all four CI providers: [reportforge.org/docs/ci-cd](https://r
500
500
  path: reports/*.pdf
501
501
  ```
502
502
 
503
- ### GitHub Actions Sharded runs
503
+ ### GitHub Actions: Sharded runs
504
504
 
505
505
  Run shards in parallel with `--reporter=json`, then merge all JSON files into one PDF:
506
506
 
@@ -543,7 +543,7 @@ jobs:
543
543
  with: { name: playwright-pdf-report, path: reports/*.pdf }
544
544
  ```
545
545
 
546
- 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.
546
+ 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.
547
547
 
548
548
  ### GitLab CI
549
549
 
@@ -606,11 +606,11 @@ ReportForge ships a **hybrid offline-first** model:
606
606
 
607
607
  1. Paste your `RFSU-…` key into the config once (or set `RF_LICENSE_KEY`).
608
608
  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`.
609
- 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.
609
+ 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.
610
610
  4. When the cache has less than 24 hours left, the reporter refreshes it in the background.
611
611
  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.
612
612
 
613
- 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.
613
+ 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.
614
614
 
615
615
  ```bash
616
616
  export RF_LICENSE_KEY=RFSU-XXXX-XXXX-XXXX-XXXX
@@ -657,17 +657,17 @@ Full guide: [reportforge.org/docs/troubleshooting](https://reportforge.org/docs/
657
657
 
658
658
  Full documentation at [reportforge.org/docs](https://reportforge.org/docs):
659
659
 
660
- - [Quick start](https://reportforge.org/docs/quickstart) install, configure, activate
661
- - [Chrome setup](https://reportforge.org/docs/running-tests#chrome-setup) Windows, Linux, macOS
662
- - [CI/CD integration](https://reportforge.org/docs/ci-cd) GitHub Actions, GitLab CI, Bitbucket Pipelines, Jenkins, Azure DevOps
663
- - [Configuration reference](https://reportforge.org/docs/configuration) all options
664
- - [Filename tokens](https://reportforge.org/docs/configuration#tokens) `{date}`, `{branch}`, `{status}`
665
- - [Templates](https://reportforge.org/docs/templates) minimal, detailed, executive
666
- - [Live runs](https://reportforge.org/docs/advanced/live) stream per-test progress to a shared watch link
667
- - [Report Sections](https://reportforge.org/docs/configuration#report-sections) add or remove sections per template
668
- - [License & offline behaviour](https://reportforge.org/docs/licensing) JWT cache, machine cap, cancellation
669
- - [Troubleshooting](https://reportforge.org/docs/troubleshooting) common issues and debug flags
670
- - **Changelog** [CHANGELOG.md](./CHANGELOG.md)
660
+ - [Quick start](https://reportforge.org/docs/quickstart): install, configure, activate
661
+ - [Chrome setup](https://reportforge.org/docs/running-tests#chrome-setup): Windows, Linux, macOS
662
+ - [CI/CD integration](https://reportforge.org/docs/ci-cd): GitHub Actions, GitLab CI, Bitbucket Pipelines, Jenkins, Azure DevOps
663
+ - [Configuration reference](https://reportforge.org/docs/configuration): all options
664
+ - [Filename tokens](https://reportforge.org/docs/configuration#tokens): `{date}`, `{branch}`, `{status}`
665
+ - [Templates](https://reportforge.org/docs/templates): minimal, detailed, executive
666
+ - [Live runs](https://reportforge.org/docs/advanced/live): stream per-test progress to a shared watch link
667
+ - [Report Sections](https://reportforge.org/docs/configuration#report-sections): add or remove sections per template
668
+ - [License & offline behaviour](https://reportforge.org/docs/licensing): JWT cache, machine cap, cancellation
669
+ - [Troubleshooting](https://reportforge.org/docs/troubleshooting): common issues and debug flags
670
+ - **Changelog**: [CHANGELOG.md](./CHANGELOG.md)
671
671
 
672
672
  ---
673
673
 
@@ -677,4 +677,4 @@ Questions and bug reports: email [support@reportforge.org](mailto:support@report
677
677
 
678
678
  ## License
679
679
 
680
- MIT see [LICENSE](./LICENSE).
680
+ MIT. See [LICENSE](./LICENSE).
package/dist/index.js CHANGED
@@ -14001,7 +14001,7 @@ var PdfReporter = class {
14001
14001
  this.liveConsole = false;
14002
14002
  this.options = parseOptions(rawOptions);
14003
14003
  this.dataCollector = new DataCollector(this.options.capture);
14004
- const version = true ? "0.13.0" : "0.x";
14004
+ const version = true ? "0.13.1" : "0.x";
14005
14005
  logger.info(`@reportforge/playwright-pdf v${version} initialised`);
14006
14006
  this.licenseClient = new LicenseClient({
14007
14007
  licenseKey: this.options.licenseKey,
package/dist/index.mjs CHANGED
@@ -14002,7 +14002,7 @@ var PdfReporter = class {
14002
14002
  this.liveConsole = false;
14003
14003
  this.options = parseOptions(rawOptions);
14004
14004
  this.dataCollector = new DataCollector(this.options.capture);
14005
- const version = true ? "0.13.0" : "0.x";
14005
+ const version = true ? "0.13.1" : "0.x";
14006
14006
  logger.info(`@reportforge/playwright-pdf v${version} initialised`);
14007
14007
  this.licenseClient = new LicenseClient({
14008
14008
  licenseKey: this.options.licenseKey,
package/package.json CHANGED
@@ -1,15 +1,21 @@
1
1
  {
2
2
  "name": "@reportforge/playwright-pdf",
3
- "version": "0.13.0",
4
- "description": "Enterprise-ready PDF reports for Playwright Test minimal, detailed, and executive templates with CI/CD integrations",
3
+ "version": "0.13.1",
4
+ "description": "Playwright Test reporter that generates designed PDF reports: minimal, detailed, and executive templates with CI/CD integrations",
5
5
  "license": "MIT",
6
6
  "author": "ReportForge",
7
+ "homepage": "https://reportforge.org",
7
8
  "repository": {
8
9
  "type": "git",
9
10
  "url": "https://github.com/muralidharan92/reportforge"
10
11
  },
12
+ "bugs": {
13
+ "url": "https://github.com/muralidharan92/reportforge/issues",
14
+ "email": "support@reportforge.org"
15
+ },
11
16
  "keywords": [
12
17
  "playwright",
18
+ "playwright-test",
13
19
  "playwright-reporter",
14
20
  "playwright-pdf",
15
21
  "playwright-report",
@@ -17,6 +23,9 @@
17
23
  "reporter",
18
24
  "test-report",
19
25
  "test-results",
26
+ "test-automation",
27
+ "e2e",
28
+ "qa",
20
29
  "pdf-report",
21
30
  "pdf-generator",
22
31
  "ci",