@reportforge/playwright-pdf 0.4.0 → 0.4.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,6 +3,14 @@
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.4.0] — 2026-06-12
7
+
8
+ ### Added
9
+
10
+ - **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`.
11
+
12
+ ---
13
+
6
14
  ## [0.3.1] — 2026-06-09
7
15
 
8
16
  ### Security
package/README.md CHANGED
@@ -56,7 +56,7 @@ Three templates, one reporter. Every PDF is fully offline — fonts, charts, and
56
56
  - **Shard merging** — combine N Playwright JSON shard reports into one PDF via `shardResults`; accepts glob patterns or explicit paths
57
57
  - **Notifications** — post pass/fail summaries to Slack, Teams, Discord, or email after each run; configurable trigger (`always` / `failure` / `success`) per channel; email supports optional PDF attachment via `attachPdf`
58
58
  - **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)
59
- - **Offline failure analysis** — classifies failures into 7 root-cause categories, clusters them, and renders a breakdown in the `detailed` PDF (one-liner in `executive`). No network, no AI service. The classifier model auto-updates offline over the existing license-refresh channel each delivered model is Ed25519-signed and verified against the bundled public key, with the bundled model always the floor; set `failureAnalysis.autoUpdateModel: false` to pin the bundled model.
59
+ - **Offline failure analysis** — sorts failures into 7 root-cause buckets and clusters them, right inside the `detailed` PDF (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).
60
60
  - `reportforge-export-feedback` — exports locally-collected unrecognized failures (tokenized, local-only) for optional manual sharing.
61
61
  - **Hybrid licensing** — one short key unlocks it; reports keep rendering offline via a cached JWT between refreshes
62
62
 
package/dist/index.js CHANGED
@@ -11215,6 +11215,19 @@ function runFailureAnalysis(reportData, options, cwd) {
11215
11215
  // src/collector/DataCollector.ts
11216
11216
  init_cjs_shims();
11217
11217
 
11218
+ // src/utils/strip-ansi.ts
11219
+ init_cjs_shims();
11220
+ var ANSI_PATTERN = new RegExp(
11221
+ [
11222
+ "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
11223
+ "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"
11224
+ ].join("|"),
11225
+ "g"
11226
+ );
11227
+ function stripAnsi(input) {
11228
+ return input.replace(ANSI_PATTERN, "");
11229
+ }
11230
+
11218
11231
  // src/collector/SuiteWalker.ts
11219
11232
  init_cjs_shims();
11220
11233
 
@@ -11449,8 +11462,8 @@ var DataCollector = class {
11449
11462
  testTitle: test.title,
11450
11463
  suitePath,
11451
11464
  error: {
11452
- message: error.message ?? String(error),
11453
- stack: error.stack
11465
+ message: stripAnsi(error.message ?? String(error)),
11466
+ stack: error.stack ? stripAnsi(error.stack) : void 0
11454
11467
  },
11455
11468
  screenshotPath: screenshotAttachment?.path,
11456
11469
  screenshotBuffer: screenshotAttachment?.body,
@@ -11772,8 +11785,8 @@ var ShardMerger = class {
11772
11785
  testTitle: spec.title,
11773
11786
  suitePath,
11774
11787
  error: {
11775
- message: error?.message ?? "Test failed",
11776
- stack: error?.stack
11788
+ message: stripAnsi(error?.message ?? "Test failed"),
11789
+ stack: error?.stack ? stripAnsi(error.stack) : void 0
11777
11790
  },
11778
11791
  screenshotPath: lastResult?.attachments.find(
11779
11792
  (a) => a.name.toLowerCase().includes("screenshot") && a.contentType.startsWith("image/")
@@ -13055,7 +13068,7 @@ var PdfReporter = class {
13055
13068
  this.dataCollector = new DataCollector();
13056
13069
  this.pdfGenerator = new PdfGenerator();
13057
13070
  this.options = parseOptions(rawOptions);
13058
- const version = true ? "0.4.0" : "0.x";
13071
+ const version = true ? "0.4.1" : "0.x";
13059
13072
  logger.info(`@reportforge/playwright-pdf v${version} initialised`);
13060
13073
  this.licenseClient = new LicenseClient({
13061
13074
  licenseKey: this.options.licenseKey,
package/dist/index.mjs CHANGED
@@ -11216,6 +11216,19 @@ function runFailureAnalysis(reportData, options, cwd) {
11216
11216
  // src/collector/DataCollector.ts
11217
11217
  init_esm_shims();
11218
11218
 
11219
+ // src/utils/strip-ansi.ts
11220
+ init_esm_shims();
11221
+ var ANSI_PATTERN = new RegExp(
11222
+ [
11223
+ "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
11224
+ "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))"
11225
+ ].join("|"),
11226
+ "g"
11227
+ );
11228
+ function stripAnsi(input) {
11229
+ return input.replace(ANSI_PATTERN, "");
11230
+ }
11231
+
11219
11232
  // src/collector/SuiteWalker.ts
11220
11233
  init_esm_shims();
11221
11234
 
@@ -11450,8 +11463,8 @@ var DataCollector = class {
11450
11463
  testTitle: test.title,
11451
11464
  suitePath,
11452
11465
  error: {
11453
- message: error.message ?? String(error),
11454
- stack: error.stack
11466
+ message: stripAnsi(error.message ?? String(error)),
11467
+ stack: error.stack ? stripAnsi(error.stack) : void 0
11455
11468
  },
11456
11469
  screenshotPath: screenshotAttachment?.path,
11457
11470
  screenshotBuffer: screenshotAttachment?.body,
@@ -11773,8 +11786,8 @@ var ShardMerger = class {
11773
11786
  testTitle: spec.title,
11774
11787
  suitePath,
11775
11788
  error: {
11776
- message: error?.message ?? "Test failed",
11777
- stack: error?.stack
11789
+ message: stripAnsi(error?.message ?? "Test failed"),
11790
+ stack: error?.stack ? stripAnsi(error.stack) : void 0
11778
11791
  },
11779
11792
  screenshotPath: lastResult?.attachments.find(
11780
11793
  (a) => a.name.toLowerCase().includes("screenshot") && a.contentType.startsWith("image/")
@@ -13056,7 +13069,7 @@ var PdfReporter = class {
13056
13069
  this.dataCollector = new DataCollector();
13057
13070
  this.pdfGenerator = new PdfGenerator();
13058
13071
  this.options = parseOptions(rawOptions);
13059
- const version = true ? "0.4.0" : "0.x";
13072
+ const version = true ? "0.4.1" : "0.x";
13060
13073
  logger.info(`@reportforge/playwright-pdf v${version} initialised`);
13061
13074
  this.licenseClient = new LicenseClient({
13062
13075
  licenseKey: this.options.licenseKey,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reportforge/playwright-pdf",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "Enterprise-ready PDF reports for Playwright Test — minimal, detailed, and executive templates with CI/CD integrations",
5
5
  "license": "MIT",
6
6
  "author": "ReportForge",