@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 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
- ![Dashboard Overview - Light Mode](docs/screenshots/light-mode.png)
11
+ ![Dashboard Overview - Light Mode](https://raw.githubusercontent.com/apatelia/zen-reporter/main/docs/screenshots/light-mode.png)
12
12
 
13
13
  Dark mode:
14
14
 
15
- ![Dashboard Overview - Dark Mode](docs/screenshots/dark-mode.png)
15
+ ![Dashboard Overview - Dark Mode](https://raw.githubusercontent.com/apatelia/zen-reporter/main/docs/screenshots/dark-mode.png)
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 & Summaries
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 $N$ slowest tests by average execution duration across runs (default: 10). |
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. |
@@ -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
- const padTotal = totalInnerWidth - msg.length;
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 = `### 📊 Test Run Summary: ${titleProject} — ${titleRun}\n\n`;
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
- md += `| Total | Passed | Failed | Timed Out | Skipped |\n`;
372
- md += `| :---: | :---: | :---: | :-------: | :-----: |\n`;
373
- md += `| ${total} | ${passed} | ${failed} | ${timedOut} | ${skipped} |\n`;
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);