@reportforge/playwright-pdf 0.2.1 → 0.2.2
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 +26 -23
- package/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +43 -1
- package/dist/index.mjs +43 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -165,31 +165,34 @@ Currency is auto-detected by region; toggle on the pricing page.
|
|
|
165
165
|
|
|
166
166
|
All options are the second element of the reporter tuple.
|
|
167
167
|
|
|
168
|
+
<!-- AUTOGEN:options-table START — edit scripts/docs/options-meta.ts, then run npm run docs:gen -->
|
|
168
169
|
| Option | Type | Default | Description |
|
|
169
170
|
|---|---|---|---|
|
|
170
|
-
| `
|
|
171
|
-
| `
|
|
172
|
-
| `
|
|
173
|
-
| `
|
|
174
|
-
| `
|
|
175
|
-
| `
|
|
176
|
-
| `
|
|
177
|
-
| `
|
|
178
|
-
| `
|
|
179
|
-
| `
|
|
180
|
-
| `
|
|
181
|
-
| `
|
|
182
|
-
| `
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
187
|
-
| `
|
|
188
|
-
| `
|
|
189
|
-
| `
|
|
190
|
-
| `
|
|
191
|
-
| `
|
|
192
|
-
| `
|
|
171
|
+
| `outputFile` | `string` | `'playwright-report/{date}-report.pdf'` | Output path. Supports tokens: `{date}`, `{datetime}`, `{branch}`, `{status}`, `{total}`, `{passed}`, `{failed}`, `{project}`. Directory is created if absent. |
|
|
172
|
+
| `template` | `'minimal' \| 'detailed' \| 'executive'` or array | `'minimal'` | Template(s) to generate. Pass an array to produce one PDF per template in one run — the template name is appended to each output filename automatically (e.g. `report-detailed.pdf`). |
|
|
173
|
+
| `licenseKey` | `string` | env `RF_LICENSE_KEY` | Subscription key (format `RFSU-…`). Falls back to the `RF_LICENSE_KEY` environment variable. PDF generation is skipped when absent or invalid. |
|
|
174
|
+
| `logo` | `string` | — | Path to a logo image (PNG, JPG, or SVG) to embed in the report header. Supports absolute and relative paths. |
|
|
175
|
+
| `primaryColor` | `string` | `'#CC785C'` | Primary brand colour (3-, 6-, or 8-digit hex). Used for headers and accent bars. |
|
|
176
|
+
| `accentColor` | `string` | `'#3F7D58'` | Accent brand colour (hex). Used for highlights and badges. |
|
|
177
|
+
| `watermark` | `string` | — | Text to render as a diagonal watermark overlay on every page — e.g. `'CONFIDENTIAL'`, `'DRAFT'`. |
|
|
178
|
+
| `pdfPassword` | `string` | — | Password-protect the generated PDF. Requires `qpdf` installed on the system. |
|
|
179
|
+
| `reportTitle` | `string` | `'Playwright Test Report'` | Custom title for the report cover page and running header. |
|
|
180
|
+
| `projectName` | `string` | from `package.json` | Project or application name. Inferred from the `package.json` `name` field if absent. |
|
|
181
|
+
| `open` | `boolean` | `false` | Open the generated PDF automatically after generation. For local use only — ignored in CI. |
|
|
182
|
+
| `puppeteerExecutablePath` | `string` | auto-detect | Full path to a Chrome or Chromium binary. Falls back to `PUPPETEER_EXECUTABLE_PATH` env, then system Chrome discovery. |
|
|
183
|
+
| `serverUrl` | `string` | `'https://reportforge.org'` | Base URL for the ReportForge licensing server. Override only for self-hosting or local development. |
|
|
184
|
+
| `compressionLevel` | `'auto' \| 'none' \| 'balanced' \| 'max'` | `'auto'` | Screenshot JPEG quality preset. `'auto'` picks based on failure volume; `'none'` keeps original PNGs; `'balanced'` uses JPEG q85; `'max'` uses JPEG q70. |
|
|
185
|
+
| `includeScreenshots` | `boolean` | `true` | Embed Playwright screenshots in the PDF. Set to `false` to omit images — useful for exec-audience reports or reducing file size. |
|
|
186
|
+
| `maxInlineFailures` | `number` | derived from `compressionLevel` | Cap on failure entries rendered inline in the PDF. Overflow is written to a sibling `{basename}-failures.json` sidecar file. |
|
|
187
|
+
| `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. |
|
|
188
|
+
| `shardResults` | `string \| string[]` | — | Glob or path array of Playwright JSON shard report files to merge into one PDF. See the Shard Merging docs. |
|
|
189
|
+
| `notify` | `object` | — | Notification channels: `slack`, `teams`, `discord` (each `{ url, enabled, on }`), `email` (`{ to, enabled, on, attachPdf }`). See the Notifications docs. |
|
|
190
|
+
| `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. |
|
|
191
|
+
| `historySize` | `number` | `10` | Maximum number of test runs to keep in the history file (integer ≥ 2). Older runs are pruned on append. |
|
|
192
|
+
| `showTrend` | `boolean` | `true` | Show the pass-rate sparkline and delta badge in the `detailed` template. Set to `false` to disable history tracking entirely. |
|
|
193
|
+
| `flakinessTopN` | `number` | `5` | Maximum flaky tests to show in the flakiness table (`detailed` template). Set to `0` to disable the table entirely. |
|
|
194
|
+
| `templatePath` | `string \| string[]` | — | Path to a custom Handlebars (`.hbs`) template file. Takes precedence over `template`. Pass an array to generate one PDF per custom template. See the Custom Templates docs. |
|
|
195
|
+
<!-- AUTOGEN:options-table END -->
|
|
193
196
|
|
|
194
197
|
Full reference: [reportforge.org/docs#configuration](https://reportforge.org/docs#configuration).
|
|
195
198
|
|
package/dist/index.d.mts
CHANGED
|
@@ -136,9 +136,12 @@ interface ReporterOptions {
|
|
|
136
136
|
*/
|
|
137
137
|
shardResults?: string | string[];
|
|
138
138
|
/**
|
|
139
|
-
*
|
|
139
|
+
* Notification channels. Post a pass/fail summary after each test run.
|
|
140
140
|
* Each channel must have `enabled: true` to fire (default is `false`).
|
|
141
141
|
* `on` controls the trigger: `'always'` (default), `'failure'`, or `'success'`.
|
|
142
|
+
*
|
|
143
|
+
* - `slack` / `teams` / `discord`: webhook URL channels
|
|
144
|
+
* - `email`: sends via Resend; `to` is required; `attachPdf: true` attaches the PDF
|
|
142
145
|
*/
|
|
143
146
|
notify?: {
|
|
144
147
|
slack?: {
|
|
@@ -156,6 +159,12 @@ interface ReporterOptions {
|
|
|
156
159
|
on?: 'always' | 'failure' | 'success';
|
|
157
160
|
enabled?: boolean;
|
|
158
161
|
};
|
|
162
|
+
email?: {
|
|
163
|
+
to: string[];
|
|
164
|
+
on?: 'always' | 'failure' | 'success';
|
|
165
|
+
enabled?: boolean;
|
|
166
|
+
attachPdf?: boolean;
|
|
167
|
+
};
|
|
159
168
|
};
|
|
160
169
|
/**
|
|
161
170
|
* Path to the history JSON file. Defaults to
|
package/dist/index.d.ts
CHANGED
|
@@ -136,9 +136,12 @@ interface ReporterOptions {
|
|
|
136
136
|
*/
|
|
137
137
|
shardResults?: string | string[];
|
|
138
138
|
/**
|
|
139
|
-
*
|
|
139
|
+
* Notification channels. Post a pass/fail summary after each test run.
|
|
140
140
|
* Each channel must have `enabled: true` to fire (default is `false`).
|
|
141
141
|
* `on` controls the trigger: `'always'` (default), `'failure'`, or `'success'`.
|
|
142
|
+
*
|
|
143
|
+
* - `slack` / `teams` / `discord`: webhook URL channels
|
|
144
|
+
* - `email`: sends via Resend; `to` is required; `attachPdf: true` attaches the PDF
|
|
142
145
|
*/
|
|
143
146
|
notify?: {
|
|
144
147
|
slack?: {
|
|
@@ -156,6 +159,12 @@ interface ReporterOptions {
|
|
|
156
159
|
on?: 'always' | 'failure' | 'success';
|
|
157
160
|
enabled?: boolean;
|
|
158
161
|
};
|
|
162
|
+
email?: {
|
|
163
|
+
to: string[];
|
|
164
|
+
on?: 'always' | 'failure' | 'success';
|
|
165
|
+
enabled?: boolean;
|
|
166
|
+
attachPdf?: boolean;
|
|
167
|
+
};
|
|
159
168
|
};
|
|
160
169
|
/**
|
|
161
170
|
* Path to the history JSON file. Defaults to
|
package/dist/index.js
CHANGED
|
@@ -11033,6 +11033,13 @@ var DataCollector = class {
|
|
|
11033
11033
|
if (existing >= 0) this.failureRecords.splice(existing, 1);
|
|
11034
11034
|
}
|
|
11035
11035
|
}
|
|
11036
|
+
/**
|
|
11037
|
+
* Builds the final `ReportData` payload from all accumulated hook data.
|
|
11038
|
+
*
|
|
11039
|
+
* @param fullResult - Playwright's `FullResult` (contains `duration` + `status`).
|
|
11040
|
+
* @returns Structured data for the PDF generator, including projects tree,
|
|
11041
|
+
* aggregated stats, failures, environment info, and chart inputs.
|
|
11042
|
+
*/
|
|
11036
11043
|
finalize(fullResult) {
|
|
11037
11044
|
const walker = new SuiteWalker();
|
|
11038
11045
|
const projects = walker.build(this.rootSuite, this.resultMap);
|
|
@@ -11967,6 +11974,15 @@ var import_path6 = __toESM(require("path"));
|
|
|
11967
11974
|
var import_fs9 = __toESM(require("fs"));
|
|
11968
11975
|
var MAX_BRANCH_LENGTH = 50;
|
|
11969
11976
|
var FilenameResolver = class {
|
|
11977
|
+
/**
|
|
11978
|
+
* Expands `{date}`, `{branch}`, and `{status}` tokens in `template`, then
|
|
11979
|
+
* resolves to an absolute path and creates the parent directory.
|
|
11980
|
+
*
|
|
11981
|
+
* @param template - Output path, possibly relative to `cwd` and possibly
|
|
11982
|
+
* containing `{date}`, `{branch}`, or `{status}` tokens.
|
|
11983
|
+
* @param ctx - Runtime values for token expansion.
|
|
11984
|
+
* @returns Absolute path with parent directories created.
|
|
11985
|
+
*/
|
|
11970
11986
|
resolve(template, ctx) {
|
|
11971
11987
|
const date = this.formatDate(ctx.date);
|
|
11972
11988
|
const branch = this.sanitiseBranch(ctx.branch);
|
|
@@ -11976,6 +11992,14 @@ var FilenameResolver = class {
|
|
|
11976
11992
|
import_fs9.default.mkdirSync(import_path6.default.dirname(absolute), { recursive: true });
|
|
11977
11993
|
return absolute;
|
|
11978
11994
|
}
|
|
11995
|
+
/**
|
|
11996
|
+
* Inserts `suffix` before the file extension so multi-template runs produce
|
|
11997
|
+
* unique filenames from the same base path.
|
|
11998
|
+
*
|
|
11999
|
+
* @example
|
|
12000
|
+
* injectTemplateSuffix('/out/2026-report.pdf', 'executive')
|
|
12001
|
+
* // → '/out/2026-report-executive.pdf'
|
|
12002
|
+
*/
|
|
11979
12003
|
injectTemplateSuffix(outputPath, suffix) {
|
|
11980
12004
|
const ext = import_path6.default.extname(outputPath);
|
|
11981
12005
|
const base = outputPath.slice(0, outputPath.length - ext.length);
|
|
@@ -12098,6 +12122,24 @@ var PdfGenerator = class {
|
|
|
12098
12122
|
} catch {
|
|
12099
12123
|
}
|
|
12100
12124
|
}
|
|
12125
|
+
/**
|
|
12126
|
+
* Generates one PDF per template source and returns their absolute output paths.
|
|
12127
|
+
*
|
|
12128
|
+
* Launches a single Puppeteer browser instance shared across all template
|
|
12129
|
+
* renders to avoid the 2–5 s startup cost per template. Each render pass goes
|
|
12130
|
+
* through: failure pagination → screenshot embedding → Handlebars render →
|
|
12131
|
+
* temp HTML write → `page.pdf()`.
|
|
12132
|
+
*
|
|
12133
|
+
* Size cap enforcement: if the first-pass PDF exceeds `options.maxFileSizeMb`,
|
|
12134
|
+
* compression settings are tightened (quality 55, maxWidth 800, inline cap
|
|
12135
|
+
* scaled to fit) and the PDF is re-rendered once. A second overrun warns but
|
|
12136
|
+
* is not re-rendered.
|
|
12137
|
+
*
|
|
12138
|
+
* @param data - Assembled `ReportData` (projects, stats, failures, charts).
|
|
12139
|
+
* @param options - Validated reporter options.
|
|
12140
|
+
* @param _licenseInfo - Kept for API symmetry; unused in this method.
|
|
12141
|
+
* @returns Absolute paths of written PDF files.
|
|
12142
|
+
*/
|
|
12101
12143
|
async generateAll(data, options, _licenseInfo) {
|
|
12102
12144
|
const sources = this.resolveTemplateSources(options);
|
|
12103
12145
|
const isMulti = sources.length > 1;
|
|
@@ -12628,7 +12670,7 @@ var PdfReporter = class {
|
|
|
12628
12670
|
this.dataCollector = new DataCollector();
|
|
12629
12671
|
this.pdfGenerator = new PdfGenerator();
|
|
12630
12672
|
this.options = parseOptions(rawOptions);
|
|
12631
|
-
const version = true ? "0.2.
|
|
12673
|
+
const version = true ? "0.2.2" : "0.x";
|
|
12632
12674
|
logger.info(`@reportforge/playwright-pdf v${version} initialised`);
|
|
12633
12675
|
this.licenseClient = new LicenseClient({
|
|
12634
12676
|
licenseKey: this.options.licenseKey,
|
package/dist/index.mjs
CHANGED
|
@@ -11034,6 +11034,13 @@ var DataCollector = class {
|
|
|
11034
11034
|
if (existing >= 0) this.failureRecords.splice(existing, 1);
|
|
11035
11035
|
}
|
|
11036
11036
|
}
|
|
11037
|
+
/**
|
|
11038
|
+
* Builds the final `ReportData` payload from all accumulated hook data.
|
|
11039
|
+
*
|
|
11040
|
+
* @param fullResult - Playwright's `FullResult` (contains `duration` + `status`).
|
|
11041
|
+
* @returns Structured data for the PDF generator, including projects tree,
|
|
11042
|
+
* aggregated stats, failures, environment info, and chart inputs.
|
|
11043
|
+
*/
|
|
11037
11044
|
finalize(fullResult) {
|
|
11038
11045
|
const walker = new SuiteWalker();
|
|
11039
11046
|
const projects = walker.build(this.rootSuite, this.resultMap);
|
|
@@ -11968,6 +11975,15 @@ import path7 from "path";
|
|
|
11968
11975
|
import fs8 from "fs";
|
|
11969
11976
|
var MAX_BRANCH_LENGTH = 50;
|
|
11970
11977
|
var FilenameResolver = class {
|
|
11978
|
+
/**
|
|
11979
|
+
* Expands `{date}`, `{branch}`, and `{status}` tokens in `template`, then
|
|
11980
|
+
* resolves to an absolute path and creates the parent directory.
|
|
11981
|
+
*
|
|
11982
|
+
* @param template - Output path, possibly relative to `cwd` and possibly
|
|
11983
|
+
* containing `{date}`, `{branch}`, or `{status}` tokens.
|
|
11984
|
+
* @param ctx - Runtime values for token expansion.
|
|
11985
|
+
* @returns Absolute path with parent directories created.
|
|
11986
|
+
*/
|
|
11971
11987
|
resolve(template, ctx) {
|
|
11972
11988
|
const date = this.formatDate(ctx.date);
|
|
11973
11989
|
const branch = this.sanitiseBranch(ctx.branch);
|
|
@@ -11977,6 +11993,14 @@ var FilenameResolver = class {
|
|
|
11977
11993
|
fs8.mkdirSync(path7.dirname(absolute), { recursive: true });
|
|
11978
11994
|
return absolute;
|
|
11979
11995
|
}
|
|
11996
|
+
/**
|
|
11997
|
+
* Inserts `suffix` before the file extension so multi-template runs produce
|
|
11998
|
+
* unique filenames from the same base path.
|
|
11999
|
+
*
|
|
12000
|
+
* @example
|
|
12001
|
+
* injectTemplateSuffix('/out/2026-report.pdf', 'executive')
|
|
12002
|
+
* // → '/out/2026-report-executive.pdf'
|
|
12003
|
+
*/
|
|
11980
12004
|
injectTemplateSuffix(outputPath, suffix) {
|
|
11981
12005
|
const ext = path7.extname(outputPath);
|
|
11982
12006
|
const base = outputPath.slice(0, outputPath.length - ext.length);
|
|
@@ -12099,6 +12123,24 @@ var PdfGenerator = class {
|
|
|
12099
12123
|
} catch {
|
|
12100
12124
|
}
|
|
12101
12125
|
}
|
|
12126
|
+
/**
|
|
12127
|
+
* Generates one PDF per template source and returns their absolute output paths.
|
|
12128
|
+
*
|
|
12129
|
+
* Launches a single Puppeteer browser instance shared across all template
|
|
12130
|
+
* renders to avoid the 2–5 s startup cost per template. Each render pass goes
|
|
12131
|
+
* through: failure pagination → screenshot embedding → Handlebars render →
|
|
12132
|
+
* temp HTML write → `page.pdf()`.
|
|
12133
|
+
*
|
|
12134
|
+
* Size cap enforcement: if the first-pass PDF exceeds `options.maxFileSizeMb`,
|
|
12135
|
+
* compression settings are tightened (quality 55, maxWidth 800, inline cap
|
|
12136
|
+
* scaled to fit) and the PDF is re-rendered once. A second overrun warns but
|
|
12137
|
+
* is not re-rendered.
|
|
12138
|
+
*
|
|
12139
|
+
* @param data - Assembled `ReportData` (projects, stats, failures, charts).
|
|
12140
|
+
* @param options - Validated reporter options.
|
|
12141
|
+
* @param _licenseInfo - Kept for API symmetry; unused in this method.
|
|
12142
|
+
* @returns Absolute paths of written PDF files.
|
|
12143
|
+
*/
|
|
12102
12144
|
async generateAll(data, options, _licenseInfo) {
|
|
12103
12145
|
const sources = this.resolveTemplateSources(options);
|
|
12104
12146
|
const isMulti = sources.length > 1;
|
|
@@ -12629,7 +12671,7 @@ var PdfReporter = class {
|
|
|
12629
12671
|
this.dataCollector = new DataCollector();
|
|
12630
12672
|
this.pdfGenerator = new PdfGenerator();
|
|
12631
12673
|
this.options = parseOptions(rawOptions);
|
|
12632
|
-
const version = true ? "0.2.
|
|
12674
|
+
const version = true ? "0.2.2" : "0.x";
|
|
12633
12675
|
logger.info(`@reportforge/playwright-pdf v${version} initialised`);
|
|
12634
12676
|
this.licenseClient = new LicenseClient({
|
|
12635
12677
|
licenseKey: this.options.licenseKey,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reportforge/playwright-pdf",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
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",
|
|
@@ -60,7 +60,9 @@
|
|
|
60
60
|
"typecheck": "tsc --noEmit",
|
|
61
61
|
"prepublishOnly": "npm run typecheck && npm run test && npm run build",
|
|
62
62
|
"generate-license": "tsx scripts/generate-license.ts",
|
|
63
|
-
"snapshot-png": "tsx scripts/snapshot-png.ts"
|
|
63
|
+
"snapshot-png": "tsx scripts/snapshot-png.ts",
|
|
64
|
+
"docs:gen": "tsx scripts/docs/sync-docs.ts --write",
|
|
65
|
+
"check:docs": "tsx scripts/docs/sync-docs.ts --check"
|
|
64
66
|
},
|
|
65
67
|
"peerDependencies": {
|
|
66
68
|
"@playwright/test": ">=1.40.0",
|