@reportforge/playwright-pdf 0.0.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +285 -0
  2. package/LICENSE +21 -0
  3. package/README.md +524 -0
  4. package/ci-templates/azure-devops/azure-pipelines.yml +58 -0
  5. package/ci-templates/bitbucket/bitbucket-pipelines.yml +42 -0
  6. package/ci-templates/github-actions/basic-workflow.yml +44 -0
  7. package/ci-templates/github-actions/matrix-workflow.yml +69 -0
  8. package/ci-templates/gitlab-ci/.gitlab-ci.yml +42 -0
  9. package/ci-templates/jenkins/Jenkinsfile +54 -0
  10. package/dist/index.d.mts +272 -0
  11. package/dist/index.d.ts +272 -0
  12. package/dist/index.js +12566 -0
  13. package/dist/index.mjs +12567 -0
  14. package/dist/templates/layouts/detailed.hbs +38 -0
  15. package/dist/templates/layouts/executive.hbs +35 -0
  16. package/dist/templates/layouts/minimal.hbs +29 -0
  17. package/dist/templates/partials/charts.hbs +306 -0
  18. package/dist/templates/partials/ci-environment.hbs +56 -0
  19. package/dist/templates/partials/cover-page.hbs +46 -0
  20. package/dist/templates/partials/defect-log.hbs +27 -0
  21. package/dist/templates/partials/executive-summary.hbs +60 -0
  22. package/dist/templates/partials/failure-deep-dive.hbs +61 -0
  23. package/dist/templates/partials/head.hbs +17 -0
  24. package/dist/templates/partials/release-gate.hbs +63 -0
  25. package/dist/templates/partials/requirements-matrix.hbs +35 -0
  26. package/dist/templates/partials/slow-tests.hbs +27 -0
  27. package/dist/templates/partials/suite-breakdown.hbs +58 -0
  28. package/dist/templates/partials/watermark.hbs +3 -0
  29. package/dist/templates/styles/base.css +234 -0
  30. package/dist/templates/styles/detailed.css +311 -0
  31. package/dist/templates/styles/executive.css +334 -0
  32. package/dist/templates/styles/minimal.css +208 -0
  33. package/package.json +99 -0
