@sentinelqa/playwright-reporter 0.1.30 → 0.1.32

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
@@ -1,15 +1,21 @@
1
1
  # Playwright Reporter
2
2
 
3
+ After every failed run, Sentinel prints a shareable debugging link:
4
+
5
+ 👉 https://sentinelqa.com/run/abc123
6
+
7
+ Open it to inspect failures instantly or share it in Slack, PRs, or GitHub issues.
8
+
3
9
  [![npm](https://img.shields.io/npm/v/@sentinelqa/playwright-reporter)](https://www.npmjs.com/package/@sentinelqa/playwright-reporter)
4
10
  [![downloads](https://img.shields.io/npm/dm/@sentinelqa/playwright-reporter)](https://www.npmjs.com/package/@sentinelqa/playwright-reporter)
5
11
  [![license](https://img.shields.io/npm/l/@sentinelqa/playwright-reporter)](./LICENSE)
6
12
 
7
- A Playwright reporter that aggregates traces, screenshots, videos, and logs
8
- into a single debugging report for failed tests.
13
+ From failed CI run root cause in seconds.
14
+ Get a shareable Playwright debugging link with traces, screenshots, and failure context — no setup required.
9
15
 
10
- Works locally out of the box with no account required.
16
+ Works with no account or API key required.
11
17
 
12
- Optionally upload runs to Sentinel Cloud for CI history and AI failure analysis.
18
+ Use it to get a shareable hosted run link from CI or local development, then upgrade to Sentinel Cloud for richer history and intelligence.
13
19
 
14
20
  ![Sentinel Report Example](./docs/screenshot.png)
15
21
  ![Run-to-Run Diff](./docs/run_diff.png)
@@ -17,24 +23,31 @@ Optionally upload runs to Sentinel Cloud for CI history and AI failure analysis.
17
23
 
18
24
  ## Features
19
25
 
20
- - Aggregates Playwright traces, screenshots, videos, and logs
21
- - Generates a local HTML debugging report
22
- - Prints a deterministic quick diagnosis in the terminal after failed runs
23
- - Adds a failure digest to the local HTML report
24
- - Groups similar failures so repeated symptoms are easy to spot
25
- - Lets you copy debug summaries for Slack, Jira, and GitHub issues
26
- - Compares the current run to the previous run on the same branch
26
+ - Free hosted debugging links by default, with no account or API key required
27
+ - Public run page that opens on unified failures across the run
28
+ - Within-run failure grouping so repeated failures collapse into one issue
29
+ - Public failure pages with screenshots, evidence, parsed errors and light summaries
30
+ - Copyable share actions for Slack, PRs, and debugging handoff
31
+ - Deterministic quick diagnosis in the terminal after failed runs
32
+ - Playwright traces, screenshots, videos and logs uploaded automatically
33
+ - 48-hour public share links on the free hosted flow
27
34
  - Works with existing Playwright reporter setup
28
- - Optional Sentinel Cloud integration
29
- - CI run history and AI debugging summaries in cloud mode
35
+ - Optional live failure capture for richer Sentinel Cloud analysis
36
+ - CI run history, retention, and deeper AI debugging in Sentinel Cloud
30
37
 
31
38
  ## Why this exists
32
39
 
33
- Debugging Playwright CI failures often means downloading traces,
34
- screenshots, and videos separately.
40
+ Debugging Playwright failures usually means downloading traces, screenshots, and logs separately from CI.
41
+
42
+ Reporter uploads those artifacts into a single hosted Sentinel run page so you can open one link, inspect failures fast, and share that link with the rest of the team.
35
43
 
36
- Reporter aggregates everything into one debugging report
37
- so you can quickly understand what failed.
44
+ ## Why teams use the free version
45
+
46
+ - Drop one wrapper into `playwright.config.ts` and keep running `npx playwright test`
47
+ - Get a hosted Sentinel debugging link automatically on failed runs
48
+ - Share one public URL in Slack, PRs, or GitHub issues instead of passing around raw CI artifacts
49
+ - See unified failures, grouped failure patterns, screenshots, and evidence in one place
50
+ - Let teammates inspect the failure without needing your CI system or local machine
38
51
 
39
52
  ## Requirements
40
53
 
@@ -47,8 +60,8 @@ so you can quickly understand what failed.
47
60
 
48
61
  - best for free and local users
49
62
  - zero-friction setup
50
- - local HTML report works exactly as today
51
- - cloud upload works when configured
63
+ - hosted Sentinel report link is generated automatically
64
+ - no `SENTINEL_TOKEN` required
52
65
  - AI summaries use trace and reporter evidence, but are less precise than live page capture
53
66
 
54
67
  Install:
@@ -87,58 +100,59 @@ Run your Playwright tests:
87
100
  npx playwright test
88
101
  ```
89
102
 
90
- If tests fail and `SENTINEL_TOKEN` is not set, Sentinel generates:
103
+ If tests fail, Sentinel uploads a hosted debugging report and prints the shareable link in the terminal.
104
+
105
+ Open the hosted report to inspect:
91
106
 
92
- - `sentinel-report/index.html`
93
- - `sentinel-debug.html`
107
+ - failed tests across jobs
108
+ - within-run grouped failures
109
+ - screenshots and videos
110
+ - trace links
111
+ - parsed failure details
112
+ - light summaries
113
+ - shareable public debugging page
94
114
 
95
- Open the report to inspect:
115
+ The free hosted public flow is designed for distribution:
96
116
 
97
- - failure digest
98
- - similar failure groups
99
- - run-to-run diff
100
- - failed tests
101
- - screenshots
102
- - videos
103
- - trace files
104
- - logs
117
+ - one shareable debugging link per run
118
+ - public read-only pages
119
+ - fast enough to use in CI comments and Slack threads
120
+ - clear upgrade path into a full Sentinel workspace when teams want history, retention, and deeper analysis
105
121
 
106
122
  ## Modes
107
123
 
108
- ### Local mode
124
+ ### Free hosted mode
109
125
 
110
- If `SENTINEL_TOKEN` is not set, the reporter generates a local HTML debugging report.
126
+ If `SENTINEL_TOKEN` is not set, the reporter uploads the run to a hosted public Sentinel report and prints the shareable URL.
111
127
 
112
- ### Cloud mode
128
+ This free public flow includes:
113
129
 
114
- If `SENTINEL_TOKEN` is set in CI, the reporter uploads the run to Sentinel instead of generating the local HTML report.
130
+ - hosted run page
131
+ - hosted failure pages
132
+ - grouped failures inside the run
133
+ - light summaries
134
+ - copy/share actions
135
+ - 48-hour share links
115
136
 
116
- ```bash
117
- SENTINEL_TOKEN=your_project_ingest_token npx playwright test
118
- ```
119
-
120
- For intentional uploads outside CI, also set `SENTINEL_UPLOAD_LOCAL=1` and provide the usual commit and run metadata expected by the uploader.
137
+ ### Workspace mode
121
138
 
122
- Example:
139
+ If `SENTINEL_TOKEN` is set, the reporter uploads into your Sentinel workspace instead of the free hosted public flow.
123
140
 
124
141
  ```bash
125
- SENTINEL_TOKEN=your_project_ingest_token \
126
- SENTINEL_UPLOAD_LOCAL=1 \
127
- GITHUB_SHA=abc123 \
128
- GITHUB_REF_NAME=main \
129
- GITHUB_RUN_ID=local-dev \
130
- npx playwright test
142
+ SENTINEL_TOKEN=your_project_ingest_token npx playwright test
131
143
  ```
132
144
 
145
+ For local runs outside CI, Sentinel will use your local git metadata automatically when available.
146
+
133
147
  ## What `withSentinel()` does
134
148
 
135
149
  - Preserves your existing reporter configuration
136
150
  - Injects a Playwright JSON reporter if one is missing
137
- - Reuses your existing Playwright HTML reporter path when configured
138
151
  - Sets sensible artifact defaults:
139
152
  - trace: `retain-on-failure`
140
153
  - screenshot: `only-on-failure`
141
154
  - video: `retain-on-failure`
155
+ - Uploads the run to hosted Sentinel at the end of the test run
142
156
 
143
157
  ## Recommended Cloud Setup
144
158
 
@@ -175,7 +189,7 @@ Use this cloud setup when you want:
175
189
  - richer DOM-aware diagnosis
176
190
  - more reliable code patches grounded in real page state
177
191
 
178
- Free and local-only users do not need this. The standard `withSentinel()` setup remains the simplest path and continues to generate the local report the same way as before.
192
+ Free and local-only users do not need this. The standard `withSentinel()` setup remains the simplest path and will upload a hosted Sentinel report automatically.
179
193
 
180
194
  ## Options
181
195
 
@@ -187,9 +201,6 @@ withSentinel(config, {
187
201
  testResultsDir: "test-results",
188
202
  artifactDirs: ["tmp/extra-artifacts"],
189
203
  verbose: true,
190
- localReportDir: "sentinel-report",
191
- localReportFileName: "index.html",
192
- localRedirectFileName: "sentinel-debug.html",
193
204
  });
194
205
  ```
195
206
 
@@ -202,6 +213,10 @@ Sentinel Cloud adds:
202
213
  - AI-generated failure summaries
203
214
  - flaky test detection
204
215
  - shareable run links
216
+ - longer retention
217
+ - compare against previous runs
218
+ - recurring failure history
219
+ - richer fix suggestions and team workflows
205
220
 
206
221
  Free for up to 100 CI runs per month.
207
222
  Create an account at [sentinelqa.com](https://sentinelqa.com).
package/dist/index.d.ts CHANGED
@@ -23,9 +23,6 @@ export type SentinelPlaywrightOptions = {
23
23
  testResultsDir?: string;
24
24
  artifactDirs?: string[];
25
25
  verbose?: boolean;
26
- localReportDir?: string;
27
- localReportFileName?: string;
28
- localRedirectFileName?: string;
29
26
  };
30
27
  export declare function withSentinel(config: PlaywrightConfig, options?: SentinelPlaywrightOptions): PlaywrightConfig;
31
28
  export declare function resolveSentinelPaths(config: PlaywrightConfig, options?: SentinelPlaywrightOptions): SentinelResolvedPaths;
package/dist/index.js CHANGED
@@ -105,10 +105,7 @@ function withSentinel(config, options = {}) {
105
105
  playwrightReportDir,
106
106
  testResultsDir,
107
107
  artifactDirs,
108
- verbose: options.verbose ?? false,
109
- localReportDir: options.localReportDir,
110
- localReportFileName: options.localReportFileName,
111
- localRedirectFileName: options.localRedirectFileName
108
+ verbose: options.verbose ?? false
112
109
  };
113
110
  const sentinelIndex = reporters.findIndex((entry) => getReporterName(entry) === sentinelReporterPath);
114
111
  if (sentinelIndex !== -1) {
@@ -5,9 +5,6 @@ type ReporterOptions = {
5
5
  testResultsDir: string;
6
6
  artifactDirs?: string[];
7
7
  verbose?: boolean;
8
- localReportDir?: string;
9
- localReportFileName?: string;
10
- localRedirectFileName?: string;
11
8
  };
12
9
  declare class SentinelReporter {
13
10
  private failedCount;
@@ -16,7 +13,6 @@ declare class SentinelReporter {
16
13
  constructor(options: ReporterOptions);
17
14
  onBegin(config: any, suite: any): void;
18
15
  onTestEnd(test: any, result: any): Promise<void>;
19
- private printLocalReport;
20
16
  onEnd(): Promise<void>;
21
17
  }
22
18
  export = SentinelReporter;
package/dist/reporter.js CHANGED
@@ -1,33 +1,16 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- const path_1 = __importDefault(require("path"));
6
- const url_1 = require("url");
7
2
  const node_1 = require("@sentinelqa/uploader/node");
8
3
  const env_1 = require("./env");
9
- const localReport_1 = require("./localReport");
10
4
  const quickDiagnosis_1 = require("./quickDiagnosis");
11
5
  const { sentinelCaptureFailureContextFromReporter } = require("@sentinelqa/uploader/playwright");
12
- const pluralize = (count, singular, plural) => {
13
- return count === 1 ? singular : plural;
14
- };
15
- const formatTerminalLink = (label, target) => {
16
- if (!process.stdout.isTTY)
17
- return label;
18
- return `\u001B]8;;${target}\u0007${label}\u001B]8;;\u0007`;
19
- };
20
6
  const colorize = (value, code) => {
21
7
  if (!process.stdout.isTTY)
22
8
  return value;
23
9
  return `\u001b[${code}m${value}\u001b[0m`;
24
10
  };
25
- const bold = (value) => colorize(value, "1");
26
11
  const green = (value) => colorize(value, "32");
27
- const cyan = (value) => colorize(value, "36");
28
12
  const yellow = (value) => colorize(value, "33");
29
13
  const dim = (value) => colorize(value, "2");
30
- const magenta = (value) => colorize(value, "35");
31
14
  class SentinelReporter {
32
15
  constructor(options) {
33
16
  this.failedCount = 0;
@@ -59,75 +42,21 @@ class SentinelReporter {
59
42
  this.failedCount += 1;
60
43
  }
61
44
  }
62
- printLocalReport(localReport) {
63
- const localReportPath = localReport.htmlPath;
64
- const relativeReportPath = path_1.default
65
- .relative(process.cwd(), localReportPath)
66
- .replace(/\\/g, "/");
67
- const displayPath = relativeReportPath.startsWith(".")
68
- ? relativeReportPath
69
- : `./${relativeReportPath}`;
70
- const openCommand = `open ${displayPath}`;
45
+ async onEnd() {
71
46
  console.log("");
72
47
  console.log(green("✔ Artifacts collected"));
73
- console.log(green("✔ Sentinel HTML debugging report created"));
74
- console.log("");
75
- console.log(bold("Report"));
76
- console.log(` ${cyan(formatTerminalLink(displayPath, (0, url_1.pathToFileURL)(localReportPath).href))}`);
77
- console.log("");
78
- console.log(bold("Open"));
79
- console.log(` ${cyan(openCommand)}`);
80
- console.log("");
81
48
  const quickDiagnosis = (0, quickDiagnosis_1.buildQuickDiagnosis)(this.options.playwrightJsonPath);
82
49
  if (quickDiagnosis?.lines.length) {
50
+ console.log("");
83
51
  console.log(yellow("Quick diagnosis"));
84
52
  for (const line of quickDiagnosis.lines) {
85
53
  console.log(` ${dim(line)}`);
86
54
  }
87
- console.log("");
88
- }
89
- if (localReport.runDiff) {
90
- console.log(yellow("Run-to-run diff"));
91
- console.log(` ${dim(`New failures: ${localReport.runDiff.newFailures.length}`)}`);
92
- console.log(` ${dim(`Fixed since last run: ${localReport.runDiff.fixedTests.length}`)}`);
93
- console.log(` ${dim(`Still failing: ${localReport.runDiff.stillFailing.length}`)}`);
94
- console.log("");
95
- }
96
- console.log(yellow("Tip"));
97
- console.log(` ${dim("Want full AI analysis, shareable run links, and CI history?")}`);
98
- console.log(` ${dim("Try Sentinel Cloud Beta free:")} ${cyan(formatTerminalLink("https://sentinelqa.com", "https://sentinelqa.com"))}`);
99
- console.log("");
100
- console.log(` ${magenta("★ If this reporter helped you debug faster,")}`);
101
- console.log(` ${dim("consider starring the project:")}`);
102
- console.log(` ${cyan(formatTerminalLink("https://github.com/adnangradascevic/playwright-reporter", "https://github.com/adnangradascevic/playwright-reporter"))}`);
103
- }
104
- async onEnd() {
105
- const hasSentinelToken = Boolean(process.env.SENTINEL_TOKEN);
106
- const hasCiEnv = (0, node_1.hasSupportedCiEnv)(process.env);
107
- const localUploadEnabled = (0, node_1.isLocalUploadEnabled)(process.env);
108
- if (!hasSentinelToken || (!hasCiEnv && !localUploadEnabled)) {
109
- const localReport = (0, localReport_1.generateLocalDebugReport)({
110
- playwrightJsonPath: this.options.playwrightJsonPath,
111
- playwrightReportDir: this.options.playwrightReportDir,
112
- testResultsDir: this.options.testResultsDir,
113
- artifactDirs: this.options.artifactDirs || [],
114
- reportDir: this.options.localReportDir,
115
- reportFileName: this.options.localReportFileName,
116
- redirectFileName: this.options.localRedirectFileName
117
- });
118
- this.printLocalReport(localReport);
119
- console.log("");
120
- if (hasSentinelToken && !hasCiEnv && !localUploadEnabled) {
121
- console.log("Sentinel upload skipped for this local run.");
122
- console.log("To upload local runs, set SENTINEL_UPLOAD_LOCAL=1 and provide the required CI metadata.");
123
- console.log("");
124
- }
125
- return;
126
55
  }
127
56
  console.log("");
128
- console.log("Uploading failure artifacts to Sentinel...");
57
+ console.log("Uploading hosted debugging report to Sentinel...");
129
58
  console.log("");
130
- const exitCode = await (0, node_1.runSentinelUpload)({
59
+ const upload = await (0, node_1.runSentinelUpload)({
131
60
  playwrightJsonPath: this.options.playwrightJsonPath,
132
61
  playwrightReportDir: this.options.playwrightReportDir,
133
62
  testResultsDir: this.options.testResultsDir,
@@ -137,11 +66,19 @@ class SentinelReporter {
137
66
  SENTINEL_REPORTER_PROJECT: this.options.project || undefined
138
67
  }
139
68
  });
140
- if (exitCode !== 0) {
141
- throw new Error(`Sentinel upload failed with exit code ${exitCode}`);
69
+ if (upload.exitCode !== 0) {
70
+ throw new Error(`Sentinel upload failed with exit code ${upload.exitCode}`);
142
71
  }
143
72
  console.log("");
144
- console.log("✔ Uploaded run to Sentinel");
73
+ console.log("✔ Hosted report uploaded to Sentinel");
74
+ if (upload.shareRunUrl || upload.internalRunUrl) {
75
+ console.log("");
76
+ console.log("Sentinel report");
77
+ console.log(` ${upload.shareRunUrl || upload.internalRunUrl}`);
78
+ if (upload.shareLabel) {
79
+ console.log(` ${dim(upload.shareLabel)}`);
80
+ }
81
+ }
145
82
  }
146
83
  }
147
84
  module.exports = SentinelReporter;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentinelqa/playwright-reporter",
3
- "version": "0.1.30",
3
+ "version": "0.1.32",
4
4
  "private": false,
5
5
  "description": "Playwright reporter for CI debugging with optional Sentinel cloud dashboards",
6
6
  "license": "MIT",