@ciach/playwright-private-reporter 0.1.1 → 0.1.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.
Files changed (64) hide show
  1. package/README.md +49 -1
  2. package/dist/cjs/cli/generateReport.d.ts.map +1 -1
  3. package/dist/cjs/cli/generateReport.js +41 -2
  4. package/dist/cjs/cli/generateReport.js.map +1 -1
  5. package/dist/cjs/index.d.ts +2 -1
  6. package/dist/cjs/index.d.ts.map +1 -1
  7. package/dist/cjs/index.js +5 -1
  8. package/dist/cjs/index.js.map +1 -1
  9. package/dist/cjs/reporter/summary.d.ts.map +1 -1
  10. package/dist/cjs/reporter/summary.js +5 -0
  11. package/dist/cjs/reporter/summary.js.map +1 -1
  12. package/dist/cjs/templates/shared.d.ts +4 -0
  13. package/dist/cjs/templates/shared.d.ts.map +1 -0
  14. package/dist/cjs/templates/shared.js +20 -0
  15. package/dist/cjs/templates/shared.js.map +1 -0
  16. package/dist/cjs/templates/summary.classic.d.ts +3 -0
  17. package/dist/cjs/templates/summary.classic.d.ts.map +1 -0
  18. package/dist/cjs/templates/summary.classic.js +60 -0
  19. package/dist/cjs/templates/summary.classic.js.map +1 -0
  20. package/dist/cjs/templates/summary.html.d.ts +5 -2
  21. package/dist/cjs/templates/summary.html.d.ts.map +1 -1
  22. package/dist/cjs/templates/summary.html.js +32 -58
  23. package/dist/cjs/templates/summary.html.js.map +1 -1
  24. package/dist/cjs/templates/summary.modern.d.ts +3 -0
  25. package/dist/cjs/templates/summary.modern.d.ts.map +1 -0
  26. package/dist/cjs/templates/summary.modern.js +543 -0
  27. package/dist/cjs/templates/summary.modern.js.map +1 -0
  28. package/dist/cjs/types/schema.d.ts +22 -0
  29. package/dist/cjs/types/schema.d.ts.map +1 -1
  30. package/dist/esm/cli/generateReport.d.ts.map +1 -1
  31. package/dist/esm/cli/generateReport.js +41 -3
  32. package/dist/esm/cli/generateReport.js.map +1 -1
  33. package/dist/esm/index.d.ts +2 -1
  34. package/dist/esm/index.d.ts.map +1 -1
  35. package/dist/esm/index.js +1 -0
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/esm/reporter/summary.d.ts.map +1 -1
  38. package/dist/esm/reporter/summary.js +5 -0
  39. package/dist/esm/reporter/summary.js.map +1 -1
  40. package/dist/esm/templates/shared.d.ts +4 -0
  41. package/dist/esm/templates/shared.d.ts.map +1 -0
  42. package/dist/esm/templates/shared.js +15 -0
  43. package/dist/esm/templates/shared.js.map +1 -0
  44. package/dist/esm/templates/summary.classic.d.ts +3 -0
  45. package/dist/esm/templates/summary.classic.d.ts.map +1 -0
  46. package/dist/esm/templates/summary.classic.js +57 -0
  47. package/dist/esm/templates/summary.classic.js.map +1 -0
  48. package/dist/esm/templates/summary.html.d.ts +5 -2
  49. package/dist/esm/templates/summary.html.d.ts.map +1 -1
  50. package/dist/esm/templates/summary.html.js +30 -58
  51. package/dist/esm/templates/summary.html.js.map +1 -1
  52. package/dist/esm/templates/summary.modern.d.ts +3 -0
  53. package/dist/esm/templates/summary.modern.d.ts.map +1 -0
  54. package/dist/esm/templates/summary.modern.js +540 -0
  55. package/dist/esm/templates/summary.modern.js.map +1 -0
  56. package/dist/esm/types/schema.d.ts +22 -0
  57. package/dist/esm/types/schema.d.ts.map +1 -1
  58. package/examples/playwright.config.ts +1 -0
  59. package/examples/summary-template-minimal.cjs +84 -0
  60. package/examples/summary-template-ops.cjs +131 -0
  61. package/examples/summary-template.cjs +63 -0
  62. package/examples/summary-templates.md +111 -0
  63. package/package.json +1 -1
  64. package/schemas/run.schema.json +191 -42
