@arpanp/zen-reporter 0.10.1 → 0.11.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 +10 -5
- package/bin/zen-reporter.js +83 -8
- package/dist/index.html +2 -2
- package/package.json +13 -3
package/README.md
CHANGED
|
@@ -8,11 +8,11 @@ Zen Reporter transforms Playwright's raw test results into an interactive, visua
|
|
|
8
8
|
|
|
9
9
|
Light mode:
|
|
10
10
|
|
|
11
|
-

|
|
11
|
+

|
|
12
12
|
|
|
13
13
|
Dark mode:
|
|
14
14
|
|
|
15
|
-

|
|
15
|
+

|
|
16
16
|
|
|
17
17
|
## Features
|
|
18
18
|
|
|
@@ -34,8 +34,12 @@ Dark mode:
|
|
|
34
34
|
- **Themes & Dark Mode**: Multiple design themes (`Cafe`, `Concept`, `Sentinel`) with light and dark mode toggles, built with WCAG-compliant color tokens and configurable default states.
|
|
35
35
|
- **Single-File Standalone Output**: Generates a self-contained single-file HTML report (`index.html`) with embedded datasets for easy sharing and CI/CD artifact storage. Optionally creates a lightweight standalone `summary.html` dedicated to executive dashboards.
|
|
36
36
|
|
|
37
|
+
> **Note**: Designed and built with AI pair-programming tools; fully tested, maintained, and quality-assured by human hands.
|
|
38
|
+
|
|
37
39
|
---
|
|
38
40
|
|
|
41
|
+
> **Compatibility**: Zen Reporter is designed for standard Playwright test suites and does not support BDD-styled tests (e.g. Cucumber / `playwright-bdd`).
|
|
42
|
+
|
|
39
43
|
## Installation
|
|
40
44
|
|
|
41
45
|
```bash
|
|
@@ -121,12 +125,13 @@ npx zr show
|
|
|
121
125
|
|
|
122
126
|
### 3. CLI Commands Reference (`zr`)
|
|
123
127
|
|
|
124
|
-
Zen Reporter includes a built-in CLI executable (`npx zr`) for serving reports and querying historical test execution data:
|
|
128
|
+
Zen Reporter includes a built-in CLI executable (`npx zr`) for serving reports, checking system environment, and querying historical test execution data:
|
|
125
129
|
|
|
126
|
-
#### Report &
|
|
130
|
+
#### Report & Environment
|
|
127
131
|
|
|
128
132
|
- **`npx zr show`** — Launch the report server to view `index.html` in your default browser.
|
|
129
133
|
- **`npx zr summary`** — Output Markdown summary snippet for current run results (ideal for PR comments or Slack).
|
|
134
|
+
- **`npx zr env`** — Print environment details (`zen-reporter` version, `@playwright/test` version, Node.js version, OS).
|
|
130
135
|
|
|
131
136
|
#### History & Intelligence (`zr history`)
|
|
132
137
|
|
|
@@ -140,7 +145,7 @@ Zen Reporter includes a built-in CLI executable (`npx zr`) for serving reports a
|
|
|
140
145
|
| `npx zr history tests` | Summarize granular historical execution metrics and average durations per test case. |
|
|
141
146
|
| `npx zr history flaky` | Identify flaky tests that passed in some runs and failed in others. |
|
|
142
147
|
| `npx zr history regressions` | List tests that passed in a previous run but failed in the latest run. |
|
|
143
|
-
| `npx zr history slow [--limit N]` | Rank the top
|
|
148
|
+
| `npx zr history slow [--limit N]` | Rank the top `N` slowest tests by average execution duration across runs (default: 10). |
|
|
144
149
|
| `npx zr history trend` | Display historical pass rate percentages per run over time. |
|
|
145
150
|
| `npx zr history report` | Build `history.json` and inject it into `index.html` to populate the History & Trends tabs. |
|
|
146
151
|
| `npx zr history query "<SQL>"` | Run arbitrary DuckDB SQL queries over recorded test runs. |
|
package/bin/zen-reporter.js
CHANGED
|
@@ -136,6 +136,14 @@ function formatDate(val) {
|
|
|
136
136
|
return `${year}-${month}-${day} ${hours}:${mins}:${secs}`;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
function padCenter(str, width) {
|
|
140
|
+
const totalPad = width - str.length;
|
|
141
|
+
if (totalPad <= 0) return str;
|
|
142
|
+
const padLeft = Math.floor(totalPad / 2);
|
|
143
|
+
const padRight = totalPad - padLeft;
|
|
144
|
+
return ' '.repeat(padLeft) + str + ' '.repeat(padRight);
|
|
145
|
+
}
|
|
146
|
+
|
|
139
147
|
function printTable({ columns, rows }, emptyMessage = 'No records found.', entityName = 'records') {
|
|
140
148
|
if (!columns || columns.length === 0) return;
|
|
141
149
|
|
|
@@ -318,10 +326,7 @@ function printTable({ columns, rows }, emptyMessage = 'No records found.', entit
|
|
|
318
326
|
emptyMessage.length > totalInnerWidth - 2
|
|
319
327
|
? emptyMessage.slice(0, totalInnerWidth - 5) + '...'
|
|
320
328
|
: emptyMessage;
|
|
321
|
-
|
|
322
|
-
const padLeft = Math.floor(padTotal / 2);
|
|
323
|
-
const padRight = padTotal - padLeft;
|
|
324
|
-
console.log(`|${' '.repeat(padLeft)}${msg}${' '.repeat(padRight)}|`);
|
|
329
|
+
console.log(`|${padCenter(msg, totalInnerWidth)}|`);
|
|
325
330
|
} else {
|
|
326
331
|
let isFirst = true;
|
|
327
332
|
for (const row of stringRows) {
|
|
@@ -364,13 +369,25 @@ function generateMarkdownSummaryFromReport(reportData) {
|
|
|
364
369
|
const titleProject = testRun.projectName || 'Test Automation Project';
|
|
365
370
|
const titleRun = testRun.testRunName || 'Test Run';
|
|
366
371
|
|
|
367
|
-
let md =
|
|
372
|
+
let md = `\n### 📊 Test Run Summary: ${titleProject} — ${titleRun}\n\n`;
|
|
368
373
|
md += `**Status:** ${statusStr}\n`;
|
|
369
374
|
md += `**Duration:** ${durationStr}\n`;
|
|
370
375
|
md += `**Pass Rate:** ${passRate}%\n\n`;
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
376
|
+
|
|
377
|
+
const headers = ['Total', 'Passed', 'Failed', 'Timed Out', 'Skipped'];
|
|
378
|
+
const values = [String(total), String(passed), String(failed), String(timedOut), String(skipped)];
|
|
379
|
+
|
|
380
|
+
if (interrupted > 0) {
|
|
381
|
+
headers.push('Interrupted');
|
|
382
|
+
values.push(String(interrupted));
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const widths = headers.map((h, i) => Math.max(h.length, values[i].length, 3));
|
|
386
|
+
const headerRow = `| ${headers.map((h, i) => padCenter(h, widths[i])).join(' | ')} |`;
|
|
387
|
+
const sepRow = `| ${widths.map((w) => ':' + '-'.repeat(w - 2) + ':').join(' | ')} |`;
|
|
388
|
+
const valueRow = `| ${values.map((v, i) => padCenter(v, widths[i])).join(' | ')} |`;
|
|
389
|
+
|
|
390
|
+
md += `${headerRow}\n${sepRow}\n${valueRow}\n`;
|
|
374
391
|
|
|
375
392
|
const failedCases = [];
|
|
376
393
|
function collectFailedCases(suites) {
|
|
@@ -407,6 +424,61 @@ function generateMarkdownSummaryFromReport(reportData) {
|
|
|
407
424
|
return md;
|
|
408
425
|
}
|
|
409
426
|
|
|
427
|
+
import { createRequire } from 'module';
|
|
428
|
+
import { platform, type } from 'os';
|
|
429
|
+
|
|
430
|
+
function getOsName() {
|
|
431
|
+
const p = platform();
|
|
432
|
+
if (p === 'darwin') return 'macOS';
|
|
433
|
+
if (p === 'win32') return 'Windows';
|
|
434
|
+
if (p === 'linux') {
|
|
435
|
+
try {
|
|
436
|
+
if (existsSync('/etc/os-release')) {
|
|
437
|
+
const content = readFileSync('/etc/os-release', 'utf8');
|
|
438
|
+
const match = content.match(/^PRETTY_NAME="?([^"\n]+)"?/m);
|
|
439
|
+
if (match && match[1]) return match[1];
|
|
440
|
+
}
|
|
441
|
+
} catch {
|
|
442
|
+
/* ignore */
|
|
443
|
+
}
|
|
444
|
+
return 'Linux';
|
|
445
|
+
}
|
|
446
|
+
return type();
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function getPlaywrightVersion(cwd) {
|
|
450
|
+
const require = createRequire(resolve(cwd, 'package.json'));
|
|
451
|
+
try {
|
|
452
|
+
const pwPkg = require('@playwright/test/package.json');
|
|
453
|
+
return pwPkg.version || 'not installed';
|
|
454
|
+
} catch {
|
|
455
|
+
return 'not installed';
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function getZenReporterVersion() {
|
|
460
|
+
try {
|
|
461
|
+
const pkgPath = resolve(
|
|
462
|
+
import.meta.dirname || new URL('.', import.meta.url).pathname,
|
|
463
|
+
'../package.json'
|
|
464
|
+
);
|
|
465
|
+
if (existsSync(pkgPath)) {
|
|
466
|
+
const pkg = JSON.parse(readFileSync(pkgPath, 'utf8'));
|
|
467
|
+
return pkg.version || 'unknown';
|
|
468
|
+
}
|
|
469
|
+
} catch {
|
|
470
|
+
/* ignore */
|
|
471
|
+
}
|
|
472
|
+
return 'unknown';
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
function handleEnv() {
|
|
476
|
+
console.log(`zen-reporter version: ${getZenReporterVersion()}`);
|
|
477
|
+
console.log(`@playwright/test version: ${getPlaywrightVersion(cwd)}`);
|
|
478
|
+
console.log(`Node.js version: ${process.version}`);
|
|
479
|
+
console.log(`OS: ${getOsName()}`);
|
|
480
|
+
}
|
|
481
|
+
|
|
410
482
|
function printHelp() {
|
|
411
483
|
console.log(`
|
|
412
484
|
Zen Reporter CLI
|
|
@@ -414,6 +486,7 @@ Zen Reporter CLI
|
|
|
414
486
|
Usage:
|
|
415
487
|
npx zr show Serve and view the HTML report
|
|
416
488
|
npx zr summary Output Markdown summary snippet for current run results
|
|
489
|
+
npx zr env Print environment details (versions, OS)
|
|
417
490
|
npx zr history List historic runs
|
|
418
491
|
npx zr history runs Same as above
|
|
419
492
|
npx zr history flaky Tests that failed in some runs and passed in others
|
|
@@ -663,6 +736,8 @@ if (command === 'show') {
|
|
|
663
736
|
console.error('✗ Failed to read report summary:', err.message || err);
|
|
664
737
|
process.exit(1);
|
|
665
738
|
}
|
|
739
|
+
} else if (command === 'env') {
|
|
740
|
+
handleEnv();
|
|
666
741
|
} else if (command === 'history') {
|
|
667
742
|
handleHistory(args.slice(1)).catch((e) => {
|
|
668
743
|
console.error('✗ history command failed:', e?.message || e);
|