@reportforge/playwright-pdf 0.16.1 → 0.18.0
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 +20 -1
- package/README.md +11 -8
- package/SECURITY.md +50 -0
- package/dist/index.d.mts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +46 -6
- package/dist/index.mjs +46 -6
- package/package.json +16 -16
package/CHANGELOG.md
CHANGED
|
@@ -3,11 +3,30 @@
|
|
|
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.18.0] - 2026-07-11
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- **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.
|
|
11
|
+
- `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.
|
|
12
|
+
- Internal dependency updates: `sharp` 0.35 (which requires Node 20), and `@types/node` 26.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## [0.17.0] - 2026-07-09
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- **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.
|
|
21
|
+
- **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.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
6
25
|
## [0.16.1] - 2026-07-09
|
|
7
26
|
|
|
8
27
|
### Changed
|
|
9
28
|
|
|
10
|
-
- **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`).
|
|
29
|
+
- **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`).
|
|
11
30
|
|
|
12
31
|
---
|
|
13
32
|
|
package/README.md
CHANGED
|
@@ -47,7 +47,7 @@ Three templates, one reporter. Every PDF is fully offline: fonts, charts, and sc
|
|
|
47
47
|
|
|
48
48
|
- **3 templates**: `minimal` (developer), `detailed` (QA team), `executive` (stakeholders)
|
|
49
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); every suite gets its own bar
|
|
50
|
+
- **Embedded Chart.js**: pass-rate doughnut + per-suite bar chart, bundled inline (no CDN); every suite gets its own bar, and large runs switch to full-width suite charts that continue across pages, so per-suite coverage and failures stay visible run-wide
|
|
51
51
|
- **Self-contained PDFs**: screenshots, fonts, logos all embedded; share or archive with confidence
|
|
52
52
|
- **Custom branding**: logo, primary/accent colours, watermark, PDF password encryption
|
|
53
53
|
- **Dynamic filenames**: `{date}`, `{branch}`, `{status}` tokens in the output path
|
|
@@ -63,6 +63,7 @@ Three templates, one reporter. Every PDF is fully offline: fonts, charts, and sc
|
|
|
63
63
|
- **Configurable sections**: add or remove any report section per template via `sections`.
|
|
64
64
|
- **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
|
|
65
65
|
- **Hybrid licensing**: one short key unlocks it; reports keep rendering offline via a cached JWT between refreshes
|
|
66
|
+
- **Update notice**: when a newer reporter version is published, each run ends with one info line naming it and the update command; delivered over the existing license refresh, no extra network calls
|
|
66
67
|
|
|
67
68
|
---
|
|
68
69
|
|
|
@@ -97,7 +98,7 @@ npx playwright test
|
|
|
97
98
|
|
|
98
99
|
> **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>`.
|
|
99
100
|
|
|
100
|
-
> **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.
|
|
101
|
+
> **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. When a newer reporter version exists, runs end with a one-line update notice.
|
|
101
102
|
|
|
102
103
|
---
|
|
103
104
|
|
|
@@ -157,7 +158,7 @@ reporter: [['@reportforge/playwright-pdf', {
|
|
|
157
158
|
| Plan | INR | USD | Includes |
|
|
158
159
|
|---|---|---|---|
|
|
159
160
|
| **Monthly** | **₹999 / month** | **$12 / month** | All three templates · custom branding · PDF encryption · up to 25 active machines · priority email support |
|
|
160
|
-
| **Yearly** | **₹8,499 / year** | **$99 / year** | Everything in Monthly · ~29
|
|
161
|
+
| **Yearly** | **₹8,499 / year** | **$99 / year** | Everything in Monthly · ~29-31% saving vs monthly |
|
|
161
162
|
|
|
162
163
|
Currency is auto-detected by region; toggle on the pricing page.
|
|
163
164
|
|
|
@@ -198,7 +199,7 @@ All options are the second element of the reporter tuple.
|
|
|
198
199
|
| `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. |
|
|
199
200
|
| `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. |
|
|
200
201
|
| `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. |
|
|
201
|
-
| `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
|
|
202
|
+
| `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. |
|
|
202
203
|
| `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. |
|
|
203
204
|
| `historySize` | `number` | `10` | Maximum number of test runs to keep in the history file (integer ≥ 2). Older runs are pruned on append. |
|
|
204
205
|
| `showTrend` | `boolean` | `true` | Show the pass-rate sparkline and delta badge in the `detailed` template. Set to `false` to disable history tracking entirely. |
|
|
@@ -225,7 +226,7 @@ reporter: [
|
|
|
225
226
|
enabled: true,
|
|
226
227
|
steps: 'failed', // 'none' | 'failed' | 'intent' | 'all'
|
|
227
228
|
// console: false, // stream stdout/stderr tails (off by default; see note)
|
|
228
|
-
// flushMs: 2000, // batch debounce (500
|
|
229
|
+
// flushMs: 2000, // batch debounce (500-10000)
|
|
229
230
|
},
|
|
230
231
|
}],
|
|
231
232
|
],
|
|
@@ -676,8 +677,10 @@ Full documentation at [reportforge.org/docs](https://reportforge.org/docs):
|
|
|
676
677
|
|
|
677
678
|
Questions and bug reports: email [support@reportforge.org](mailto:support@reportforge.org).
|
|
678
679
|
|
|
679
|
-
##
|
|
680
|
+
## Security
|
|
681
|
+
|
|
682
|
+
Found a vulnerability? Email [support@reportforge.org](mailto:support@reportforge.org) with a subject starting with `[SECURITY]` — please don't open a public issue. Details, scope, and response timelines are in [SECURITY.md](./SECURITY.md); machine-readable contact data is at [reportforge.org/.well-known/security.txt](https://reportforge.org/.well-known/security.txt).
|
|
680
683
|
|
|
681
|
-
|
|
684
|
+
## License
|
|
682
685
|
|
|
683
|
-
|
|
686
|
+
[Elastic License 2.0](./LICENSE). The license does not allow offering the software as a hosted service, bypassing or removing the license-key check, or stripping license or copyright notices. Generating PDF reports requires an active subscription.
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
ReportForge handles license keys, payment webhooks, and customer data. We take
|
|
4
|
+
vulnerability reports seriously and appreciate coordinated disclosure.
|
|
5
|
+
|
|
6
|
+
## Reporting a vulnerability
|
|
7
|
+
|
|
8
|
+
Email **[support@reportforge.org](mailto:support@reportforge.org)** with the
|
|
9
|
+
subject line starting with `[SECURITY]`.
|
|
10
|
+
|
|
11
|
+
Please include:
|
|
12
|
+
|
|
13
|
+
- A description of the issue and where it lives (npm package
|
|
14
|
+
`@reportforge/playwright-pdf`, the `reportforge.org` service, or both).
|
|
15
|
+
- Steps to reproduce, or a proof of concept.
|
|
16
|
+
- The version(s) affected, if known.
|
|
17
|
+
|
|
18
|
+
Please do **not** open a public GitHub issue for security reports, and do not
|
|
19
|
+
test against production customer data — a trial subscription gives you a full
|
|
20
|
+
legitimate environment to test the license flow.
|
|
21
|
+
|
|
22
|
+
## What to expect
|
|
23
|
+
|
|
24
|
+
- **Acknowledgement within 48 hours** of your report.
|
|
25
|
+
- A triage verdict (accepted / not a vulnerability / duplicate) within 7 days.
|
|
26
|
+
- If accepted: a fix or mitigation timeline, and credit in the release notes
|
|
27
|
+
if you want it. We ask for up to **90 days** of coordinated disclosure
|
|
28
|
+
before you publish details.
|
|
29
|
+
- We do not currently run a paid bounty program.
|
|
30
|
+
|
|
31
|
+
## Scope
|
|
32
|
+
|
|
33
|
+
In scope:
|
|
34
|
+
|
|
35
|
+
- The npm package `@reportforge/playwright-pdf` (report generation, license
|
|
36
|
+
client, bundled assets).
|
|
37
|
+
- The `reportforge.org` service: license API, dashboard, checkout, webhooks.
|
|
38
|
+
|
|
39
|
+
Out of scope:
|
|
40
|
+
|
|
41
|
+
- Denial of service / volumetric attacks.
|
|
42
|
+
- Reports about the 25-machine licensing cap working as documented.
|
|
43
|
+
- Vulnerabilities exclusively in third-party services we integrate
|
|
44
|
+
(Razorpay, Clerk, Vercel, Resend) — report those upstream.
|
|
45
|
+
|
|
46
|
+
## Supported versions
|
|
47
|
+
|
|
48
|
+
Only the latest published version of `@reportforge/playwright-pdf` receives
|
|
49
|
+
security fixes. Machine-readable contact data is published at
|
|
50
|
+
[`https://reportforge.org/.well-known/security.txt`](https://reportforge.org/.well-known/security.txt).
|
package/dist/index.d.mts
CHANGED
|
@@ -379,6 +379,13 @@ interface LicenseInfo {
|
|
|
379
379
|
* field was persisted — treat absence as "no extra features".
|
|
380
380
|
*/
|
|
381
381
|
features?: string[];
|
|
382
|
+
/**
|
|
383
|
+
* Latest published npm version of the reporter, as last reported by the
|
|
384
|
+
* license server (activate/refresh piggyback). Absent when the server
|
|
385
|
+
* could not reach the registry or the cache predates this field. Used
|
|
386
|
+
* only for the non-blocking run-end update notice.
|
|
387
|
+
*/
|
|
388
|
+
latestVersion?: string;
|
|
382
389
|
}
|
|
383
390
|
|
|
384
391
|
/**
|
|
@@ -417,6 +424,7 @@ interface LicenseInfo {
|
|
|
417
424
|
declare class PdfReporter implements Reporter {
|
|
418
425
|
private readonly options;
|
|
419
426
|
private readonly cwd;
|
|
427
|
+
private readonly version;
|
|
420
428
|
private readonly licenseClient;
|
|
421
429
|
private readonly dataCollector;
|
|
422
430
|
private readonly pdfGenerator;
|
package/dist/index.d.ts
CHANGED
|
@@ -379,6 +379,13 @@ interface LicenseInfo {
|
|
|
379
379
|
* field was persisted — treat absence as "no extra features".
|
|
380
380
|
*/
|
|
381
381
|
features?: string[];
|
|
382
|
+
/**
|
|
383
|
+
* Latest published npm version of the reporter, as last reported by the
|
|
384
|
+
* license server (activate/refresh piggyback). Absent when the server
|
|
385
|
+
* could not reach the registry or the cache predates this field. Used
|
|
386
|
+
* only for the non-blocking run-end update notice.
|
|
387
|
+
*/
|
|
388
|
+
latestVersion?: string;
|
|
382
389
|
}
|
|
383
390
|
|
|
384
391
|
/**
|
|
@@ -417,6 +424,7 @@ interface LicenseInfo {
|
|
|
417
424
|
declare class PdfReporter implements Reporter {
|
|
418
425
|
private readonly options;
|
|
419
426
|
private readonly cwd;
|
|
427
|
+
private readonly version;
|
|
420
428
|
private readonly licenseClient;
|
|
421
429
|
private readonly dataCollector;
|
|
422
430
|
private readonly pdfGenerator;
|
package/dist/index.js
CHANGED
|
@@ -10995,7 +10995,8 @@ var LicenseClient = class {
|
|
|
10995
10995
|
fingerprintHash: this.fingerprint.hash,
|
|
10996
10996
|
machinesUsed: result.machinesUsed,
|
|
10997
10997
|
machineLimit: result.machineLimit,
|
|
10998
|
-
features: payload.features
|
|
10998
|
+
features: payload.features,
|
|
10999
|
+
latestVersion: result.latestVersion
|
|
10999
11000
|
};
|
|
11000
11001
|
writeCache(entry);
|
|
11001
11002
|
logger.debug(`license path=${cached ? "refresh" : "activate"} response`, {
|
|
@@ -11014,7 +11015,8 @@ var LicenseClient = class {
|
|
|
11014
11015
|
expiry: new Date(payload.exp * 1e3),
|
|
11015
11016
|
machinesUsed: result.machinesUsed,
|
|
11016
11017
|
machineLimit: result.machineLimit,
|
|
11017
|
-
features: payload.features
|
|
11018
|
+
features: payload.features,
|
|
11019
|
+
latestVersion: result.latestVersion
|
|
11018
11020
|
};
|
|
11019
11021
|
} catch (err) {
|
|
11020
11022
|
const msg = err.message;
|
|
@@ -11111,13 +11113,47 @@ function toLicenseInfo(payload, cached, normalizedKey, source) {
|
|
|
11111
11113
|
// Prefer the signed `features` claim (authenticated) over the unauthenticated
|
|
11112
11114
|
// sidecar — falls back to the sidecar only for caches written before the
|
|
11113
11115
|
// payload was threaded through here.
|
|
11114
|
-
features: payload.features ?? cached.features
|
|
11116
|
+
features: payload.features ?? cached.features,
|
|
11117
|
+
latestVersion: cached.latestVersion
|
|
11115
11118
|
};
|
|
11116
11119
|
}
|
|
11117
11120
|
function normalizeUrl(url) {
|
|
11118
11121
|
return url.endsWith("/") ? url.slice(0, -1) : url;
|
|
11119
11122
|
}
|
|
11120
11123
|
|
|
11124
|
+
// src/license/update-notice.ts
|
|
11125
|
+
init_cjs_shims();
|
|
11126
|
+
|
|
11127
|
+
// src/license/version.ts
|
|
11128
|
+
init_cjs_shims();
|
|
11129
|
+
function parseTriple(v) {
|
|
11130
|
+
if (!v) return null;
|
|
11131
|
+
const m = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(v.trim());
|
|
11132
|
+
if (!m) return null;
|
|
11133
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
11134
|
+
}
|
|
11135
|
+
function isNewer(latest, current) {
|
|
11136
|
+
const l = parseTriple(latest);
|
|
11137
|
+
const c = parseTriple(current);
|
|
11138
|
+
if (!l || !c) return false;
|
|
11139
|
+
if (l[0] !== c[0]) return l[0] > c[0];
|
|
11140
|
+
if (l[1] !== c[1]) return l[1] > c[1];
|
|
11141
|
+
return l[2] > c[2];
|
|
11142
|
+
}
|
|
11143
|
+
|
|
11144
|
+
// src/license/update-notice.ts
|
|
11145
|
+
function maybePrintUpdateNotice(licenseInfo, currentVersion) {
|
|
11146
|
+
try {
|
|
11147
|
+
const latest = licenseInfo?.latestVersion;
|
|
11148
|
+
if (!latest || !isNewer(latest, currentVersion)) return;
|
|
11149
|
+
const shown = latest.replace(/[^\w.+-]/g, "");
|
|
11150
|
+
logger.info(
|
|
11151
|
+
`Update available: ${currentVersion} -> ${shown}. Run: npm i -D @reportforge/playwright-pdf@latest`
|
|
11152
|
+
);
|
|
11153
|
+
} catch {
|
|
11154
|
+
}
|
|
11155
|
+
}
|
|
11156
|
+
|
|
11121
11157
|
// src/analysis/index.ts
|
|
11122
11158
|
init_cjs_shims();
|
|
11123
11159
|
|
|
@@ -14119,8 +14155,8 @@ var PdfReporter = class {
|
|
|
14119
14155
|
this.liveConsole = false;
|
|
14120
14156
|
this.options = parseOptions(rawOptions);
|
|
14121
14157
|
this.dataCollector = new DataCollector(this.options.capture);
|
|
14122
|
-
|
|
14123
|
-
logger.info(`@reportforge/playwright-pdf v${version} initialised`);
|
|
14158
|
+
this.version = true ? "0.18.0" : "0.x";
|
|
14159
|
+
logger.info(`@reportforge/playwright-pdf v${this.version} initialised`);
|
|
14124
14160
|
this.licenseClient = new LicenseClient({
|
|
14125
14161
|
licenseKey: this.options.licenseKey,
|
|
14126
14162
|
serverUrl: this.options.serverUrl,
|
|
@@ -14193,7 +14229,10 @@ var PdfReporter = class {
|
|
|
14193
14229
|
const licenseInfo = await this.license();
|
|
14194
14230
|
if (!licenseInfo) return;
|
|
14195
14231
|
const collected = this._collectData(result);
|
|
14196
|
-
if (!collected)
|
|
14232
|
+
if (!collected) {
|
|
14233
|
+
maybePrintUpdateNotice(licenseInfo, this.version);
|
|
14234
|
+
return;
|
|
14235
|
+
}
|
|
14197
14236
|
if (this.options.showTrend && collected.stats.total > 0) {
|
|
14198
14237
|
try {
|
|
14199
14238
|
this._appendTrend(collected);
|
|
@@ -14218,6 +14257,7 @@ var PdfReporter = class {
|
|
|
14218
14257
|
const sender = new NotificationSender();
|
|
14219
14258
|
await sender.sendAll(reportData, this.options.notify, pdfPaths);
|
|
14220
14259
|
}
|
|
14260
|
+
maybePrintUpdateNotice(licenseInfo, this.version);
|
|
14221
14261
|
}
|
|
14222
14262
|
_collectData(result) {
|
|
14223
14263
|
if (this.options.shardResults && this.options.shardResults.length > 0) {
|
package/dist/index.mjs
CHANGED
|
@@ -10996,7 +10996,8 @@ var LicenseClient = class {
|
|
|
10996
10996
|
fingerprintHash: this.fingerprint.hash,
|
|
10997
10997
|
machinesUsed: result.machinesUsed,
|
|
10998
10998
|
machineLimit: result.machineLimit,
|
|
10999
|
-
features: payload.features
|
|
10999
|
+
features: payload.features,
|
|
11000
|
+
latestVersion: result.latestVersion
|
|
11000
11001
|
};
|
|
11001
11002
|
writeCache(entry);
|
|
11002
11003
|
logger.debug(`license path=${cached ? "refresh" : "activate"} response`, {
|
|
@@ -11015,7 +11016,8 @@ var LicenseClient = class {
|
|
|
11015
11016
|
expiry: new Date(payload.exp * 1e3),
|
|
11016
11017
|
machinesUsed: result.machinesUsed,
|
|
11017
11018
|
machineLimit: result.machineLimit,
|
|
11018
|
-
features: payload.features
|
|
11019
|
+
features: payload.features,
|
|
11020
|
+
latestVersion: result.latestVersion
|
|
11019
11021
|
};
|
|
11020
11022
|
} catch (err) {
|
|
11021
11023
|
const msg = err.message;
|
|
@@ -11112,13 +11114,47 @@ function toLicenseInfo(payload, cached, normalizedKey, source) {
|
|
|
11112
11114
|
// Prefer the signed `features` claim (authenticated) over the unauthenticated
|
|
11113
11115
|
// sidecar — falls back to the sidecar only for caches written before the
|
|
11114
11116
|
// payload was threaded through here.
|
|
11115
|
-
features: payload.features ?? cached.features
|
|
11117
|
+
features: payload.features ?? cached.features,
|
|
11118
|
+
latestVersion: cached.latestVersion
|
|
11116
11119
|
};
|
|
11117
11120
|
}
|
|
11118
11121
|
function normalizeUrl(url) {
|
|
11119
11122
|
return url.endsWith("/") ? url.slice(0, -1) : url;
|
|
11120
11123
|
}
|
|
11121
11124
|
|
|
11125
|
+
// src/license/update-notice.ts
|
|
11126
|
+
init_esm_shims();
|
|
11127
|
+
|
|
11128
|
+
// src/license/version.ts
|
|
11129
|
+
init_esm_shims();
|
|
11130
|
+
function parseTriple(v) {
|
|
11131
|
+
if (!v) return null;
|
|
11132
|
+
const m = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(v.trim());
|
|
11133
|
+
if (!m) return null;
|
|
11134
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
11135
|
+
}
|
|
11136
|
+
function isNewer(latest, current) {
|
|
11137
|
+
const l = parseTriple(latest);
|
|
11138
|
+
const c = parseTriple(current);
|
|
11139
|
+
if (!l || !c) return false;
|
|
11140
|
+
if (l[0] !== c[0]) return l[0] > c[0];
|
|
11141
|
+
if (l[1] !== c[1]) return l[1] > c[1];
|
|
11142
|
+
return l[2] > c[2];
|
|
11143
|
+
}
|
|
11144
|
+
|
|
11145
|
+
// src/license/update-notice.ts
|
|
11146
|
+
function maybePrintUpdateNotice(licenseInfo, currentVersion) {
|
|
11147
|
+
try {
|
|
11148
|
+
const latest = licenseInfo?.latestVersion;
|
|
11149
|
+
if (!latest || !isNewer(latest, currentVersion)) return;
|
|
11150
|
+
const shown = latest.replace(/[^\w.+-]/g, "");
|
|
11151
|
+
logger.info(
|
|
11152
|
+
`Update available: ${currentVersion} -> ${shown}. Run: npm i -D @reportforge/playwright-pdf@latest`
|
|
11153
|
+
);
|
|
11154
|
+
} catch {
|
|
11155
|
+
}
|
|
11156
|
+
}
|
|
11157
|
+
|
|
11122
11158
|
// src/analysis/index.ts
|
|
11123
11159
|
init_esm_shims();
|
|
11124
11160
|
|
|
@@ -14120,8 +14156,8 @@ var PdfReporter = class {
|
|
|
14120
14156
|
this.liveConsole = false;
|
|
14121
14157
|
this.options = parseOptions(rawOptions);
|
|
14122
14158
|
this.dataCollector = new DataCollector(this.options.capture);
|
|
14123
|
-
|
|
14124
|
-
logger.info(`@reportforge/playwright-pdf v${version} initialised`);
|
|
14159
|
+
this.version = true ? "0.18.0" : "0.x";
|
|
14160
|
+
logger.info(`@reportforge/playwright-pdf v${this.version} initialised`);
|
|
14125
14161
|
this.licenseClient = new LicenseClient({
|
|
14126
14162
|
licenseKey: this.options.licenseKey,
|
|
14127
14163
|
serverUrl: this.options.serverUrl,
|
|
@@ -14194,7 +14230,10 @@ var PdfReporter = class {
|
|
|
14194
14230
|
const licenseInfo = await this.license();
|
|
14195
14231
|
if (!licenseInfo) return;
|
|
14196
14232
|
const collected = this._collectData(result);
|
|
14197
|
-
if (!collected)
|
|
14233
|
+
if (!collected) {
|
|
14234
|
+
maybePrintUpdateNotice(licenseInfo, this.version);
|
|
14235
|
+
return;
|
|
14236
|
+
}
|
|
14198
14237
|
if (this.options.showTrend && collected.stats.total > 0) {
|
|
14199
14238
|
try {
|
|
14200
14239
|
this._appendTrend(collected);
|
|
@@ -14219,6 +14258,7 @@ var PdfReporter = class {
|
|
|
14219
14258
|
const sender = new NotificationSender();
|
|
14220
14259
|
await sender.sendAll(reportData, this.options.notify, pdfPaths);
|
|
14221
14260
|
}
|
|
14261
|
+
maybePrintUpdateNotice(licenseInfo, this.version);
|
|
14222
14262
|
}
|
|
14223
14263
|
_collectData(result) {
|
|
14224
14264
|
if (this.options.shardResults && this.options.shardResults.length > 0) {
|
package/package.json
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reportforge/playwright-pdf",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
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",
|
|
7
7
|
"homepage": "https://reportforge.org",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "https://github.com/muralidharan92/reportforge"
|
|
11
|
-
},
|
|
12
8
|
"bugs": {
|
|
13
|
-
"url": "https://github.com/muralidharan92/reportforge/issues",
|
|
14
9
|
"email": "support@reportforge.org"
|
|
15
10
|
},
|
|
16
11
|
"keywords": [
|
|
@@ -30,7 +25,11 @@
|
|
|
30
25
|
"pdf-generator",
|
|
31
26
|
"ci",
|
|
32
27
|
"puppeteer",
|
|
33
|
-
"html-to-pdf"
|
|
28
|
+
"html-to-pdf",
|
|
29
|
+
"reportforge",
|
|
30
|
+
"reportforge-playwright-pdf",
|
|
31
|
+
"report",
|
|
32
|
+
"forge"
|
|
34
33
|
],
|
|
35
34
|
"main": "./dist/index.js",
|
|
36
35
|
"module": "./dist/index.mjs",
|
|
@@ -53,7 +52,8 @@
|
|
|
53
52
|
"ci-templates",
|
|
54
53
|
"README.md",
|
|
55
54
|
"CHANGELOG.md",
|
|
56
|
-
"LICENSE"
|
|
55
|
+
"LICENSE",
|
|
56
|
+
"SECURITY.md"
|
|
57
57
|
],
|
|
58
58
|
"scripts": {
|
|
59
59
|
"prebuild": "npm run bundle-chartjs && npm run bundle-fonts && npm run bundle-pubkey && npm run bundle-model && npm run precompile-templates",
|
|
@@ -82,14 +82,14 @@
|
|
|
82
82
|
},
|
|
83
83
|
"peerDependencies": {
|
|
84
84
|
"@playwright/test": ">=1.40.0",
|
|
85
|
-
"puppeteer-core": ">=21.0.0 <
|
|
85
|
+
"puppeteer-core": ">=21.0.0 <26.0.0"
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
88
|
"chrome-finder": "^1.0.7",
|
|
89
89
|
"framer-motion": "^12.40.0",
|
|
90
90
|
"glob": "^13.0.6",
|
|
91
91
|
"handlebars": "^4.7.8",
|
|
92
|
-
"sharp": "^0.
|
|
92
|
+
"sharp": "^0.35.3",
|
|
93
93
|
"zod": "^3.23.8"
|
|
94
94
|
},
|
|
95
95
|
"devDependencies": {
|
|
@@ -98,20 +98,20 @@
|
|
|
98
98
|
"@fontsource/source-serif-pro": "^5.2.5",
|
|
99
99
|
"@playwright/test": "^1.49.0",
|
|
100
100
|
"@types/handlebars": "^4.1.0",
|
|
101
|
-
"@types/node": "^
|
|
101
|
+
"@types/node": "^26.1.1",
|
|
102
102
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
103
103
|
"@typescript-eslint/parser": "^8.0.0",
|
|
104
|
-
"@vitest/coverage-v8": "^
|
|
104
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
105
105
|
"chart.js": "^4.4.0",
|
|
106
106
|
"eslint": "^9.0.0",
|
|
107
107
|
"prettier": "^3.3.0",
|
|
108
|
-
"puppeteer-core": "^
|
|
108
|
+
"puppeteer-core": "^25.3.0",
|
|
109
109
|
"tsup": "^8.3.0",
|
|
110
110
|
"tsx": "^4.19.0",
|
|
111
|
-
"typescript": "^5.
|
|
112
|
-
"vitest": "^
|
|
111
|
+
"typescript": "^5.9.3",
|
|
112
|
+
"vitest": "^4.1.10"
|
|
113
113
|
},
|
|
114
114
|
"engines": {
|
|
115
|
-
"node": ">=
|
|
115
|
+
"node": ">=20.0.0"
|
|
116
116
|
}
|
|
117
117
|
}
|