@@ -0,0 +1,84 @@
1
+ function escapeHtml(value) {
2
+ return String(value ?? '')
3
+ .replaceAll('&', '&')
4
+ .replaceAll('<', '&lt;')
5
+ .replaceAll('>', '&gt;')
6
+ .replaceAll('"', '&quot;')
7
+ .replaceAll("'", '&#39;');
8
+ }
9
+
10
+ exports.renderSummary = ({ title, runSummary, failuresSummary, artifactLinks }) => `<!DOCTYPE html>
11
+ <html lang="en">
12
+ <head>
13
+ <meta charset="utf-8" />
14
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
15
+ <title>${escapeHtml(title)}</title>
16
+ <style>
17
+ body {
18
+ margin: 0;
19
+ padding: 24px;
20
+ font-family: system-ui, sans-serif;
21
+ background: #f8fafc;
22
+ color: #0f172a;
23
+ }
24
+ main {
25
+ max-width: 760px;
26
+ margin: 0 auto;
27
+ background: #ffffff;
28
+ border: 1px solid #e2e8f0;
29
+ border-radius: 16px;
30
+ padding: 24px;
31
+ }
32
+ .stats {
33
+ display: grid;
34
+ grid-template-columns: repeat(4, minmax(0, 1fr));
35
+ gap: 12px;
36
+ margin: 20px 0;
37
+ }
38
+ .stat {
39
+ padding: 12px;
40
+ border-radius: 12px;
41
+ background: #f8fafc;
42
+ border: 1px solid #e2e8f0;
43
+ }
44
+ .stat strong {
45
+ display: block;
46
+ margin-top: 6px;
47
+ font-size: 1.5rem;
48
+ }
49
+ ul { padding-left: 20px; }
50
+ a { color: #0f766e; }
51
+ code {
52
+ background: #e2e8f0;
53
+ border-radius: 6px;
54
+ padding: 2px 6px;
55
+ }
56
+ @media (max-width: 640px) {
57
+ body { padding: 12px; }
58
+ .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
59
+ }
60
+ </style>
61
+ </head>
62
+ <body>
63
+ <main>
64
+ <h1>${escapeHtml(title)}</h1>
65
+ <p>Status: <strong>${escapeHtml(runSummary.run.status)}</strong></p>
66
+ <div class="stats">
67
+ <div class="stat"><span>Passed</span><strong>${runSummary.counts.passed}</strong></div>
68
+ <div class="stat"><span>Failed</span><strong>${runSummary.counts.failed}</strong></div>
69
+ <div class="stat"><span>Flaky</span><strong>${runSummary.counts.flaky}</strong></div>
70
+ <div class="stat"><span>Groups</span><strong>${failuresSummary.groups.length}</strong></div>
71
+ </div>
72
+ <h2>Top failures</h2>
73
+ <ul>
74
+ ${failuresSummary.groups.slice(0, 5).map((group) => `<li><strong>${escapeHtml(group.title)}</strong> <code>${escapeHtml(group.fingerprint)}</code></li>`).join('') || '<li>No failing groups</li>'}
75
+ </ul>
76
+ <h2>Artifacts</h2>
77
+ <ul>
78
+ <li><a href="${escapeHtml(artifactLinks.playwrightReport)}">Playwright report</a></li>
79
+ <li><a href="${escapeHtml(artifactLinks.junit)}">JUnit XML</a></li>
80
+ <li><a href="${escapeHtml(artifactLinks.testResults)}">Test results</a></li>
81
+ </ul>
82
+ </main>
83
+ </body>
84
+ </html>`;
@@ -0,0 +1,131 @@
1
+ function escapeHtml(value) {
2
+ return String(value ?? '')
3
+ .replaceAll('&', '&amp;')
4
+ .replaceAll('<', '&lt;')
5
+ .replaceAll('>', '&gt;')
6
+ .replaceAll('"', '&quot;')
7
+ .replaceAll("'", '&#39;');
8
+ }
9
+
10
+ function renderFailure(group) {
11
+ return `
12
+ <details class="failure" open>
13
+ <summary>
14
+ <span class="title">${escapeHtml(group.title)}</span>
15
+ <span class="meta">${group.countInRun}x</span>
16
+ </summary>
17
+ <div class="body">
18
+ <p><strong>Fingerprint:</strong> <code>${escapeHtml(group.fingerprint)}</code></p>
19
+ <p><strong>File:</strong> ${escapeHtml(group.testFile)}</p>
20
+ <pre>${escapeHtml(group.normalizedMessage)}</pre>
21
+ </div>
22
+ </details>`;
23
+ }
24
+
25
+ exports.renderSummary = ({ title, runSummary, failuresSummary, diff }) => `<!DOCTYPE html>
26
+ <html lang="en">
27
+ <head>
28
+ <meta charset="utf-8" />
29
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
30
+ <title>${escapeHtml(title)}</title>
31
+ <style>
32
+ :root {
33
+ --bg: #10151c;
34
+ --panel: #17202b;
35
+ --panel-strong: #1f2a37;
36
+ --ink: #e5edf5;
37
+ --muted: #94a3b8;
38
+ --danger: #f87171;
39
+ --warning: #fbbf24;
40
+ --success: #34d399;
41
+ --line: rgba(148, 163, 184, 0.18);
42
+ }
43
+ body {
44
+ margin: 0;
45
+ padding: 20px;
46
+ font-family: "IBM Plex Sans", system-ui, sans-serif;
47
+ background: radial-gradient(circle at top, #182433 0%, var(--bg) 60%);
48
+ color: var(--ink);
49
+ }
50
+ main { max-width: 1080px; margin: 0 auto; }
51
+ .hero, .panel {
52
+ background: rgba(23, 32, 43, 0.92);
53
+ border: 1px solid var(--line);
54
+ border-radius: 18px;
55
+ padding: 20px;
56
+ box-shadow: 0 18px 40px rgba(0, 0, 0, 0.24);
57
+ }
58
+ .metrics {
59
+ display: grid;
60
+ grid-template-columns: repeat(4, minmax(0, 1fr));
61
+ gap: 12px;
62
+ margin-top: 16px;
63
+ }
64
+ .metric {
65
+ background: var(--panel-strong);
66
+ border: 1px solid var(--line);
67
+ border-radius: 14px;
68
+ padding: 14px;
69
+ }
70
+ .metric strong {
71
+ display: block;
72
+ margin-top: 8px;
73
+ font-size: 1.8rem;
74
+ }
75
+ .danger strong { color: var(--danger); }
76
+ .warning strong { color: var(--warning); }
77
+ .success strong { color: var(--success); }
78
+ .stack { margin-top: 16px; display: grid; gap: 12px; }
79
+ .failure {
80
+ background: var(--panel);
81
+ border: 1px solid var(--line);
82
+ border-radius: 14px;
83
+ }
84
+ .failure summary {
85
+ cursor: pointer;
86
+ list-style: none;
87
+ display: flex;
88
+ justify-content: space-between;
89
+ gap: 12px;
90
+ padding: 14px 16px;
91
+ }
92
+ .failure .body {
93
+ border-top: 1px solid var(--line);
94
+ padding: 14px 16px 16px;
95
+ }
96
+ .failure pre {
97
+ white-space: pre-wrap;
98
+ background: #0b1220;
99
+ border-radius: 10px;
100
+ padding: 12px;
101
+ overflow: auto;
102
+ }
103
+ code {
104
+ background: #0b1220;
105
+ border-radius: 6px;
106
+ padding: 2px 6px;
107
+ }
108
+ .meta { color: var(--muted); }
109
+ @media (max-width: 720px) {
110
+ .metrics { grid-template-columns: repeat(2, minmax(0, 1fr)); }
111
+ }
112
+ </style>
113
+ </head>
114
+ <body>
115
+ <main>
116
+ <section class="hero">
117
+ <p class="meta">Operations / incident-focused summary</p>
118
+ <h1>${escapeHtml(title)}</h1>
119
+ <div class="metrics">
120
+ <div class="metric danger"><span>Failed</span><strong>${runSummary.counts.failed}</strong></div>
121
+ <div class="metric warning"><span>New</span><strong>${diff ? diff.newFailures.length : runSummary.history.newFailures}</strong></div>
122
+ <div class="metric warning"><span>Still failing</span><strong>${diff ? diff.stillFailing.length : runSummary.history.stillFailing}</strong></div>
123
+ <div class="metric success"><span>Fixed</span><strong>${diff ? diff.fixedFailures.length : runSummary.history.fixedFailures}</strong></div>
124
+ </div>
125
+ </section>
126
+ <section class="panel stack">
127
+ ${failuresSummary.groups.slice(0, 10).map(renderFailure).join('') || '<p>No failing groups</p>'}
128
+ </section>
129
+ </main>
130
+ </body>
131
+ </html>`;
@@ -0,0 +1,63 @@
1
+ exports.renderSummary = ({ title, runSummary, failuresSummary, diff, artifactLinks }) => `<!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>${title}</title>
7
+ <style>
8
+ body {
9
+ margin: 0;
10
+ font-family: Georgia, "Times New Roman", serif;
11
+ color: #1b1f23;
12
+ background: linear-gradient(180deg, #fdf8ef 0%, #f3ece0 100%);
13
+ }
14
+ main {
15
+ width: min(880px, calc(100% - 2rem));
16
+ margin: 2rem auto;
17
+ padding: 2rem;
18
+ background: rgba(255, 255, 255, 0.9);
19
+ border: 1px solid rgba(27, 31, 35, 0.12);
20
+ border-radius: 24px;
21
+ }
22
+ h1 { margin-top: 0; font-size: 2.5rem; }
23
+ .lead { color: #5c6670; }
24
+ .grid {
25
+ display: grid;
26
+ grid-template-columns: repeat(3, minmax(0, 1fr));
27
+ gap: 1rem;
28
+ margin-top: 1.5rem;
29
+ }
30
+ .card {
31
+ padding: 1rem;
32
+ border-radius: 16px;
33
+ background: #fff;
34
+ border: 1px solid rgba(27, 31, 35, 0.1);
35
+ }
36
+ .card strong {
37
+ display: block;
38
+ margin-top: 0.4rem;
39
+ font-size: 1.8rem;
40
+ }
41
+ ul { line-height: 1.6; }
42
+ a { color: #0f766e; }
43
+ @media (max-width: 720px) { .grid { grid-template-columns: 1fr; } }
44
+ </style>
45
+ </head>
46
+ <body>
47
+ <main>
48
+ <h1>${title}</h1>
49
+ <p class="lead">Custom template module example. New failures: ${diff ? diff.newFailures.length : 0}.</p>
50
+ <div class="grid">
51
+ <div class="card"><span>Status</span><strong>${runSummary.run.status}</strong></div>
52
+ <div class="card"><span>Failed</span><strong>${runSummary.counts.failed}</strong></div>
53
+ <div class="card"><span>Failure groups</span><strong>${failuresSummary.groups.length}</strong></div>
54
+ </div>
55
+ <h2>Artifacts</h2>
56
+ <ul>
57
+ <li><a href="${artifactLinks.playwrightReport}">Playwright report</a></li>
58
+ <li><a href="${artifactLinks.junit}">JUnit XML</a></li>
59
+ <li><a href="${artifactLinks.testResults}">Test results</a></li>
60
+ </ul>
61
+ </main>
62
+ </body>
63
+ </html>`;
@@ -0,0 +1,111 @@
1
+ # Summary Template Guide
2
+
3
+ This package supports pluggable HTML summary templates. The Playwright reporter still writes JSON first, and the HTML gets generated later by `generateReport()`. That means you can redesign the summary without changing the failure collection logic.
4
+
5
+ ## What a template module looks like
6
+
7
+ Use a local `.js`, `.mjs`, or `.cjs` file that exports either:
8
+
9
+ - `default`
10
+ - `renderSummary`
11
+
12
+ The export must be a function that returns an HTML string.
13
+
14
+ ```js
15
+ exports.renderSummary = (context) => '<!DOCTYPE html><html>...</html>';
16
+ ```
17
+
18
+ ## Context passed to the template
19
+
20
+ The renderer receives a single `context` object with:
21
+
22
+ - `title`: final page title used for the summary.
23
+ - `theme`: resolved built-in theme name, either `classic` or `modern`.
24
+ - `runSummary`: parsed `run.json` payload.
25
+ - `failuresSummary`: parsed `failures.json` payload.
26
+ - `diff`: history diff when a previous failures file was provided.
27
+ - `artifactLinks`: relative links for Playwright HTML, JUnit XML, and retained test results.
28
+
29
+ ## How to enable a template
30
+
31
+ In Playwright config:
32
+
33
+ ```ts
34
+ import { defineConfig } from '@playwright/test';
35
+ import { withPrivateReporter } from '@ciach/playwright-private-reporter';
36
+
37
+ export default withPrivateReporter(
38
+ defineConfig({}),
39
+ {
40
+ projectName: 'payments-ui',
41
+ summaryTemplatePath: './reporting/summary-template.mjs',
42
+ },
43
+ );
44
+ ```
45
+
46
+ From the standalone CLI:
47
+
48
+ ```bash
49
+ PRIVATE_REPORT_SUMMARY_TEMPLATE_PATH=./reporting/summary-template.mjs \
50
+ npx playwright-private-reporter-generate
51
+ ```
52
+
53
+ ## Recommended template rules
54
+
55
+ - Escape any user-controlled text before interpolating it into HTML.
56
+ - Keep the output fully self-contained: inline CSS, no external assets.
57
+ - Use `artifactLinks` rather than hard-coding report paths.
58
+ - Prefer grouped failures over raw test lists on the first screen.
59
+ - Use collapsible sections when you expose stack traces or large attachment lists.
60
+
61
+ ## Built-in themes vs custom templates
62
+
63
+ Built-ins are faster when you only want a visual direction:
64
+
65
+ - `summaryTheme: 'classic'` keeps a compact layout close to the original template.
66
+ - `summaryTheme: 'modern'` adds stronger hierarchy, cards, artifact navigation, and collapsible failure groups.
67
+
68
+ Use a custom template when you need:
69
+
70
+ - brand-specific styling,
71
+ - very different failure layouts,
72
+ - executive summaries,
73
+ - incident-response dashboards,
74
+ - consumer-specific artifact ordering.
75
+
76
+ ## Ready-to-copy examples
77
+
78
+ Three example templates are included in this folder:
79
+
80
+ 1. `summary-template.cjs`
81
+ A polished card-based summary for stakeholder-facing CI pages.
82
+
83
+ 2. `summary-template-minimal.cjs`
84
+ A compact low-friction summary for teams that want very little styling.
85
+
86
+ 3. `summary-template-ops.cjs`
87
+ A darker incident-focused summary that keeps the most important failures open by default.
88
+
89
+ ## Wrapping a built-in theme
90
+
91
+ You can also import a built-in renderer and extend it instead of starting from zero:
92
+
93
+ ```ts
94
+ import { renderModernSummaryHtml } from '@ciach/playwright-private-reporter';
95
+
96
+ export function renderSummary(context) {
97
+ return renderModernSummaryHtml({
98
+ ...context,
99
+ title: `${context.title} / Custom Brand`,
100
+ });
101
+ }
102
+ ```
103
+
104
+ ## Debugging template loading
105
+
106
+ If a template fails to load, check these first:
107
+
108
+ - the path is resolved from the current working directory,
109
+ - the file exports `default` or `renderSummary`,
110
+ - the renderer returns a string,
111
+ - the module syntax matches the file extension.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ciach/playwright-private-reporter",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Jenkins-first Playwright reporting utilities.",
5
5
  "license": "MIT",
