@reportforge/playwright-pdf 0.22.0 → 0.22.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/README.md +22 -19
- package/SECURITY.md +2 -2
- package/dist/index.d.mts +8 -8
- package/dist/index.d.ts +8 -8
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -2
- package/CHANGELOG.md +0 -602
package/README.md
CHANGED
|
@@ -57,14 +57,15 @@ Three templates, one reporter. Every PDF is fully offline: fonts, charts, and sc
|
|
|
57
57
|
- **Shard merging**: combine N Playwright JSON shard reports into one PDF via `shardResults`; accepts glob patterns or explicit paths
|
|
58
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
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
|
-
- **
|
|
61
|
-
- **
|
|
60
|
+
- **Pass-rate trend**: cross-run trend chart from stored history; opt-in `remoteHistory` keeps the trend alive on ephemeral CI runners by storing aggregate numbers only (pass rate, counts, duration, verdict; no test titles or error text, and the branch name never travels in plaintext), with no extra network calls
|
|
61
|
+
- **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 with automatic updates; pin it any time. Full details at [reportforge.org/docs/advanced/failure-analysis](https://reportforge.org/docs/advanced/failure-analysis).
|
|
62
|
+
- **On-device training**: teach the classifier your team's failures without any data leaving your machine. Label locally-collected samples (`npx @reportforge/playwright-pdf label-feedback`), then `train-model` trains and cross-validates a personal layer on-device; it activates only when it measurably beats the base model on your own labeled set (`evaluate-model` shows the comparison any time). Commit the model file to your repo via `failureAnalysis.localModelPath` to share it with CI. Training data, the trained model, and evaluation are all local files; the analysis code cannot even name a network primitive (enforced by an automated source audit).
|
|
62
63
|
- `npx @reportforge/playwright-pdf export-feedback`: merges your locally-collected feedback (tokenized + redacted) into one CSV for review or moving between machines. Local file only; there is no upload.
|
|
63
64
|
- **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.
|
|
64
65
|
- **Configurable sections**: add or remove any report section per template via `sections`.
|
|
65
66
|
- **Executive report brief band**: leads with a plain-language brief (trend + root causes) and one hero pass-rate number instead of a flat KPI grid
|
|
66
|
-
- **Hybrid licensing**: one short key unlocks it; reports keep rendering offline via a cached
|
|
67
|
-
- **Update notice**: when a newer reporter version is published, each run ends with one info line naming it and the update command;
|
|
67
|
+
- **Hybrid licensing**: one short key unlocks it; reports keep rendering offline via a locally cached license between refreshes
|
|
68
|
+
- **Update notice**: when a newer reporter version is published, each run ends with one info line naming it and the update command; no extra network calls
|
|
68
69
|
|
|
69
70
|
---
|
|
70
71
|
|
|
@@ -107,14 +108,14 @@ npx playwright test
|
|
|
107
108
|
|
|
108
109
|
### Requirements
|
|
109
110
|
|
|
110
|
-
- Node.js ≥
|
|
111
|
+
- Node.js ≥ 20
|
|
111
112
|
- `@playwright/test` ≥ 1.40 (peer dependency)
|
|
112
|
-
- `puppeteer-core` ≥ 21 (peer dependency)
|
|
113
|
+
- `puppeteer-core` ≥ 21 < 26 (peer dependency)
|
|
113
114
|
- Chrome or Chromium installed on the machine
|
|
114
115
|
|
|
115
116
|
### Chrome setup
|
|
116
117
|
|
|
117
|
-
The reporter
|
|
118
|
+
The reporter locates Chrome via the `puppeteerExecutablePath` option first, then the `PUPPETEER_EXECUTABLE_PATH` environment variable, then `chrome-finder` (system Chrome), then puppeteer-core's bundled Chromium if present. Full per-OS instructions: [reportforge.org/docs/running-tests#chrome-setup](https://reportforge.org/docs/running-tests#chrome-setup).
|
|
118
119
|
|
|
119
120
|
**Windows**
|
|
120
121
|
|
|
@@ -199,13 +200,13 @@ All options are the second element of the reporter tuple.
|
|
|
199
200
|
| `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. |
|
|
200
201
|
| `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. |
|
|
201
202
|
| `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. |
|
|
202
|
-
| `failureAnalysis` | `object` | `{ enabled: true }` | Offline failure root-cause analysis (embedded
|
|
203
|
+
| `failureAnalysis` | `object` | `{ enabled: true }` | Offline failure root-cause analysis (embedded classifier; no runtime network) with on-device personalization: label collected failures, then the `train-model` CLI trains + evaluates a local layer entirely on your machine; it activates only when it beats the base model, and nothing leaves the machine. Fields: `enabled` (default `true`), `maxClusters` (default `10`), `minStrength` (`weak`\|`moderate`\|`strong`, default `weak`), `maxFailuresToAnalyse` (default `500`), `collectUnclassified` (default `true`), `collectScope` (`blind-spots`\|`all`, default `blind-spots`), `autoUpdateModel` (default `true`), `localModel` (use the gate-passed on-device model, default `true`), `localModelPath` (share a team-trained model via a repo-committed file). See the Failure Analysis docs. |
|
|
203
204
|
| `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. |
|
|
204
205
|
| `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. |
|
|
205
206
|
| `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. |
|
|
206
207
|
| `historySize` | `number` | `10` | Maximum number of test runs to keep in the history file (integer ≥ 2). Older runs are pruned on append. |
|
|
207
208
|
| `showTrend` | `boolean` | `true` | Show the pass-rate sparkline and delta badge in the `detailed` template. Set to `false` to disable history tracking entirely. |
|
|
208
|
-
| `remoteHistory` | `boolean` | `false` | Opt-in server-side trend store so the pass-rate trend survives ephemeral CI runners (the local history file is wiped with the workspace, leaving the chart stuck at one data point). One request per run
|
|
209
|
+
| `remoteHistory` | `boolean` | `false` | Opt-in server-side trend store so the pass-rate trend survives ephemeral CI runners (the local history file is wiped with the workspace, leaving the chart stuck at one data point). One small authenticated request per run carrying aggregate numbers only — no test titles, no error text, and the branch name never travels in plaintext. Falls back to the local history file on any failure. See the History docs. |
|
|
209
210
|
| `flakinessTopN` | `number` | `5` | Maximum flaky tests to show in the flakiness table (`detailed` template). Set to `0` to disable the table entirely. |
|
|
210
211
|
| `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). |
|
|
211
212
|
| `requirementTagPattern` | `string` | `'^@?[A-Z][A-Z0-9]*-\\d+$'` | Regex deciding which tags count as requirement IDs in the Requirements Traceability section (`detailed` template). Matching tags (ticket shapes like `@ODP-5328`, `REQ-001`) get the traceability matrix; everything else (`@regression`, `@sanity`) collapses into a compact tag summary instead of repeating identical rows. Set to `''` to disable the split and list every tag in the matrix. |
|
|
@@ -238,7 +239,7 @@ reporter: [
|
|
|
238
239
|
|
|
239
240
|
`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.
|
|
240
241
|
|
|
241
|
-
Sharded runs need no extra config:
|
|
242
|
+
Sharded runs need no extra config: every shard of one CI run converges on the same live view automatically. Set `RF_LIVE_RUN_ID` to override when your CI is not auto-detected.
|
|
242
243
|
|
|
243
244
|
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.
|
|
244
245
|
|
|
@@ -330,7 +331,7 @@ reporter: [['@reportforge/playwright-pdf', {
|
|
|
330
331
|
}]]
|
|
331
332
|
```
|
|
332
333
|
|
|
333
|
-
One request per run
|
|
334
|
+
One small authenticated request per run, carrying aggregate numbers only (pass rate, counts, duration, verdict; no test titles, no error text, and the branch name never travels in plaintext). The server keeps roughly the last 100 runs per project + branch, expiring after 180 days, and returns them for the chart; any failure falls back to the local file. The flakiness table stays local-only by design (it needs test titles, which never leave your machine). Bitbucket Pipelines users especially: Bitbucket caches are immutable once written, so `remoteHistory` is the practical path there.
|
|
334
335
|
|
|
335
336
|
**CI caching alternative** (keeps even aggregate numbers off the server): set `historyFile` to a project-relative path and cache it between runs:
|
|
336
337
|
|
|
@@ -439,7 +440,7 @@ reporter: [['@reportforge/playwright-pdf', {
|
|
|
439
440
|
|---|---|
|
|
440
441
|
| `coverPage` | Full-page cover: title, verdict badge, KPI stats strip, branch + commit |
|
|
441
442
|
| `analysisOneliner` | One-line failure-analysis summary banner |
|
|
442
|
-
| `releaseGate` | Ship/hold recommendation banner (APPROVED TO SHIP / HOLD) |
|
|
443
|
+
| `releaseGate` | Ship/hold recommendation banner (APPROVED TO SHIP / HOLD, or a neutral NO TESTS RAN when the run executed zero tests) |
|
|
443
444
|
| `summary` | KPI strip (total · passed · failed · timed-out · skipped · flaky), verdict, duration, pass rate, flaky callout |
|
|
444
445
|
| `charts` | Pass-rate doughnut + stacked suite-results bar |
|
|
445
446
|
| `trend` | Pass-rate trend line, run-history table, and flakiness table (rendered inside `charts`) |
|
|
@@ -450,6 +451,7 @@ reporter: [['@reportforge/playwright-pdf', {
|
|
|
450
451
|
| `failureAnalysis` | Inline per-test root-cause chip under each failed test (category + representative error + match strength, from the offline classifier) |
|
|
451
452
|
| `slowTests` | `SLOW` badge on the duration-ranked slowest tests, shown inline in the breakdown |
|
|
452
453
|
| `defectLog` | `DEF-####` numbered failure table (severity, duration) + opt-in repro detail (`capture`) |
|
|
454
|
+
| `briefBand` | Executive brief band: one plain-language sentence (trend delta + root causes) and a hero pass-rate stat |
|
|
453
455
|
|
|
454
456
|
#### Display modifiers: tune a section that's on
|
|
455
457
|
|
|
@@ -468,7 +470,7 @@ Omit `sections` entirely and each template renders exactly this (✓ = on):
|
|
|
468
470
|
| Section | minimal | detailed | executive |
|
|
469
471
|
|---|:-:|:-:|:-:|
|
|
470
472
|
| `coverPage` | – | – | ✓ |
|
|
471
|
-
| `analysisOneliner` | – | – |
|
|
473
|
+
| `analysisOneliner` | – | – | – |
|
|
472
474
|
| `releaseGate` | ✓ | ✓ | ✓ |
|
|
473
475
|
| `summary` | ✓ | ✓ | ✓ |
|
|
474
476
|
| `charts` | – | ✓ | ✓ |
|
|
@@ -480,6 +482,7 @@ Omit `sections` entirely and each template renders exactly this (✓ = on):
|
|
|
480
482
|
| `failureAnalysis` | – | ✓ | – |
|
|
481
483
|
| `slowTests` | – | ✓ | ✓ |
|
|
482
484
|
| `defectLog` | – | ✓ | – |
|
|
485
|
+
| `briefBand` | – | – | ✓ |
|
|
483
486
|
| `passRate` | ✓ | ✓ | ✓ |
|
|
484
487
|
| `fullEnvironment` | – | ✓ | – |
|
|
485
488
|
| `retries` | ✓ | ✓ | – |
|
|
@@ -622,10 +625,10 @@ stage('Playwright Tests') {
|
|
|
622
625
|
ReportForge ships a **hybrid offline-first** model:
|
|
623
626
|
|
|
624
627
|
1. Paste your `RFSU-…` key into the config once (or set `RF_LICENSE_KEY`).
|
|
625
|
-
2. On first run the reporter activates against the license server
|
|
626
|
-
3. Every subsequent run is **fully offline**: the cached
|
|
627
|
-
4.
|
|
628
|
-
5. Each subscription allows up to **25 active machines
|
|
628
|
+
2. On first run the reporter activates against the license server and caches a signed license at `~/.reportforge/license.json`.
|
|
629
|
+
3. Every subsequent run is **fully offline**: the cached license is validated on-device. No network call.
|
|
630
|
+
4. The reporter refreshes the cache automatically in the background before it expires.
|
|
631
|
+
5. Each subscription allows up to **25 active machines**. Machines that haven't run in 30 days free up automatically.
|
|
629
632
|
|
|
630
633
|
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.
|
|
631
634
|
|
|
@@ -676,7 +679,7 @@ Common issues:
|
|
|
676
679
|
- **`Chrome/Chromium not found`** → install Google Chrome Stable; don't use the Ubuntu `chromium-browser` snap.
|
|
677
680
|
- **Charts blank** → ensure `npm run bundle-chartjs` ran at build; the reporter waits up to 30s for `window.__chartsReady`.
|
|
678
681
|
- **`pdfPassword` ignored** → requires `qpdf` on `PATH` (`apt install qpdf` / `brew install qpdf` / `choco install qpdf`).
|
|
679
|
-
- **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
|
|
682
|
+
- **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 license cache all skip PDF generation.
|
|
680
683
|
|
|
681
684
|
Full guide: [reportforge.org/docs/troubleshooting](https://reportforge.org/docs/troubleshooting).
|
|
682
685
|
|
|
@@ -694,7 +697,7 @@ Full documentation at [reportforge.org/docs](https://reportforge.org/docs):
|
|
|
694
697
|
- [Templates](https://reportforge.org/docs/templates): minimal, detailed, executive
|
|
695
698
|
- [Live runs](https://reportforge.org/docs/advanced/live): stream per-test progress to a shared watch link
|
|
696
699
|
- [Report Sections](https://reportforge.org/docs/configuration#report-sections): add or remove sections per template
|
|
697
|
-
- [License & offline behaviour](https://reportforge.org/docs/licensing):
|
|
700
|
+
- [License & offline behaviour](https://reportforge.org/docs/licensing): license cache, machine cap, cancellation
|
|
698
701
|
- [Troubleshooting](https://reportforge.org/docs/troubleshooting): common issues and debug flags
|
|
699
702
|
- [Changelog](https://reportforge.org/changelog): version history and release notes
|
|
700
703
|
|
package/SECURITY.md
CHANGED
|
@@ -40,8 +40,8 @@ Out of scope:
|
|
|
40
40
|
|
|
41
41
|
- Denial of service / volumetric attacks.
|
|
42
42
|
- Reports about the 25-machine licensing cap working as documented.
|
|
43
|
-
- Vulnerabilities exclusively in third-party services we integrate
|
|
44
|
-
|
|
43
|
+
- Vulnerabilities exclusively in third-party services we integrate (for
|
|
44
|
+
example our payment provider, Razorpay) — report those upstream.
|
|
45
45
|
|
|
46
46
|
## Supported versions
|
|
47
47
|
|
package/dist/index.d.mts
CHANGED
|
@@ -202,7 +202,7 @@ interface ReporterOptions {
|
|
|
202
202
|
};
|
|
203
203
|
/**
|
|
204
204
|
* Offline failure root-cause analysis. Classifies failures into categories
|
|
205
|
-
* using an embedded
|
|
205
|
+
* using an embedded classifier model and renders a clustered breakdown in
|
|
206
206
|
* the `detailed` PDF (one-liner in `executive`). No network calls at runtime.
|
|
207
207
|
* Optionally personalizes on YOUR machine: label collected failures
|
|
208
208
|
* (`label-feedback`), then `train-model` trains + evaluates a local layer that
|
|
@@ -230,9 +230,9 @@ interface ReporterOptions {
|
|
|
230
230
|
*/
|
|
231
231
|
collectScope?: 'blind-spots' | 'all';
|
|
232
232
|
/**
|
|
233
|
-
* Auto-update the BASE classifier model
|
|
234
|
-
*
|
|
235
|
-
*
|
|
233
|
+
* Auto-update the BASE classifier model (offline-tolerant; the bundled
|
|
234
|
+
* model is always the floor; delivered models are signature-verified).
|
|
235
|
+
* Set false to pin the bundled model for reproducibility.
|
|
236
236
|
* Default: true
|
|
237
237
|
*/
|
|
238
238
|
autoUpdateModel?: boolean;
|
|
@@ -335,10 +335,10 @@ interface ReporterOptions {
|
|
|
335
335
|
/**
|
|
336
336
|
* Store the pass-rate trend on the ReportForge server so it survives
|
|
337
337
|
* ephemeral CI runners (where the local history file is wiped every run).
|
|
338
|
-
* One request per run
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
338
|
+
* One small authenticated request per run, carrying AGGREGATE NUMBERS ONLY —
|
|
339
|
+
* pass rate, counts, duration, verdict. No test titles, no error text; even
|
|
340
|
+
* the branch name never travels in plaintext. Falls back to the local
|
|
341
|
+
* history file on any failure.
|
|
342
342
|
* @default false
|
|
343
343
|
*/
|
|
344
344
|
remoteHistory?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -202,7 +202,7 @@ interface ReporterOptions {
|
|
|
202
202
|
};
|
|
203
203
|
/**
|
|
204
204
|
* Offline failure root-cause analysis. Classifies failures into categories
|
|
205
|
-
* using an embedded
|
|
205
|
+
* using an embedded classifier model and renders a clustered breakdown in
|
|
206
206
|
* the `detailed` PDF (one-liner in `executive`). No network calls at runtime.
|
|
207
207
|
* Optionally personalizes on YOUR machine: label collected failures
|
|
208
208
|
* (`label-feedback`), then `train-model` trains + evaluates a local layer that
|
|
@@ -230,9 +230,9 @@ interface ReporterOptions {
|
|
|
230
230
|
*/
|
|
231
231
|
collectScope?: 'blind-spots' | 'all';
|
|
232
232
|
/**
|
|
233
|
-
* Auto-update the BASE classifier model
|
|
234
|
-
*
|
|
235
|
-
*
|
|
233
|
+
* Auto-update the BASE classifier model (offline-tolerant; the bundled
|
|
234
|
+
* model is always the floor; delivered models are signature-verified).
|
|
235
|
+
* Set false to pin the bundled model for reproducibility.
|
|
236
236
|
* Default: true
|
|
237
237
|
*/
|
|
238
238
|
autoUpdateModel?: boolean;
|
|
@@ -335,10 +335,10 @@ interface ReporterOptions {
|
|
|
335
335
|
/**
|
|
336
336
|
* Store the pass-rate trend on the ReportForge server so it survives
|
|
337
337
|
* ephemeral CI runners (where the local history file is wiped every run).
|
|
338
|
-
* One request per run
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
338
|
+
* One small authenticated request per run, carrying AGGREGATE NUMBERS ONLY —
|
|
339
|
+
* pass rate, counts, duration, verdict. No test titles, no error text; even
|
|
340
|
+
* the branch name never travels in plaintext. Falls back to the local
|
|
341
|
+
* history file on any failure.
|
|
342
342
|
* @default false
|
|
343
343
|
*/
|
|
344
344
|
remoteHistory?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -14413,7 +14413,7 @@ var PdfReporter = class {
|
|
|
14413
14413
|
this.options = parseOptions(rawOptions);
|
|
14414
14414
|
setLogLevel(this.options.logLevel);
|
|
14415
14415
|
this.dataCollector = new DataCollector(this.options.capture);
|
|
14416
|
-
this.version = true ? "0.22.
|
|
14416
|
+
this.version = true ? "0.22.1" : "0.x";
|
|
14417
14417
|
logger.info(`@reportforge/playwright-pdf v${this.version} initialised`);
|
|
14418
14418
|
this.licenseClient = new LicenseClient({
|
|
14419
14419
|
licenseKey: this.options.licenseKey,
|
package/dist/index.mjs
CHANGED
|
@@ -14414,7 +14414,7 @@ var PdfReporter = class {
|
|
|
14414
14414
|
this.options = parseOptions(rawOptions);
|
|
14415
14415
|
setLogLevel(this.options.logLevel);
|
|
14416
14416
|
this.dataCollector = new DataCollector(this.options.capture);
|
|
14417
|
-
this.version = true ? "0.22.
|
|
14417
|
+
this.version = true ? "0.22.1" : "0.x";
|
|
14418
14418
|
logger.info(`@reportforge/playwright-pdf v${this.version} initialised`);
|
|
14419
14419
|
this.licenseClient = new LicenseClient({
|
|
14420
14420
|
licenseKey: this.options.licenseKey,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reportforge/playwright-pdf",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.1",
|
|
4
4
|
"description": "Playwright Test reporter that generates designed PDF reports: minimal, detailed, and executive templates with CI/CD integrations",
|
|
5
5
|
"license": "Elastic-2.0",
|
|
6
6
|
"author": "ReportForge",
|
|
@@ -51,7 +51,6 @@
|
|
|
51
51
|
"dist",
|
|
52
52
|
"ci-templates",
|
|
53
53
|
"README.md",
|
|
54
|
-
"CHANGELOG.md",
|
|
55
54
|
"LICENSE",
|
|
56
55
|
"SECURITY.md"
|
|
57
56
|
],
|
package/CHANGELOG.md
DELETED
|
@@ -1,602 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project will be documented in this file.
|
|
4
|
-
Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
5
|
-
|
|
6
|
-
## [0.21.0] - 2026-07-12
|
|
7
|
-
|
|
8
|
-
### Added
|
|
9
|
-
|
|
10
|
-
- **`remoteHistory` option — the pass-rate trend now survives ephemeral CI runners.** The local history file is wiped with the CI workspace, so the trend chart never accumulated past one data point. With `remoteHistory: true`, the reporter sends one request per run over the existing license connection carrying **aggregate numbers only** (pass rate, counts, duration, verdict, an opaque run id — no test titles, no error text; the branch name is sent as a hash). The server keeps the last 100 runs per project + branch and returns them for the chart. Any failure falls back to the local file. The flakiness table stays local-only by design (it needs test titles, which never leave your machine).
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## [0.20.2] - 2026-07-12
|
|
15
|
-
|
|
16
|
-
### Fixed
|
|
17
|
-
|
|
18
|
-
- **A run that executed zero tests (e.g. a `--grep` that matched nothing) no longer renders "APPROVED TO SHIP".** The release gate now shows a neutral "NO TESTS RAN" card explaining that there is nothing to assess, and the reporter prints a warning pointing at test filters. Previously an empty run produced an approval verdict over "0 of 0 tests passed · 0%".
|
|
19
|
-
- Sub-second durations are rounded — a near-empty run prints `36ms`, not `36.343000000000075ms`.
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## [0.20.1] - 2026-07-12
|
|
24
|
-
|
|
25
|
-
### Fixed
|
|
26
|
-
|
|
27
|
-
- **PDF generation no longer fails with "License JWT verification failed: JWT expired" on long runs.** The license resolved at run start (shared with live streaming) could expire mid-run — typically a token issued minutes before the subscription's billing-period end, while the subscription itself renews and stays active. The reporter now re-resolves the license at report time when less than 5 minutes of token TTL remain; the existing token-expired recovery (fresh activation) picks up the renewed period automatically. If the refresh genuinely cannot recover, the run downgrades to the normal warn-and-skip instead of a hard error.
|
|
28
|
-
|
|
29
|
-
---
|
|
30
|
-
|
|
31
|
-
## [0.20.0] - 2026-07-11
|
|
32
|
-
|
|
33
|
-
### Added
|
|
34
|
-
|
|
35
|
-
- **On-device training for failure analysis.** Label locally-collected failure samples (`npx @reportforge/playwright-pdf label-feedback`), then `train-model` trains and cross-validates (LOOCV under 50 rows, seeded stratified 5-fold above) a personal classifier layer entirely on your machine. It activates only when it measurably beats the shipped base model on your own labeled set (champion/challenger gate; the layer answers only past a confidence threshold calibrated to >=90% held-out precision, renders `strong` at >=95%). `evaluate-model` prints the base vs. base+local comparison any time without writing anything.
|
|
36
|
-
- **New `failureAnalysis` options**: `localModel` (use the gate-passed on-device model, default `true`), `localModelPath` (point at a repo-committed model file, from `train-model --out --project`, to share a team-trained layer with ephemeral CI machines; the file contains only redacted token statistics), `collectScope` (`'blind-spots' | 'all'`; `'all'` also collects confidently-classified failures so wrong-but-confident predictions can be corrected by labeling).
|
|
37
|
-
- The feedback CSV gained a `label` column (`category,margin,label,text`). Legacy 3-column files parse forever and migrate on first write. Human labels survive re-sighting of the same failure and are exempt from ring-buffer eviction. A `project.json` marker in each feedback dir powers the `--project` filter and the labeler's project display.
|
|
38
|
-
|
|
39
|
-
### Changed
|
|
40
|
-
|
|
41
|
-
- `export-feedback` output is normalized to the v2 header and reframed as "review or move your training data" (local training is now the primary consumer; there is still no upload).
|
|
42
|
-
- Classification is now a model chain: deterministic rules -> local layer (when present, gate-passed, and confident) -> base model. Per-test chip strength is resolved at the producing source; local-model margins are never compared against the base thresholds.
|
|
43
|
-
|
|
44
|
-
### Fixed
|
|
45
|
-
|
|
46
|
-
- The assertion-timeout rule also recognizes the modern Playwright call-log shape (`expect.toBeVisible with timeout 5000ms`) alongside the classic `Expect "toBeVisible"` form (found via a web error-corpus sweep).
|
|
47
|
-
|
|
48
|
-
### Security
|
|
49
|
-
|
|
50
|
-
- The no-network guarantee for failure analysis is mechanically enforced: a CI source scan fails if any analysis/training code names a network primitive (`fetch`, `node:http(s)`, sockets, HTTP clients, WebSocket, or a hardcoded URL). The docs gained a full "Data & network surface" inventory table.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## [0.19.1] - 2026-07-11
|
|
55
|
-
|
|
56
|
-
### Fixed
|
|
57
|
-
|
|
58
|
-
- **A blank browser window no longer flashes during report generation on Windows.** Chrome's new headless mode (the only mode left in Chrome 132+) briefly uncloaks a window on some Windows/GPU combinations; the PDF renderer now parks that window far off-screen. No effect on PDF output or other platforms.
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## [0.19.0] - 2026-07-11
|
|
63
|
-
|
|
64
|
-
### Added
|
|
65
|
-
|
|
66
|
-
- **New `logLevel` option** (`'silent' | 'error' | 'warn' | 'info' | 'debug'`, default `'info'`) controls how chatty the reporter's `[reportforge]` console lines are. `'debug'` prints the same diagnostics as `RF_DEBUG=1` (useful in CI where env vars are awkward to set); `'silent'` suppresses everything, including error lines. `RF_DEBUG=1` always forces debug output, overriding the option, so "set `RF_DEBUG=1` and send the log" keeps working regardless of config.
|
|
67
|
-
- **`RF_DEBUG=1` now explains previously silent failure paths**: license cache reads/writes, cached-token rejection (including exactly why the reporter re-activated instead of serving from cache), device-id persistence, Chrome discovery, and the qpdf availability probe.
|
|
68
|
-
|
|
69
|
-
### Changed
|
|
70
|
-
|
|
71
|
-
- A failed write of `~/.reportforge/device.json` now logs a warning, because it means this machine may register a new license seat on every run.
|
|
72
|
-
- The live watch URL is printed once instead of twice; the banner link line now carries the `[reportforge]` prefix so it stays greppable in CI logs.
|
|
73
|
-
- CLI output prefixes are consistent: the `demo` and `export-feedback` commands use the same `[reportforge]` prefix as the reporter.
|
|
74
|
-
|
|
75
|
-
---
|
|
76
|
-
|
|
77
|
-
## [0.18.0] - 2026-07-11
|
|
78
|
-
|
|
79
|
-
### Changed
|
|
80
|
-
|
|
81
|
-
- **Node 20 is now the minimum supported version** (was Node 18). Node 18 reached end-of-life in April 2025 and no longer receives security patches, and dependencies have begun dropping support for it. If you are still on Node 18, upgrade to Node 20 or later before taking this release. CI now tests against Node 20, 22, and 24.
|
|
82
|
-
- `puppeteer-core` is now supported up to v25 (peer range widened to `>=21 <26`). Existing v21 to v24 installs keep working, so no action is needed unless you want to upgrade.
|
|
83
|
-
- Internal dependency updates: `sharp` 0.35 (which requires Node 20), and `@types/node` 26.
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## [0.17.0] - 2026-07-09
|
|
88
|
-
|
|
89
|
-
### Added
|
|
90
|
-
|
|
91
|
-
- **The reporter now tells you when a newer version is available.** Each run ends with one info line naming the current and latest version and the update command, e.g. `Update available: 0.16.1 -> 0.17.0. Run: npm i -D @reportforge/playwright-pdf@latest`. The latest published version is piggybacked on the existing license activate/refresh call, so there are no extra network calls; the notice never blocks or fails a run and disappears once you update.
|
|
92
|
-
- **Admins can send release announcement emails.** A new `/admin/announce` panel builds the email body from the changelog entry for a chosen version and sends it to a selected audience (active subscribers, all subscribers, or active plus recently churned within 90 days), with a preview step and idempotency protection against duplicate sends.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## [0.16.1] - 2026-07-09
|
|
97
|
-
|
|
98
|
-
### Changed
|
|
99
|
-
|
|
100
|
-
- **Relicensed from MIT to the Elastic License 2.0** (source-available). The source stays readable, copyable, and modifiable; the license does not allow offering the software as a hosted service, bypassing or removing the license-key check, or stripping license/copyright notices. Surfaces updated together: `LICENSE`, `package.json` license metadata, README badge + License section, docs badge, marketing footer, pricing FAQ, and legal terms (§2 License grant, §7 IP, `lastUpdated`).
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## [0.16.0] - 2026-07-07
|
|
105
|
-
|
|
106
|
-
### Added
|
|
107
|
-
|
|
108
|
-
- **Every suite now gets its own bar in the Suite Results chart.** Runs with more than 10 suites switch from the compact side-by-side canvas to full-width charts (about 45 suites per page-sized canvas, "continued" across pages, declaration order preserved) — a run-wide per-suite coverage map instead of a silently truncated top-10. The Pass Rate doughnut takes the freed slot at 230px. A 150-suite safety ceiling (failures kept first, remainder summarised in a "+ N more suites" note under the chart) guards pathological runs only. Applies to every template that renders the charts section.
|
|
109
|
-
- **Per-suite totals on the bar chart**: each bar ends with its muted test count, so counts read directly instead of via gridlines.
|
|
110
|
-
|
|
111
|
-
### Changed
|
|
112
|
-
|
|
113
|
-
- **Chart polish**: the pass-rate doughnut renders as a gauge (thicker ring, rounded and gapped segments), legends use colour dots, bars have rounded caps, and suite labels went from 9px to 10px with taller rows.
|
|
114
|
-
|
|
115
|
-
### Fixed
|
|
116
|
-
|
|
117
|
-
- **Chart axis labels no longer clip their first character.** Chart.js measured tick labels before the report's embedded Inter font finished loading and painted them after, so wide-glyph labels overflowed their measured gutter. Charts now initialise after `document.fonts.ready`, making measurement match paint exactly.
|
|
118
|
-
- **X-axis no longer draws one tick per test** on suites with large test counts (`stepSize: 1` replaced with auto steps capped at 12, integers only).
|
|
119
|
-
- `timedOut` counts are now carried through the suite-chart data type and the demo fixture's suite entries.
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## [0.15.1] - 2026-07-07
|
|
124
|
-
|
|
125
|
-
### Changed
|
|
126
|
-
|
|
127
|
-
- **Release Recommendation copy is dash-free and data-driven.** The banner verdict reads `HOLD: N FAILURES` and the detail line now carries the per-run root-cause tally from failure analysis, e.g. "3 of 21 tests failed (2 assertion, 1 timeout). Each failure may be a product defect or an automation script issue. Review and verify manually before shipping." Falls back to the plain count when analysis is off; `flaky-by-retry` is excluded from the tally (flaky tests keep their own suffix). Timed-out variant matches.
|
|
128
|
-
|
|
129
|
-
---
|
|
130
|
-
|
|
131
|
-
## [0.15.0] - 2026-07-07
|
|
132
|
-
|
|
133
|
-
### Changed
|
|
134
|
-
|
|
135
|
-
- **Suite Breakdown now always opens on a fresh page** in every template (`minimal`, `detailed`, `executive`), instead of starting mid-page after whatever section precedes it.
|
|
136
|
-
- **Watermark now stamps from the Suite Breakdown page to the end of the report.** The cover, summary, and chart pages stay clean — a diagonal stamp behind the doughnut/trend charts hurt readability on exactly the pages built to be glanced at. The copies anchor inside the suite-breakdown section (its forced page break makes the section's top edge an exact page boundary), so every copy stays page-centred without estimating print pagination; custom templates and `sections` overrides without that section fall back to whole-document stamping. Also fixes a latent overshoot where the page-count pad could paint a blank trailing page containing only a watermark.
|
|
137
|
-
- **Watermark opacity raised from 4% to 10%** — visible as a stamp rather than barely-there, still light enough to keep text underneath legible.
|
|
138
|
-
- **Release Recommendation no longer says "fix before shipping."** A failure isn't necessarily a product defect, so the HOLD banner now reads: "Review each failure — it may be a product defect or an automation script issue — and verify manually before shipping." The timed-out variant matches ("often an environment or automation issue").
|
|
139
|
-
|
|
140
|
-
---
|
|
141
|
-
|
|
142
|
-
## [0.14.3] - 2026-07-06
|
|
143
|
-
|
|
144
|
-
### Fixed
|
|
145
|
-
|
|
146
|
-
- **Watermark now shows on every page instead of only one.** Chromium's print-to-PDF doesn't repeat `position: fixed` elements per page (only paged-media renderers like Prince/WeasyPrint do), so a single watermark div only ever printed once for the whole document. An inline script now measures the rendered page height and stamps one `position: absolute` copy per page. Also changed from `z-index: -1` to painting above content — at 4% opacity it doesn't affect legibility, and the negative z-index made it invisible on any page dense enough to have no background gaps.
|
|
147
|
-
- **Executive report now leads with the pass-rate/suite-results charts, trend chart second.** Previously the trend chart was promoted above the doughnut/bar row; both now render in the same order as the other templates, landing on the same page as the summary stats.
|
|
148
|
-
|
|
149
|
-
---
|
|
150
|
-
|
|
151
|
-
## [0.14.2] - 2026-07-06
|
|
152
|
-
|
|
153
|
-
### Fixed
|
|
154
|
-
|
|
155
|
-
- **Pass-rate doughnut and suite-results bar charts no longer render flush-left inside their card.** `canvas` computes to `display: block` in Chromium, so `.chart-card`'s `text-align: center` (which only centers inline-level boxes) never centered it — most visible on the executive template's wide secondary chart row. `.chart-card canvas` now centers with explicit `margin: 0 auto`.
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
## [0.14.1] - 2026-07-06
|
|
160
|
-
|
|
161
|
-
### Fixed
|
|
162
|
-
|
|
163
|
-
- **Executive report's pass-rate doughnut centre text no longer overlaps the ring.** The `executive` template renders the doughnut at 150px (vs 186px on `detailed`/`minimal`), but the centre-text plugin drew a fixed 28px/9px label sized for the larger canvas. Text now scales off the doughnut's actual inner radius, so it fits cleanly at any canvas size.
|
|
164
|
-
|
|
165
|
-
---
|
|
166
|
-
|
|
167
|
-
## [0.14.0] - 2026-07-06
|
|
168
|
-
|
|
169
|
-
### Added
|
|
170
|
-
|
|
171
|
-
- **Executive report leads with a plain-language brief and a hero pass-rate stat**: a new tinted brief band composes the trend delta and root-cause tally into one sentence (e.g. "Pass rate climbed 4 points to 92%... 3 root causes remain: 2 assertion, 1 timeout"), replacing the 6-card KPI grid with a single hero pass-rate number and a compact secondary stat row. The trend chart is promoted above the smaller pass-rate/suite-results charts. `detailed` and `minimal` templates are unchanged.
|
|
172
|
-
- **New `sections.briefBand` option** to toggle the brief band on any template (on by default for `executive`).
|
|
173
|
-
|
|
174
|
-
### Fixed
|
|
175
|
-
|
|
176
|
-
- **Flaky doughnut slice now matches the `--flaky` design token** instead of a stray hardcoded color.
|
|
177
|
-
- **`minimal` template's header no longer uses a side-stripe border**, now consistent with the design system's top-accent-bar convention used everywhere else.
|
|
178
|
-
|
|
179
|
-
---
|
|
180
|
-
|
|
181
|
-
## [0.13.2] - 2026-07-04
|
|
182
|
-
|
|
183
|
-
### Fixed
|
|
184
|
-
|
|
185
|
-
- **License refresh no longer wipes a valid cache on rate-limit**: an HTTP 429/408 from the license server was misclassified as a denial, clearing a still-valid cached license and skipping PDF generation. Now treated as transient — falls back to the cache.
|
|
186
|
-
- **`pdfPassword` encryption now actually works**: a malformed qpdf command meant every password-protected PDF shipped unencrypted while the run reported success. qpdf failures are now fatal instead of silent, and the password is no longer passed via process arguments.
|
|
187
|
-
- **`test.fail()` expected failures no longer miscounted**: an expected failure was counted as a failure in the KPI stats and failure list even though the suite tree correctly showed it as passed.
|
|
188
|
-
- **Sharded runs: describe blocks split across shards now merge correctly** instead of rendering as duplicate, half-populated nodes.
|
|
189
|
-
- **Sharded runs: failure severity now reflects tags/annotations** instead of always showing "medium".
|
|
190
|
-
- **Custom templates sharing a basename no longer overwrite each other's output.**
|
|
191
|
-
- **PDF size-cap retuning now actually reduces the inline failure count** when the report has fewer real failures than the configured cap.
|
|
192
|
-
|
|
193
|
-
---
|
|
194
|
-
|
|
195
|
-
## [0.13.1] - 2026-07-03
|
|
196
|
-
|
|
197
|
-
### Changed
|
|
198
|
-
|
|
199
|
-
- **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.
|
|
200
|
-
|
|
201
|
-
---
|
|
202
|
-
|
|
203
|
-
## [0.6.3] - 2026-06-27
|
|
204
|
-
|
|
205
|
-
### Fixed
|
|
206
|
-
|
|
207
|
-
- **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.
|
|
208
|
-
|
|
209
|
-
### Changed
|
|
210
|
-
|
|
211
|
-
- **CLI is now subcommand-based.** The `reportforge-demo` and `reportforge-export-feedback` bins are consolidated into one `playwright-pdf` bin with subcommands:
|
|
212
|
-
- `npx @reportforge/playwright-pdf demo [--template=minimal|detailed|executive] [--output=<path>]`
|
|
213
|
-
- `npx @reportforge/playwright-pdf export-feedback`
|
|
214
|
-
- This is breaking **only** if you relied on the old `reportforge-demo` / `reportforge-export-feedback` names on your `PATH` after a global install; the `npx` invocations gain capability and lose none.
|
|
215
|
-
|
|
216
|
-
---
|
|
217
|
-
|
|
218
|
-
## [0.6.2] - 2026-06-23
|
|
219
|
-
|
|
220
|
-
### Fixed
|
|
221
|
-
|
|
222
|
-
- **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).
|
|
223
|
-
- **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".
|
|
224
|
-
- **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).
|
|
225
|
-
- **Executive analysis one-liner ordering**: the one-line summary sits below the header instead of orphaning at the top of page 2.
|
|
226
|
-
- **Retry attempts are 1-based**: the retry history reads `#1`, `#2`… instead of a zero-based `#0`.
|
|
227
|
-
- **Zero-count suite pill hidden**: the "passed" pill no longer renders when its count is 0.
|
|
228
|
-
- **Suite-bar labels stop clipping**: long suite / describe labels are truncated and the axis gutter widened.
|
|
229
|
-
- **Consistent footer copy** across all three templates.
|
|
230
|
-
|
|
231
|
-
---
|
|
232
|
-
|
|
233
|
-
## [0.6.1] - 2026-06-22
|
|
234
|
-
|
|
235
|
-
### Documentation
|
|
236
|
-
|
|
237
|
-
- **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.
|
|
238
|
-
- Fixed the README documentation links to point at the real `/docs/<page>` routes instead of non-existent `/docs#<anchor>` anchors.
|
|
239
|
-
|
|
240
|
-
_No runtime changes: `@reportforge/playwright-pdf@0.6.1` is identical in behaviour to `0.6.0`._
|
|
241
|
-
|
|
242
|
-
---
|
|
243
|
-
|
|
244
|
-
## [0.6.0] - 2026-06-22
|
|
245
|
-
|
|
246
|
-
### Added
|
|
247
|
-
|
|
248
|
-
- **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.
|
|
249
|
-
|
|
250
|
-
### Changed
|
|
251
|
-
|
|
252
|
-
- Shared section styles (cover page, charts, defect log, coverage bars, environment table, failure analysis, suite breakdown) moved to the base stylesheet, so a section toggled into a template that didn't ship it before now renders fully styled.
|
|
253
|
-
|
|
254
|
-
---
|
|
255
|
-
|
|
256
|
-
## [0.5.1] - 2026-06-19
|
|
257
|
-
|
|
258
|
-
### Security
|
|
259
|
-
|
|
260
|
-
- **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).
|
|
261
|
-
|
|
262
|
-
### Changed
|
|
263
|
-
|
|
264
|
-
- **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).
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
## [0.5.0] - 2026-06-19
|
|
269
|
-
|
|
270
|
-
### Added
|
|
271
|
-
|
|
272
|
-
- **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".
|
|
273
|
-
- **Release gate on every template**: the ship/hold verdict banner now appears in `minimal` and `detailed`, not just `executive`.
|
|
274
|
-
- **Severity-ranked failures**: failure cards are colour-coded and ordered critical-first (also drives defect-log numbering and sidecar-overflow priority).
|
|
275
|
-
- **Describe-block Suite Results**: a single-file run breaks down by describe block instead of rendering one bar.
|
|
276
|
-
- **Threshold-coloured requirements coverage bars**: red `<50%`, amber `<80%`, green `≥80%`.
|
|
277
|
-
|
|
278
|
-
### Changed
|
|
279
|
-
|
|
280
|
-
- **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.
|
|
281
|
-
- The pass-rate verdict renders "TIMED OUT" instead of "TIMEDOUT".
|
|
282
|
-
|
|
283
|
-
### Fixed
|
|
284
|
-
|
|
285
|
-
- **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.
|
|
286
|
-
- The pass-rate doughnut centre now matches the KPI strip (single source of truth) rather than computing a second, divergent figure.
|
|
287
|
-
- 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.
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
## [0.4.0] - 2026-06-12
|
|
292
|
-
|
|
293
|
-
### Added
|
|
294
|
-
|
|
295
|
-
- **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`.
|
|
296
|
-
|
|
297
|
-
---
|
|
298
|
-
|
|
299
|
-
## [0.3.1] - 2026-06-09
|
|
300
|
-
|
|
301
|
-
### Security
|
|
302
|
-
|
|
303
|
-
- **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.
|
|
304
|
-
- **`DEMO_LICENSE_INFO` no longer exported**: the demo fixture constant is now module-private; not accessible via deep import from the published package.
|
|
305
|
-
- **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.
|
|
306
|
-
|
|
307
|
-
---
|
|
308
|
-
|
|
309
|
-
## [0.3.0] - 2026-06-08
|
|
310
|
-
|
|
311
|
-
### Added
|
|
312
|
-
|
|
313
|
-
- **`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.
|
|
314
|
-
- **`reportforge-demo` bin wired in `package.json`**: available immediately after `npm install`; no global install required via `npx`.
|
|
315
|
-
|
|
316
|
-
### Changed
|
|
317
|
-
|
|
318
|
-
- `src/collector/stats-utils.ts` (new): `statsFromTests` and `aggregateStats` extracted from `SuiteWalker` and `ShardMerger` to a shared utility; eliminates 3-way duplication.
|
|
319
|
-
- GitHub Actions pinned to commit SHAs (supply-chain hardening).
|
|
320
|
-
|
|
321
|
-
---
|
|
322
|
-
|
|
323
|
-
## [0.0.1] - 2026-05-26
|
|
324
|
-
|
|
325
|
-
### Changed
|
|
326
|
-
|
|
327
|
-
- **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:
|
|
328
|
-
- `npm install @reportforge/playwright-pdf puppeteer-core`
|
|
329
|
-
- `reporter: [['@reportforge/playwright-pdf', { /* opts */ }]]`
|
|
330
|
-
- `import { defineReporterConfig } from '@reportforge/playwright-pdf'`
|
|
331
|
-
|
|
332
|
-
---
|
|
333
|
-
|
|
334
|
-
> **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]`.
|
|
335
|
-
|
|
336
|
-
## [1.4.3] - 2026-05-14
|
|
337
|
-
|
|
338
|
-
### Fixed
|
|
339
|
-
|
|
340
|
-
- **Build scripts path regression.** All four `scripts/build/` bundlers (`bundle-chartjs`, `bundle-fonts`, `bundle-license-pubkey`, `precompile-templates`) resolved paths one directory too shallow after being moved from `scripts/` to `scripts/build/` in v1.4.2, breaking integration tests and the full build. Fixed `__dirname`-relative paths to correctly anchor to the repo root.
|
|
341
|
-
- **PDF encryption password no longer visible in process argv.** The `pdfPassword` option now passes the encryption key to `qpdf` via a `--password-file` temp file (mode `0600`, deleted immediately after use) rather than as a positional command-line argument. Prevents the password appearing in `/proc/PID/cmdline` or `ps` output on shared runners. Requires `qpdf >= 10.2.0`.
|
|
342
|
-
|
|
343
|
-
### Changed
|
|
344
|
-
|
|
345
|
-
- **`LicenseClient` internals refactored**: `resolve()` decomposed into `_validateKey`, `_readCache`, and `_offlineFallback` helpers for clarity; no behaviour change.
|
|
346
|
-
- **`PdfReporter.onEnd()` refactored**: extracted `_collectData`, `_appendTrend`, and `_buildReportData` methods; history write failures now logged as warnings instead of propagating.
|
|
347
|
-
- **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.
|
|
348
|
-
- **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`.
|
|
349
|
-
|
|
350
|
-
## [1.4.2] - 2026-05-13
|
|
351
|
-
|
|
352
|
-
### Changed
|
|
353
|
-
|
|
354
|
-
- **Detailed template: trend chart redesign.** Replaced the two disconnected, unlabelled sparklines (pass-rate + duration) with a single, properly designed trend card:
|
|
355
|
-
- 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.
|
|
356
|
-
- Visible x-axis (formatted date labels) and y-axis (% gridlines with tick values).
|
|
357
|
-
- Data points colored by verdict (green = passed, orange = partial, red = failed).
|
|
358
|
-
- Inline data labels rendering the pass-rate % above each point.
|
|
359
|
-
- Gradient fill under the line.
|
|
360
|
-
- Run history table below the chart (date · colored pass-rate · test count · duration) replacing the meaningless colored-dot row.
|
|
361
|
-
- Delta badge ("↑ 2% vs previous run") in the card header.
|
|
362
|
-
- **`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.
|
|
363
|
-
|
|
364
|
-
## [1.4.1] - 2026-05-13
|
|
365
|
-
|
|
366
|
-
### Changed
|
|
367
|
-
|
|
368
|
-
- **Docs: corrected USD pricing** (`$19/month` → `$12/month` and `$149/year` → `$99/year`) in README and CHANGELOG. No code change.
|
|
369
|
-
- **Docs: added CHANGELOG entry for v1.3.0** (test history trending) which was shipped but not recorded.
|
|
370
|
-
|
|
371
|
-
## [1.4.0] - 2026-05-10
|
|
372
|
-
|
|
373
|
-
### Changed
|
|
374
|
-
|
|
375
|
-
- **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.
|
|
376
|
-
|
|
377
|
-
- **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.
|
|
378
|
-
|
|
379
|
-
- **Atomic JWT cache write.** The license cache at `~/.reportforge/license.json` is now written via a temporary file + atomic rename, preventing cache corruption when multiple Playwright workers run in parallel.
|
|
380
|
-
|
|
381
|
-
### Fixed
|
|
382
|
-
|
|
383
|
-
- **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.
|
|
384
|
-
|
|
385
|
-
- **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.
|
|
386
|
-
|
|
387
|
-
## [1.3.0] - 2026-05-09
|
|
388
|
-
|
|
389
|
-
### Added
|
|
390
|
-
- **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.
|
|
391
|
-
```ts
|
|
392
|
-
reporter: [['pdf-report-forge', {
|
|
393
|
-
template: 'detailed',
|
|
394
|
-
historyFile: '.reportforge/history.json',
|
|
395
|
-
historySize: 10,
|
|
396
|
-
}]]
|
|
397
|
-
```
|
|
398
|
-
The history file is local; it is never sent to the licensing server.
|
|
399
|
-
|
|
400
|
-
## [1.2.16] - 2026-05-02
|
|
401
|
-
|
|
402
|
-
### Added
|
|
403
|
-
- **Webhook notifications**: post pass/fail summaries to Slack, Teams, or Discord after each run.
|
|
404
|
-
Configure per channel with `url`, `enabled: true`, and `on: 'always' | 'failure' | 'success'`.
|
|
405
|
-
```ts
|
|
406
|
-
notify: {
|
|
407
|
-
slack: { url: process.env.SLACK_WEBHOOK_URL, enabled: true, on: 'failure' },
|
|
408
|
-
}
|
|
409
|
-
```
|
|
410
|
-
Notifications fire after PDF generation (even if PDF fails). Requires a valid license.
|
|
411
|
-
|
|
412
|
-
## [1.2.15] - 2026-05-01
|
|
413
|
-
|
|
414
|
-
### Added
|
|
415
|
-
- **Shard merging**: configure `shardResults` in the reporter options with paths or glob patterns
|
|
416
|
-
pointing at Playwright JSON shard files to produce a single merged PDF covering all shards.
|
|
417
|
-
```ts
|
|
418
|
-
// playwright.config.ts
|
|
419
|
-
reporter: [['pdf-report-forge', { shardResults: 'results/shard-*.json' }]]
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
## [1.2.14] - 2026-05-01
|
|
423
|
-
|
|
424
|
-
### Added
|
|
425
|
-
- **`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.
|
|
426
|
-
- **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).
|
|
427
|
-
|
|
428
|
-
### Fixed
|
|
429
|
-
- **`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`.
|
|
430
|
-
|
|
431
|
-
## [1.2.13] - 2026-05-01
|
|
432
|
-
|
|
433
|
-
### Changed
|
|
434
|
-
- **README**: added `defineReporterConfig` to Quick Start example; prominent badge CTA for the free trial; license note converted to blockquote.
|
|
435
|
-
- **CHANGELOG**: backfilled entries for v1.2.4 – v1.2.12.
|
|
436
|
-
|
|
437
|
-
## [1.2.12] - 2026-05-01
|
|
438
|
-
|
|
439
|
-
### Fixed
|
|
440
|
-
- **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.
|
|
441
|
-
|
|
442
|
-
## [1.2.11] - 2026-05-01
|
|
443
|
-
|
|
444
|
-
### Added
|
|
445
|
-
- **`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`.
|
|
446
|
-
|
|
447
|
-
### Fixed
|
|
448
|
-
- **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.
|
|
449
|
-
- **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.
|
|
450
|
-
|
|
451
|
-
## [1.2.10] - 2026-04-30
|
|
452
|
-
|
|
453
|
-
### Fixed
|
|
454
|
-
- **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`.
|
|
455
|
-
- **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.
|
|
456
|
-
|
|
457
|
-
## [1.2.9] - 2026-04-30
|
|
458
|
-
|
|
459
|
-
### Fixed
|
|
460
|
-
- **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.
|
|
461
|
-
- **PEM env var newlines normalised**: `\n` literal sequences in Vercel / CI env vars are expanded to real newlines before passing to `createPrivateKey`.
|
|
462
|
-
|
|
463
|
-
## [1.2.8] - 2026-04-29
|
|
464
|
-
|
|
465
|
-
### Changed
|
|
466
|
-
- 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.
|
|
467
|
-
|
|
468
|
-
## [1.2.7] - 2026-04-29
|
|
469
|
-
|
|
470
|
-
### Fixed
|
|
471
|
-
- **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.
|
|
472
|
-
|
|
473
|
-
## [1.2.6] - 2026-04-29
|
|
474
|
-
|
|
475
|
-
### Fixed
|
|
476
|
-
- **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.
|
|
477
|
-
- **Misleading "unreachable" log warning** removed from the license refresh path.
|
|
478
|
-
- **Windows libuv teardown crash (initial fix via `AbortSignal.timeout()`)**: see v1.2.7 for the definitive approach.
|
|
479
|
-
|
|
480
|
-
## [1.2.5] - 2026-04-29
|
|
481
|
-
|
|
482
|
-
### Fixed
|
|
483
|
-
- **`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.
|
|
484
|
-
|
|
485
|
-
## [1.2.4] - 2026-04-29
|
|
486
|
-
|
|
487
|
-
### Fixed
|
|
488
|
-
- **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.
|
|
489
|
-
|
|
490
|
-
## [1.2.3] - 2026-04-28
|
|
491
|
-
|
|
492
|
-
### Changed
|
|
493
|
-
- **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.
|
|
494
|
-
|
|
495
|
-
## [1.2.2] - 2026-04-28
|
|
496
|
-
|
|
497
|
-
### Fixed
|
|
498
|
-
- **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.
|
|
499
|
-
|
|
500
|
-
## [1.2.1] - 2026-04-28
|
|
501
|
-
|
|
502
|
-
### Fixed
|
|
503
|
-
- **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.
|
|
504
|
-
|
|
505
|
-
## [1.2.0] - 2026-04-28
|
|
506
|
-
|
|
507
|
-
### Added
|
|
508
|
-
- **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.
|
|
509
|
-
|
|
510
|
-
## [Unreleased]
|
|
511
|
-
|
|
512
|
-
### Changed (BREAKING)
|
|
513
|
-
- **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:
|
|
514
|
-
- `npm install pdf-report-forge puppeteer-core`
|
|
515
|
-
- `reporter: [['pdf-report-forge', { /* opts */ }]]`
|
|
516
|
-
- Log prefix changed from `[playwright-pdf-reporter]` to `[reportforge]` to match the new brand-aligned identity. Update any CI grep filters accordingly.
|
|
517
|
-
- PDF footer text changed from "Generated by playwright-pdf-reporter" to "Generated by ReportForge" across all three templates.
|
|
518
|
-
- **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.
|
|
519
|
-
- `LicenseClient.resolve()` now returns `LicenseInfo | null` (was `LicenseInfo` always); deleted `FREE_LICENSE` constant.
|
|
520
|
-
- `LicensePlan` type narrowed to `'subscription'` only (was `'free' | 'subscription'`).
|
|
521
|
-
- Deleted `FeatureGate` and the `showCommunityBadge` plumbing: every feature is available with a valid license, none with an invalid one.
|
|
522
|
-
- 4xx denial path no longer leaks the just-cleared cache through the offline fallback.
|
|
523
|
-
|
|
524
|
-
### Marketing
|
|
525
|
-
- Pricing page, homepage, and dashboards now sell a single subscription plan with a 7-day free trial. Removed all "Free forever" surfaces.
|
|
526
|
-
|
|
527
|
-
## [1.0.0] - 2026-04-21
|
|
528
|
-
|
|
529
|
-
First public release. Subscription model replaces the former one-time tiers.
|
|
530
|
-
(Note: this release still shipped a free tier on the marketing site; that was
|
|
531
|
-
removed in the unreleased breaking change above.)
|
|
532
|
-
|
|
533
|
-
### Added
|
|
534
|
-
- Subscription licensing: **$19/mo** or **$149/yr** (~35% savings), 7-day free trial with no card.
|
|
535
|
-
- 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.
|
|
536
|
-
- Automatic JWT refresh in the background when the cache has < 24h remaining.
|
|
537
|
-
- **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.
|
|
538
|
-
- Customer self-service portal (cancel, switch plan, update card) via Stripe Customer Portal.
|
|
539
|
-
- 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`.
|
|
540
|
-
- Fonts (Source Serif Pro, Inter, JetBrains Mono) bundled into the PDF; no web font fetch at render time.
|
|
541
|
-
- Bulk-run performance: 1 500-test report renders to ~0.65 MB (was ~10.4 MB).
|
|
542
|
-
|
|
543
|
-
### Changed
|
|
544
|
-
- Default `primaryColor` → `#CC785C`, `accentColor` → `#3F7D58` (matches the shipped templates).
|
|
545
|
-
- Default `maxFileSizeMb` → `8` (was `12`). The bulk-test floor now comfortably fits under the new cap after the design refresh.
|
|
546
|
-
- Pricing structure: two subscription prices (monthly / yearly) replace the former three-tier matrix.
|
|
547
|
-
- CI builds now fail hard if `LICENSE_SIGNING_PUBLIC_KEY` is unset, preventing the publish of an artifact that would silently downgrade paying customers to the free tier.
|
|
548
|
-
|
|
549
|
-
### Removed
|
|
550
|
-
- One-time license tiers Professional (`RFPR-…`, $199/yr) and Enterprise (`RFEN-…`, $999/yr).
|
|
551
|
-
- CLI generation of legacy `RFPR-`/`RFEN-` keys from `scripts/generate-license.ts`.
|
|
552
|
-
- Standalone token-management dashboard (`/dashboard/tokens`, `/api/tokens/…`); superseded by the subscription dashboard at `/dashboard`.
|
|
553
|
-
|
|
554
|
-
### Migration
|
|
555
|
-
No existing customers; clean cutover. New installs get the subscription flow.
|
|
556
|
-
|
|
557
|
-
## [0.1.0] - 2026-04-13
|
|
558
|
-
|
|
559
|
-
### Added
|
|
560
|
-
- Initial release of `pdf-report-forge`
|
|
561
|
-
- Three configurable report templates: `minimal`, `detailed`, `executive`
|
|
562
|
-
- Sections: Executive Summary + KPIs, Suite Breakdown, Failure Deep-Dive, CI/CD & Environment
|
|
563
|
-
- Embedded Chart.js charts (doughnut pass-rate, bar suite results) in `detailed` and `executive` templates
|
|
564
|
-
- Screenshot embedding: failures with screenshots are embedded inline (base64) in the PDF
|
|
565
|
-
- Requirements traceability matrix built from test tags in `detailed` template
|
|
566
|
-
- Defect log table in `detailed` template
|
|
567
|
-
- Cover page with verdict in `executive` template
|
|
568
|
-
- Custom branding: `logo`, `primaryColor`, `accentColor`
|
|
569
|
-
- Dynamic output filename tokens: `{date}`, `{branch}`, `{status}`
|
|
570
|
-
- Watermark overlay support
|
|
571
|
-
- PDF password encryption via `qpdf` integration
|
|
572
|
-
- Offline HMAC-based license key validation
|
|
573
|
-
- License tiers: Free (no key), Professional (`RFPR-`), Enterprise (`RFEN-`)
|
|
574
|
-
- CI/CD integration templates: GitHub Actions (basic + sharded), Jenkins, GitLab CI, Azure DevOps
|
|
575
|
-
- Reusable GitHub composite Action in `.github/actions/playwright-pdf-report/`
|
|
576
|
-
- Auto Chrome/Chromium discovery via `chrome-finder` + common system paths
|
|
577
|
-
- Full TypeScript support with exported types
|
|
578
|
-
|
|
579
|
-
[Unreleased]: https://github.com/muralidharan92/reportforge/compare/v1.4.1...HEAD
|
|
580
|
-
[1.4.1]: https://github.com/muralidharan92/reportforge/compare/v1.4.0...v1.4.1
|
|
581
|
-
[1.4.0]: https://github.com/muralidharan92/reportforge/compare/v1.3.0...v1.4.0
|
|
582
|
-
[1.3.0]: https://github.com/muralidharan92/reportforge/compare/v1.2.16...v1.3.0
|
|
583
|
-
[1.2.16]: https://github.com/muralidharan92/reportforge/compare/v1.2.15...v1.2.16
|
|
584
|
-
[1.2.15]: https://github.com/muralidharan92/reportforge/compare/v1.2.14...v1.2.15
|
|
585
|
-
[1.2.14]: https://github.com/muralidharan92/reportforge/compare/v1.2.13...v1.2.14
|
|
586
|
-
[1.2.13]: https://github.com/muralidharan92/reportforge/compare/v1.2.12...v1.2.13
|
|
587
|
-
[1.2.12]: https://github.com/muralidharan92/reportforge/compare/v1.2.11...v1.2.12
|
|
588
|
-
[1.2.11]: https://github.com/muralidharan92/reportforge/compare/v1.2.10...v1.2.11
|
|
589
|
-
[1.2.10]: https://github.com/muralidharan92/reportforge/compare/v1.2.9...v1.2.10
|
|
590
|
-
[1.2.9]: https://github.com/muralidharan92/reportforge/compare/v1.2.8...v1.2.9
|
|
591
|
-
[1.2.8]: https://github.com/muralidharan92/reportforge/compare/v1.2.7...v1.2.8
|
|
592
|
-
[1.2.7]: https://github.com/muralidharan92/reportforge/compare/v1.2.6...v1.2.7
|
|
593
|
-
[1.2.6]: https://github.com/muralidharan92/reportforge/compare/v1.2.5...v1.2.6
|
|
594
|
-
[1.2.5]: https://github.com/muralidharan92/reportforge/compare/v1.2.4...v1.2.5
|
|
595
|
-
[1.2.4]: https://github.com/muralidharan92/reportforge/compare/v1.2.3...v1.2.4
|
|
596
|
-
[1.2.3]: https://github.com/muralidharan92/reportforge/compare/v1.2.2...v1.2.3
|
|
597
|
-
[1.2.2]: https://github.com/muralidharan92/reportforge/compare/v1.2.1...v1.2.2
|
|
598
|
-
[1.2.1]: https://github.com/muralidharan92/reportforge/compare/v1.2.0...v1.2.1
|
|
599
|
-
[1.2.0]: https://github.com/muralidharan92/reportforge/compare/v1.1.0...v1.2.0
|
|
600
|
-
[1.1.0]: https://github.com/muralidharan92/reportforge/compare/v1.0.0...v1.1.0
|
|
601
|
-
[1.0.0]: https://github.com/muralidharan92/reportforge/releases/tag/v1.0.0
|
|
602
|
-
[0.1.0]: https://github.com/muralidharan92/reportforge/releases/tag/v0.1.0
|