package/README.md ADDED
@@ -0,0 +1,524 @@
1
+ # @reportforge/playwright-pdf
2
+
3
+ > Playwright PDF reporter — generate branded PDF reports from [Playwright Test](https://playwright.dev/) results. Three templates (minimal, detailed, executive) for developers, QA teams, and stakeholders. CI-ready, self-contained, with embedded screenshots and charts.
4
+
5
+ Drop it into any Playwright project and get a PDF report on every CI run. No changes to your tests.
6
+
7
+ [![npm](https://img.shields.io/npm/v/@reportforge/playwright-pdf.svg)](https://www.npmjs.com/package/@reportforge/playwright-pdf)
8
+ [![Node](https://img.shields.io/node/v/@reportforge/playwright-pdf.svg)](https://nodejs.org/)
9
+ [![License](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)
10
+
11
+ <p align="center">
12
+ <a href="https://reportforge.org/pricing">
13
+ <img src="https://img.shields.io/badge/Start%20Free%20Trial-reportforge.org%2Fpricing-CC785C?style=for-the-badge" alt="Start free trial at reportforge.org/pricing" />
14
+ </a><br>
15
+ <sub>7-day trial · ₹999/mo or $12/mo after · 25 machines · all 3 templates · cancel anytime</sub>
16
+ </p>
17
+
18
+ **[Docs](https://reportforge.org/docs)** · **[Pricing](https://reportforge.org/pricing)** · **[Support](mailto:support@reportforge.org)**
19
+
20
+ ---
21
+
22
+ ## Report Gallery
23
+
24
+ Three templates, one reporter. Every PDF is fully offline — fonts, charts, and screenshots are embedded.
25
+
26
+ <table>
27
+ <tr>
28
+ <th align="center"><code>minimal</code><br/><sub>Developer / PR checks</sub></th>
29
+ <th align="center"><code>detailed</code><br/><sub>QA team</sub></th>
30
+ <th align="center"><code>executive</code><br/><sub>Stakeholders</sub></th>
31
+ </tr>
32
+ <tr>
33
+ <td><a href="https://reportforge.org/template-minimal.png"><img src="https://reportforge.org/template-minimal.png" alt="minimal template preview" width="300"/></a></td>
34
+ <td><a href="https://reportforge.org/template-detailed.png"><img src="https://reportforge.org/template-detailed.png" alt="detailed template preview" width="300"/></a></td>
35
+ <td><a href="https://reportforge.org/template-executive.png"><img src="https://reportforge.org/template-executive.png" alt="executive template preview" width="300"/></a></td>
36
+ </tr>
37
+ <tr>
38
+ <td align="center"><sub>KPI dashboard · suite breakdown · failure stack traces · embedded screenshots</sub></td>
39
+ <td align="center"><sub>Everything in minimal <strong>+ charts · requirements matrix · defect log · full environment</strong></sub></td>
40
+ <td align="center"><sub>Cover page · KPI dashboard · charts · failure summary <em>(no stack traces)</em></sub></td>
41
+ </tr>
42
+ </table>
43
+
44
+ ---
45
+
46
+ ## Features
47
+
48
+ - **3 templates** — `minimal` (developer), `detailed` (QA team), `executive` (stakeholders)
49
+ - **Detailed reports** — KPI dashboard, suite breakdown, failure deep-dive with screenshots, CI/CD environment
50
+ - **Embedded Chart.js** — pass-rate doughnut + per-suite bar chart, bundled inline (no CDN)
51
+ - **Self-contained PDFs** — screenshots, fonts, logos all embedded; share or archive with confidence
52
+ - **Custom branding** — logo, primary/accent colours, watermark, PDF password encryption
53
+ - **Dynamic filenames** — `{date}`, `{branch}`, `{status}` tokens in the output path
54
+ - **CI/CD snippets** — GitHub Actions, GitLab CI, Bitbucket Pipelines, Jenkins, Azure DevOps
55
+ - **Shard merging** — combine N Playwright JSON shard reports into one PDF via `shardResults`; accepts glob patterns or explicit paths
56
+ - **Webhook notifications** — post pass/fail summaries to Slack, Teams, or Discord on every run; configurable per channel with `on: 'always' | 'failure' | 'success'`
57
+ - **Hybrid licensing** — one short key unlocks it; reports keep rendering offline via a cached JWT between refreshes
58
+
59
+ ---
60
+
61
+ ## Quick Start
62
+
63
+ ```bash
64
+ npm install --save-dev @reportforge/playwright-pdf puppeteer-core
65
+ ```
66
+
67
+ ```ts
68
+ // playwright.config.ts
69
+ import { defineConfig } from '@playwright/test';
70
+ import { defineReporterConfig } from '@reportforge/playwright-pdf';
71
+
72
+ export default defineConfig({
73
+ reporter: [
74
+ ['@reportforge/playwright-pdf', defineReporterConfig({
75
+ template: 'detailed',
76
+ outputFile: 'reports/{date}-{branch}-{status}.pdf',
77
+ })],
78
+ ],
79
+ use: { screenshot: 'only-on-failure' },
80
+ });
81
+ ```
82
+
83
+ `defineReporterConfig` is an optional typed identity helper — it gives you IntelliSense and type-checking on the options object without a separate `ReporterOptions` import. You can also pass a plain object literal if you prefer.
84
+
85
+ ```bash
86
+ npx playwright test
87
+ # → reports/2026-05-01-main-failed.pdf
88
+ ```
89
+
90
+ > **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.
91
+
92
+ ---
93
+
94
+ ## Installation
95
+
96
+ ### Requirements
97
+
98
+ - Node.js ≥ 18
99
+ - `@playwright/test` ≥ 1.40 (peer dependency)
100
+ - `puppeteer-core` ≥ 21 (peer dependency)
101
+ - Chrome or Chromium installed on the machine
102
+
103
+ ### Chrome setup
104
+
105
+ The reporter auto-detects Chrome via `PUPPETEER_EXECUTABLE_PATH`, then system Chrome, then `chrome-finder`. Full per-OS instructions: [reportforge.org/docs#chrome-setup](https://reportforge.org/docs#chrome-setup).
106
+
107
+ **Windows**
108
+
109
+ ```powershell
110
+ winget install Google.Chrome
111
+ $env:PUPPETEER_EXECUTABLE_PATH = "C:\Program Files\Google\Chrome\Application\chrome.exe"
112
+ ```
113
+
114
+ **Linux (Debian / Ubuntu)**
115
+
116
+ ```bash
117
+ wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | \
118
+ sudo gpg --dearmor -o /usr/share/keyrings/google-chrome.gpg
119
+ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/google-chrome.gpg] \
120
+ http://dl.google.com/linux/chrome/deb/ stable main" | \
121
+ sudo tee /etc/apt/sources.list.d/google-chrome.list
122
+ sudo apt-get update -qq && sudo apt-get install -y google-chrome-stable
123
+ export PUPPETEER_EXECUTABLE_PATH=/usr/bin/google-chrome-stable
124
+ ```
125
+
126
+ > **Note:** Do not use the `chromium-browser` apt package — it installs as a snap on Ubuntu and Puppeteer cannot drive it.
127
+
128
+ **macOS**
129
+
130
+ ```bash
131
+ brew install --cask google-chrome
132
+ export PUPPETEER_EXECUTABLE_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
133
+ ```
134
+
135
+ Or set the path in `playwright.config.ts`:
136
+
137
+ ```ts
138
+ reporter: [['@reportforge/playwright-pdf', {
139
+ puppeteerExecutablePath: '/usr/bin/google-chrome-stable',
140
+ }]]
141
+ ```
142
+
143
+ ---
144
+
145
+ ## Pricing
146
+
147
+ | Plan | INR | USD | Includes |
148
+ |---|---|---|---|
149
+ | **Monthly** | **₹999 / month** | **$12 / month** | All three templates · custom branding · PDF encryption · up to 25 active machines · priority email support |
150
+ | **Yearly** | **₹8,499 / year** | **$99 / year** | Everything in Monthly · ~29–31% saving vs monthly |
151
+
152
+ Currency is auto-detected by region; toggle on the pricing page.
153
+
154
+ <p align="center">
155
+ <a href="https://reportforge.org/pricing">
156
+ <img src="https://img.shields.io/badge/Start%20Free%20Trial-reportforge.org%2Fpricing-CC785C?style=for-the-badge" alt="Start free trial" />
157
+ </a><br>
158
+ <sub>7-day trial · no charge until day 8 · cancel anytime from your dashboard</sub>
159
+ </p>
160
+
161
+ ---
162
+
163
+ ## Configuration
164
+
165
+ All options are the second element of the reporter tuple.
166
+
167
+ | Option | Type | Default | Description |
168
+ |---|---|---|---|
169
+ | `template` | `'minimal' \| 'detailed' \| 'executive'` or array | `'minimal'` | Template(s) to generate. Pass an array to produce one PDF per template — the template name is appended automatically (e.g. `report-detailed.pdf`). |
170
+ | `outputFile` | `string` | `'playwright-report/{date}-report.pdf'` | Output path (supports tokens) |
171
+ | `reportTitle` | `string` | `'Playwright Test Report'` | Title in header and cover |
172
+ | `projectName` | `string` | from `package.json` | Project name shown in report |
173
+ | `logo` | `string` | — | Path to logo image (PNG / JPG / SVG) |
174
+ | `primaryColor` | `string` | `'#CC785C'` | Brand colour (hex) |
175
+ | `accentColor` | `string` | `'#3F7D58'` | Accent colour (hex) |
176
+ | `watermark` | `string` | — | Diagonal watermark text (e.g. `'CONFIDENTIAL'`) |
177
+ | `pdfPassword` | `string` | — | Password-protect the PDF (requires `qpdf`) |
178
+ | `licenseKey` | `string` | env `RF_LICENSE_KEY` | Subscription key (format `RFSU-…`) |
179
+ | `compressionLevel` | `'auto' \| 'none' \| 'balanced' \| 'max'` | `'auto'` | Screenshot JPEG quality + inline failure cap |
180
+ | `includeScreenshots` | `boolean` | `true` | Embed screenshots in the PDF. Set to `false` to omit images — useful for exec-audience reports or reducing file size. |
181
+ | `maxInlineFailures` | `number` | derived from `compressionLevel` | Cap on inline failures; overflow spills to `{basename}-failures.json` |
182
+ | `maxFileSizeMb` | `number` | `8` | Soft cap; reporter re-renders with `max` compression once if exceeded |
183
+ | `serverUrl` | `string` | `'https://reportforge.org'` | Licensing server base URL (override only for self-hosting) |
184
+ | `open` | `boolean` | `false` | Open PDF after generation (local only) |
185
+ | `shardResults` | `string \| string[]` | — | Glob or path array of Playwright JSON shard files to merge into one PDF. |
186
+ | `notify` | `object` | — | Webhook notification channels. See [Webhook Notifications](#webhook-notifications). |
187
+ | `historyFile` | `string` | `~/.reportforge/{key}/history.json` | Path to history JSON. Relative paths resolved from cwd at startup. |
188
+ | `historySize` | `number` | `10` | Max run entries to keep (integer ≥ 2). |
189
+ | `showTrend` | `boolean` | `true` | Set to `false` to disable history write and sparkline entirely. |
190
+ | `puppeteerExecutablePath` | `string` | auto-detect | Path to Chrome / Chromium |
191
+
192
+ Full reference: [reportforge.org/docs#configuration](https://reportforge.org/docs#configuration).
193
+
194
+ ### Shard Merging
195
+
196
+ Combine parallel Playwright shards into one PDF without re-running any tests.
197
+
198
+ **Workflow:**
199
+
200
+ 1. Run each shard with `--reporter=json` to produce a JSON output file.
201
+ 2. In a separate step, point `shardResults` at those files — accepts a glob or an explicit array.
202
+
203
+ ```typescript
204
+ // playwright.config.ts (merge step)
205
+ reporter: [
206
+ ['@reportforge/playwright-pdf', {
207
+ shardResults: 'results/shard-*.json', // glob
208
+ // or: shardResults: ['results/shard-1.json', 'results/shard-2.json'],
209
+ outputFile: 'reports/{date}-report.pdf',
210
+ }],
211
+ ],
212
+ ```
213
+
214
+ The merge step can run against a dummy test file with zero tests — `shardResults` takes precedence over live results.
215
+
216
+ > **Note:** Timed-out tests are counted as failures in shard mode (Playwright JSON stats do not distinguish `timedOut` from `failed`).
217
+
218
+ ### Webhook Notifications
219
+
220
+ Post a summary message to Slack, Teams, or Discord after each run.
221
+
222
+ ```typescript
223
+ notify: {
224
+ slack: {
225
+ url: 'https://hooks.slack.com/services/...',
226
+ enabled: true, // required — defaults to false
227
+ on: 'always', // 'always' | 'failure' | 'success' (default: 'always')
228
+ },
229
+ teams: {
230
+ url: 'https://outlook.office.com/webhook/...',
231
+ enabled: true,
232
+ on: 'failure',
233
+ },
234
+ discord: {
235
+ url: 'https://discord.com/api/webhooks/...',
236
+ enabled: true,
237
+ },
238
+ },
239
+ ```
240
+
241
+ Each channel is independent. `enabled: false` (the default) lets you store a URL without activating it — useful for staging configs. Set `enabled: true` to activate.
242
+
243
+ The `on` trigger controls when the message fires:
244
+
245
+ | Value | Sends when |
246
+ |---|---|
247
+ | `'always'` | Every run |
248
+ | `'failure'` | `stats.failed > 0` or run timed out / interrupted |
249
+ | `'success'` | All tests passed |
250
+
251
+ The summary includes pass rate, test counts, duration, and the report filename. Notifications require a valid license and fire after PDF generation (or after a PDF generation failure — you still get the ping).
252
+
253
+ ### Test History Trending
254
+
255
+ After each run the reporter appends a summary entry to a local JSON file and renders a pass-rate sparkline + verdict row in the `detailed` template.
256
+
257
+ **Local dev (zero config)** — history is written automatically to `~/.reportforge/{projectKey}/history.json`. The sparkline appears once two or more runs have been recorded.
258
+
259
+ **CI with ephemeral runners** — set `historyFile` to a project-relative path and cache it between runs:
260
+
261
+ ```typescript
262
+ // playwright.config.ts
263
+ reporter: [['@reportforge/playwright-pdf', {
264
+ template: 'detailed',
265
+ historyFile: '.reportforge/history.json',
266
+ }]]
267
+ ```
268
+
269
+ ```yaml
270
+ # .github/workflows/test.yml
271
+ - uses: actions/cache@v4
272
+ with:
273
+ path: .reportforge/history.json
274
+ key: reportforge-history-${{ github.ref }}
275
+ # Omit restore-keys — cross-branch fallback causes misleading sparklines on PRs
276
+ ```
277
+
278
+ **Monorepo** — each package needs a distinct `historyFile` (e.g. `.reportforge/api-history.json`, `.reportforge/web-history.json`) so runs do not overwrite each other.
279
+
280
+ ### Filename tokens
281
+
282
+ | Token | Replaced with | Example |
283
+ |---|---|---|
284
+ | `{date}` | `YYYY-MM-DD` (UTC) | `2026-04-21` |
285
+ | `{branch}` | Git branch, sanitised | `feature-auth` |
286
+ | `{status}` | Overall verdict | `passed` / `failed` / `timedout` / `interrupted` |
287
+
288
+ ---
289
+
290
+ ## Templates
291
+
292
+ ### `minimal` — Developer-focused
293
+
294
+ Clean layout, KPI numbers, hierarchical test table, failure details with stack traces and embedded screenshots. Fast to generate. Good for local development and PR checks.
295
+
296
+ ### `detailed` — QA Team
297
+
298
+ Everything in `minimal`, **plus** Chart.js pass-rate + suite-results charts, a numbered defect log, a requirements traceability matrix derived from `@TAG` annotations, and the full CI/CD environment table.
299
+
300
+ ### `executive` — Stakeholder presentations
301
+
302
+ Full-page cover with verdict + KPI strip, followed by a compact dashboard with charts and a failures summary (titles only — **no raw stack traces**). Best for sprint reports and management dashboards.
303
+
304
+ ### Generating multiple templates in one run
305
+
306
+ Pass an array to `template` to generate one PDF per template from a single test run. The template name is appended to the output filename automatically:
307
+
308
+ ```ts
309
+ // playwright.config.ts
310
+ reporter: [
311
+ ['@reportforge/playwright-pdf', {
312
+ template: ['detailed', 'executive'],
313
+ outputFile: 'reports/{date}-report.pdf',
314
+ licenseKey: process.env.RF_LICENSE_KEY,
315
+ }],
316
+ ]
317
+ ```
318
+
319
+ ```
320
+ # → reports/2026-04-28-report-detailed.pdf
321
+ # → reports/2026-04-28-report-executive.pdf
322
+ ```
323
+
324
+ One license check, one data-collection pass — faster than multiple reporter instances. Duplicate entries are silently deduplicated.
325
+
326
+ ---
327
+
328
+ ## CI/CD Integration
329
+
330
+ Full workflows for all four CI providers: [reportforge.org/docs#ci-cd](https://reportforge.org/docs#ci-cd).
331
+
332
+ ### GitHub Actions
333
+
334
+ ```yaml
335
+ - name: Run Playwright tests
336
+ run: npx playwright test
337
+ env:
338
+ RF_LICENSE_KEY: ${{ secrets.RF_LICENSE_KEY }}
339
+ PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome-stable
340
+
341
+ - name: Upload PDF report
342
+ if: always()
343
+ uses: actions/upload-artifact@v4
344
+ with:
345
+ name: playwright-pdf-report
346
+ path: reports/*.pdf
347
+ ```
348
+
349
+ ### GitHub Actions — Sharded runs
350
+
351
+ Run shards in parallel with `--reporter=json`, then merge all JSON files into one PDF:
352
+
353
+ ```yaml
354
+ jobs:
355
+ test:
356
+ strategy:
357
+ matrix:
358
+ shard: [1, 2, 3, 4]
359
+ runs-on: ubuntu-latest
360
+ steps:
361
+ - uses: actions/checkout@v4
362
+ - uses: actions/setup-node@v4
363
+ with: { node-version: '20' }
364
+ - run: npm ci
365
+ - run: npx playwright test --shard=${{ matrix.shard }}/4 --reporter=json
366
+ env:
367
+ PLAYWRIGHT_JSON_OUTPUT_NAME: results/shard-${{ matrix.shard }}.json
368
+ - uses: actions/upload-artifact@v4
369
+ with:
370
+ name: shard-json-${{ matrix.shard }}
371
+ path: results/shard-${{ matrix.shard }}.json
372
+
373
+ merge-pdf:
374
+ needs: test
375
+ runs-on: ubuntu-latest
376
+ steps:
377
+ - uses: actions/checkout@v4
378
+ - uses: actions/setup-node@v4
379
+ with: { node-version: '20' }
380
+ - run: npm ci
381
+ - uses: actions/download-artifact@v4
382
+ with: { pattern: shard-json-*, merge-multiple: true, path: results }
383
+ - run: npx playwright test --reporter=@reportforge/playwright-pdf tests/dummy.spec.ts
384
+ env:
385
+ RF_LICENSE_KEY: ${{ secrets.RF_LICENSE_KEY }}
386
+ PUPPETEER_EXECUTABLE_PATH: /usr/bin/google-chrome-stable
387
+ SHARD_RESULTS_GLOB: 'results/shard-*.json'
388
+ - uses: actions/upload-artifact@v4
389
+ with: { name: playwright-pdf-report, path: reports/*.pdf }
390
+ ```
391
+
392
+ In `playwright.config.ts` set `shardResults: process.env.SHARD_RESULTS_GLOB`. `tests/dummy.spec.ts` can be a single skipped test — live results are ignored when `shardResults` is set.
393
+
394
+ ### GitLab CI
395
+
396
+ ```yaml
397
+ playwright-tests:
398
+ image: mcr.microsoft.com/playwright:v1.49.0-jammy
399
+ script:
400
+ - npm ci && npx playwright test
401
+ artifacts:
402
+ paths: [reports/*.pdf]
403
+ when: always
404
+ expire_in: 30 days
405
+ ```
406
+
407
+ ### Bitbucket Pipelines
408
+
409
+ ```yaml
410
+ image: mcr.microsoft.com/playwright:v1.49.0-jammy
411
+ pipelines:
412
+ default:
413
+ - step:
414
+ name: Playwright Tests + PDF Report
415
+ caches: [node]
416
+ script:
417
+ - npm ci
418
+ - npx playwright test
419
+ artifacts:
420
+ - playwright-report/*.pdf
421
+ ```
422
+
423
+ Set `RF_LICENSE_KEY` in **Repository Settings → Repository variables**.
424
+
425
+ ### Jenkins
426
+
427
+ ```groovy
428
+ stage('Playwright Tests') {
429
+ withCredentials([string(credentialsId: 'rf-license', variable: 'RF_LICENSE_KEY')]) {
430
+ sh 'npx playwright test'
431
+ }
432
+ archiveArtifacts artifacts: 'reports/*.pdf', allowEmptyArchive: true
433
+ }
434
+ ```
435
+
436
+ ### Azure DevOps
437
+
438
+ ```yaml
439
+ - script: npx playwright test
440
+ env: { RF_LICENSE_KEY: $(RF_LICENSE_KEY) }
441
+ - task: PublishPipelineArtifact@1
442
+ inputs:
443
+ targetPath: reports
444
+ artifact: playwright-pdf-report
445
+ ```
446
+
447
+ ---
448
+
449
+ ## Licensing
450
+
451
+ ReportForge ships a **hybrid offline-first** model:
452
+
453
+ 1. Paste your `RFSU-…` key into the config once (or set `RF_LICENSE_KEY`).
454
+ 2. On first run the reporter activates against the license server, receives a short-lived **Ed25519-signed JWT**, and caches it at `~/.reportforge/license.json`.
455
+ 3. Every subsequent run is **fully offline** — the cached JWT is verified locally against a public key bundled into the npm package. No network call.
456
+ 4. When the cache has less than 24 hours left, the reporter refreshes it in the background.
457
+ 5. Each subscription allows up to **25 active machines** in any rolling 30-day window. Machines that haven't run in 30 days are pruned automatically.
458
+
459
+ 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.
460
+
461
+ ```bash
462
+ export RF_LICENSE_KEY=RFSU-XXXX-XXXX-XXXX-XXXX
463
+ npx playwright test
464
+ ```
465
+
466
+ Full lifecycle + offline failure modes: [reportforge.org/docs#license](https://reportforge.org/docs#license).
467
+
468
+ ---
469
+
470
+ ## Requirements Traceability
471
+
472
+ The `detailed` template generates a requirements matrix from test tags. Tag tests to link them to requirements:
473
+
474
+ ```ts
475
+ test('@REQ-101 user can login', async ({ page }) => { /* ... */ });
476
+ test.describe('@FEAT-payment', () => { /* ... */ });
477
+ ```
478
+
479
+ The matrix rolls tests up per tag with pass count, fail count, and coverage percentage.
480
+
481
+ ---
482
+
483
+ ## Troubleshooting
484
+
485
+ Set `RF_DEBUG=1` to log the full activation flow and error stack traces:
486
+
487
+ ```bash
488
+ RF_DEBUG=1 npx playwright test 2>&1 | grep '\[reportforge\]'
489
+ ```
490
+
491
+ Common issues:
492
+
493
+ - **`Chrome/Chromium not found`** → install Google Chrome Stable; don't use the Ubuntu `chromium-browser` snap.
494
+ - **Charts blank** → ensure `npm run bundle-chartjs` ran at build; the reporter waits up to 30s for `window.__chartsReady`.
495
+ - **`pdfPassword` ignored** → requires `qpdf` on `PATH` (`apt install qpdf` / `brew install qpdf` / `choco install qpdf`).
496
+ - **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 JWT cache all skip PDF generation.
497
+
498
+ Full guide: [reportforge.org/docs#troubleshooting](https://reportforge.org/docs#troubleshooting).
499
+
500
+ ---
501
+
502
+ ## Documentation
503
+
504
+ Full documentation at [reportforge.org/docs](https://reportforge.org/docs):
505
+
506
+ - [Quick start](https://reportforge.org/docs#install) — install, configure, activate
507
+ - [Chrome setup](https://reportforge.org/docs#chrome-setup) — Windows, Linux, macOS
508
+ - [CI/CD integration](https://reportforge.org/docs#ci-cd) — GitHub Actions, GitLab CI, Bitbucket Pipelines, Jenkins, Azure DevOps
509
+ - [Configuration reference](https://reportforge.org/docs#configuration) — all options
510
+ - [Filename tokens](https://reportforge.org/docs#tokens) — `{date}`, `{branch}`, `{status}`
511
+ - [Templates](https://reportforge.org/docs#templates) — minimal, detailed, executive
512
+ - [License & offline behaviour](https://reportforge.org/docs#license) — JWT cache, machine cap, cancellation
513
+ - [Troubleshooting](https://reportforge.org/docs#troubleshooting) — common issues and debug flags
514
+ - **Changelog** — [CHANGELOG.md](./CHANGELOG.md)
515
+
516
+ ---
517
+
518
+ ## Contributing
519
+
520
+ Questions and bug reports: email [support@reportforge.org](mailto:support@reportforge.org).
521
+
522
+ ## License
523
+
524
+ MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,58 @@
1
+ # Add this to your azure-pipelines.yml
2
+ # Requires Node.js tool installed on the agent
3
+
4
+ trigger:
5
+ branches:
6
+ include:
7
+ - main
8
+ - develop
9
+
10
+ pr:
11
+ branches:
12
+ include:
13
+ - main
14
+
15
+ pool:
16
+ vmImage: 'ubuntu-latest'
17
+
18
+ variables:
19
+ - group: reportforge-secrets # Variable group containing RF_LICENSE_KEY
20
+
21
+ stages:
22
+ - stage: Test
23
+ displayName: 'Playwright Tests + PDF Report'
24
+ jobs:
25
+ - job: PlaywrightTest
26
+ displayName: 'Run Tests'
27
+ steps:
28
+ - task: NodeTool@0
29
+ displayName: 'Install Node.js'
30
+ inputs:
31
+ versionSpec: '22.x'
32
+
33
+ - script: npm ci
34
+ displayName: 'Install dependencies'
35
+
36
+ - script: npx playwright install chromium --with-deps
37
+ displayName: 'Install Playwright browsers'
38
+
39
+ - script: npx playwright test
40
+ displayName: 'Run Playwright tests'
41
+ env:
42
+ RF_LICENSE_KEY: $(RF_LICENSE_KEY)
43
+
44
+ - task: PublishPipelineArtifact@1
45
+ displayName: 'Upload PDF Report'
46
+ condition: always()
47
+ inputs:
48
+ targetPath: playwright-report
49
+ artifact: playwright-pdf-report
50
+ publishLocation: pipeline
51
+
52
+ - task: PublishTestResults@2
53
+ displayName: 'Publish Test Results'
54
+ condition: always()
55
+ inputs:
56
+ testResultsFormat: 'JUnit'
57
+ testResultsFiles: 'test-results/results.xml'
58
+ failTaskOnFailedTests: false
@@ -0,0 +1,42 @@
1
+ # Copy this file to bitbucket-pipelines.yml in your project root.
2
+ # Set RF_LICENSE_KEY in Repository Settings > Repository variables.
3
+ # Uses the official Playwright Docker image which includes Chromium.
4
+
5
+ image: mcr.microsoft.com/playwright:v1.49.0-jammy
6
+
7
+ pipelines:
8
+ default:
9
+ - step:
10
+ name: Playwright Tests + PDF Report
11
+ caches:
12
+ - node
13
+ script:
14
+ - npm ci
15
+ - npx playwright test
16
+ artifacts:
17
+ - playwright-report/*.pdf
18
+ after-script:
19
+ - |
20
+ if [ -n "$BITBUCKET_PR_ID" ] && [ -n "$BITBUCKET_WORKSPACE" ] && [ -n "$BB_API_TOKEN" ]; then
21
+ curl -s -X POST \
22
+ -u "${BITBUCKET_REPO_OWNER}:${BB_API_TOKEN}" \
23
+ -H "Content-Type: application/json" \
24
+ -d "{\"content\": {\"raw\": \"PDF report available — download from the [pipeline artifacts](https://bitbucket.org/${BITBUCKET_WORKSPACE}/${BITBUCKET_REPO_SLUG}/pipelines/results/${BITBUCKET_PIPELINE_UUID}).\"}, \"inline\": false}" \
25
+ "https://api.bitbucket.org/2.0/repositories/${BITBUCKET_WORKSPACE}/${BITBUCKET_REPO_SLUG}/pullrequests/${BITBUCKET_PR_ID}/comments" || true
26
+ fi
27
+
28
+ branches:
29
+ main:
30
+ - step:
31
+ name: Playwright Tests + PDF Report
32
+ caches:
33
+ - node
34
+ script:
35
+ - npm ci
36
+ - npx playwright test
37
+ artifacts:
38
+ - playwright-report/*.pdf
39
+
40
+ definitions:
41
+ caches:
42
+ node: node_modules
@@ -0,0 +1,44 @@
1
+ # Copy this file to .github/workflows/playwright.yml in your project
2
+ name: Playwright Tests + PDF Report
3
+
4
+ on:
5
+ push:
6
+ branches: [main, develop]
7
+ pull_request:
8
+ branches: [main]
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: ubuntu-latest
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - uses: actions/setup-node@v4
17
+ with:
18
+ node-version: '22'
19
+ cache: 'npm'
20
+
21
+ - name: Install dependencies
22
+ run: npm ci
23
+
24
+ - name: Install Playwright browsers
25
+ run: npx playwright install chromium --with-deps
26
+
27
+ - name: Run Playwright tests
28
+ run: npx playwright test
29
+ env:
30
+ RF_LICENSE_KEY: ${{ secrets.RF_LICENSE_KEY }}
31
+
32
+ - name: Upload PDF Report
33
+ if: always()
34
+ uses: actions/upload-artifact@v4
35
+ with:
36
+ name: playwright-pdf-report
37
+ path: playwright-report/*.pdf
38
+ retention-days: 30
39
+
40
+ - name: Comment PR
41
+ if: always() && github.event_name == 'pull_request'
42
+ uses: ./.github/actions/playwright-pdf-report
43
+ with:
44
+ github-token: ${{ secrets.GITHUB_TOKEN }}