6
6
  "author": "ciach",
@@ -3,33 +3,109 @@
3
3
  "$id": "https://your-org.example/schemas/playwright-private-reporter/run.schema.json",
4
4
  "title": "Private Reporter Run Summary",
5
5
  "type": "object",
6
- "required": ["schemaVersion", "projectName", "generatedAt", "run", "counts", "projects", "history", "artifacts", "failures"],
6
+ "required": [
7
+ "schemaVersion",
8
+ "projectName",
9
+ "generatedAt",
10
+ "run",
11
+ "counts",
12
+ "projects",
13
+ "history",
14
+ "artifacts",
15
+ "failures"
16
+ ],
7
17
  "properties": {
8
- "schemaVersion": { "const": "1.0" },
9
- "projectName": { "type": "string" },
10
- "generatedAt": { "type": "string", "format": "date-time" },
18
+ "schemaVersion": {
19
+ "const": "1.0"
20
+ },
21
+ "projectName": {
22
+ "type": "string"
23
+ },
24
+ "generatedAt": {
25
+ "type": "string",
26
+ "format": "date-time"
27
+ },
28
+ "presentation": {
29
+ "type": "object",
30
+ "properties": {
31
+ "summaryTitle": {
32
+ "type": "string"
33
+ },
34
+ "summaryTheme": {
35
+ "enum": [
36
+ "classic",
37
+ "modern"
38
+ ]
39
+ },
40
+ "summaryTemplatePath": {
41
+ "type": "string"
42
+ }
43
+ },
44
+ "additionalProperties": false
45
+ },
11
46
  "run": {
12
47
  "type": "object",
13
- "required": ["status"],
48
+ "required": [
49
+ "status"
50
+ ],
14
51
  "properties": {
15
- "status": { "enum": ["passed", "failed", "partial"] },
16
- "buildId": { "type": "string" },
17
- "buildUrl": { "type": "string" },
18
- "branch": { "type": "string" },
19
- "commit": { "type": "string" }
52
+ "status": {
53
+ "enum": [
54
+ "passed",
55
+ "failed",
56
+ "partial"
57
+ ]
58
+ },
59
+ "buildId": {
60
+ "type": "string"
61
+ },
62
+ "buildUrl": {
63
+ "type": "string"
64
+ },
65
+ "branch": {
66
+ "type": "string"
67
+ },
68
+ "commit": {
69
+ "type": "string"
70
+ }
20
71
  },
21
72
  "additionalProperties": false
22
73
  },
23
74
  "counts": {
24
75
  "type": "object",
25
- "required": ["passed", "failed", "skipped", "flaky", "timedOut", "interrupted"],
76
+ "required": [
77
+ "passed",
78
+ "failed",
79
+ "skipped",
80
+ "flaky",
81
+ "timedOut",
82
+ "interrupted"
83
+ ],
26
84
  "properties": {
27
- "passed": { "type": "integer", "minimum": 0 },
28
- "failed": { "type": "integer", "minimum": 0 },
29
- "skipped": { "type": "integer", "minimum": 0 },
30
- "flaky": { "type": "integer", "minimum": 0 },
31
- "timedOut": { "type": "integer", "minimum": 0 },
32
- "interrupted": { "type": "integer", "minimum": 0 }
85
+ "passed": {
86
+ "type": "integer",
87
+ "minimum": 0
88
+ },
89
+ "failed": {
90
+ "type": "integer",
91
+ "minimum": 0
92
+ },
93
+ "skipped": {
94
+ "type": "integer",
95
+ "minimum": 0
96
+ },
97
+ "flaky": {
98
+ "type": "integer",
99
+ "minimum": 0
100
+ },
101
+ "timedOut": {
102
+ "type": "integer",
103
+ "minimum": 0
104
+ },
105
+ "interrupted": {
106
+ "type": "integer",
107
+ "minimum": 0
108
+ }
33
109
  },
34
110
  "additionalProperties": false
35
111
  },
@@ -37,44 +113,92 @@
37
113
  "type": "array",
38
114
  "items": {
39
115
  "type": "object",
40
- "required": ["name", "counts"],
116
+ "required": [
117
+ "name",
118
+ "counts"
119
+ ],
41
120
  "properties": {
42
- "name": { "type": "string" },
43
- "counts": { "$ref": "#/$defs/counts" }
121
+ "name": {
122
+ "type": "string"
123
+ },
124
+ "counts": {
125
+ "$ref": "#/$defs/counts"
126
+ }
44
127
  },
45
128
  "additionalProperties": false
46
129
  }
47
130
  },
48
131
  "history": {
49
132
  "type": "object",
50
- "required": ["enabled", "newFailures", "fixedFailures", "stillFailing"],
133
+ "required": [
134
+ "enabled",
135
+ "newFailures",
136
+ "fixedFailures",
137
+ "stillFailing"
138
+ ],
51
139
  "properties": {
52
- "enabled": { "type": "boolean" },
53
- "previousBuildId": { "type": "string" },
54
- "newFailures": { "type": "integer", "minimum": 0 },
55
- "fixedFailures": { "type": "integer", "minimum": 0 },
56
- "stillFailing": { "type": "integer", "minimum": 0 }
140
+ "enabled": {
141
+ "type": "boolean"
142
+ },
143
+ "previousBuildId": {
144
+ "type": "string"
145
+ },
146
+ "newFailures": {
147
+ "type": "integer",
148
+ "minimum": 0
149
+ },
150
+ "fixedFailures": {
151
+ "type": "integer",
152
+ "minimum": 0
153
+ },
154
+ "stillFailing": {
155
+ "type": "integer",
156
+ "minimum": 0
157
+ }
57
158
  },
58
159
  "additionalProperties": false
59
160
  },
60
161
  "artifacts": {
61
162
  "type": "object",
62
- "required": ["blobReportDir", "playwrightHtmlDir", "testResultsDir", "junitPath", "internalReportDir"],
163
+ "required": [
164
+ "blobReportDir",
165
+ "playwrightHtmlDir",
166
+ "testResultsDir",
167
+ "junitPath",
168
+ "internalReportDir"
169
+ ],
63
170
  "properties": {
64
- "blobReportDir": { "type": "string" },
65
- "playwrightHtmlDir": { "type": "string" },
66
- "testResultsDir": { "type": "string" },
67
- "junitPath": { "type": "string" },
68
- "internalReportDir": { "type": "string" }
171
+ "blobReportDir": {
172
+ "type": "string"
173
+ },
174
+ "playwrightHtmlDir": {
175
+ "type": "string"
176
+ },
177
+ "testResultsDir": {
178
+ "type": "string"
179
+ },
180
+ "junitPath": {
181
+ "type": "string"
182
+ },
183
+ "internalReportDir": {
184
+ "type": "string"
185
+ }
69
186
  },
70
187
  "additionalProperties": false
71
188
  },
72
189
  "failures": {
73
190
  "type": "object",
74
- "required": ["totalGroups"],
191
+ "required": [
192
+ "totalGroups"
193
+ ],
75
194
  "properties": {
76
- "totalGroups": { "type": "integer", "minimum": 0 },
77
- "topFingerprint": { "type": "string" }
195
+ "totalGroups": {
196
+ "type": "integer",
197
+ "minimum": 0
198
+ },
199
+ "topFingerprint": {
200
+ "type": "string"
201
+ }
78
202
  },
79
203
  "additionalProperties": false
80
204
  }
@@ -82,14 +206,39 @@
82
206
  "$defs": {
83
207
  "counts": {
84
208
  "type": "object",
85
- "required": ["passed", "failed", "skipped", "flaky", "timedOut", "interrupted"],
209
+ "required": [
210
+ "passed",
211
+ "failed",
212
+ "skipped",
213
+ "flaky",
214
+ "timedOut",
215
+ "interrupted"
216
+ ],
86
217
  "properties": {
87
- "passed": { "type": "integer", "minimum": 0 },
88
- "failed": { "type": "integer", "minimum": 0 },
89
- "skipped": { "type": "integer", "minimum": 0 },
90
- "flaky": { "type": "integer", "minimum": 0 },
91
- "timedOut": { "type": "integer", "minimum": 0 },
92
- "interrupted": { "type": "integer", "minimum": 0 }
218
+ "passed": {
219
+ "type": "integer",
220
+ "minimum": 0
221
+ },
222
+ "failed": {
223
+ "type": "integer",
224
+ "minimum": 0
225
+ },
226
+ "skipped": {
227
+ "type": "integer",
228
+ "minimum": 0
229
+ },
230
+ "flaky": {
231
+ "type": "integer",
232
+ "minimum": 0
233
+ },
234
+ "timedOut": {
235
+ "type": "integer",
236
+ "minimum": 0
237
+ },
238
+ "interrupted": {
239
+ "type": "integer",
240
+ "minimum": 0
241
+ }
93
242
  },
94
243
  "additionalProperties": false
95
244
  }