@ciach/playwright-private-reporter 0.1.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 (105) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -0
  3. package/dist/cjs/bin/generate-report.d.ts +3 -0
  4. package/dist/cjs/bin/generate-report.d.ts.map +1 -0
  5. package/dist/cjs/bin/generate-report.js +6 -0
  6. package/dist/cjs/bin/generate-report.js.map +1 -0
  7. package/dist/cjs/cli/generateReport.d.ts +11 -0
  8. package/dist/cjs/cli/generateReport.d.ts.map +1 -0
  9. package/dist/cjs/cli/generateReport.js +56 -0
  10. package/dist/cjs/cli/generateReport.js.map +1 -0
  11. package/dist/cjs/config/withPrivateReporter.d.ts +4 -0
  12. package/dist/cjs/config/withPrivateReporter.d.ts.map +1 -0
  13. package/dist/cjs/config/withPrivateReporter.js +41 -0
  14. package/dist/cjs/config/withPrivateReporter.js.map +1 -0
  15. package/dist/cjs/history/diffRuns.d.ts +3 -0
  16. package/dist/cjs/history/diffRuns.d.ts.map +1 -0
  17. package/dist/cjs/history/diffRuns.js +16 -0
  18. package/dist/cjs/history/diffRuns.js.map +1 -0
  19. package/dist/cjs/history/loadPrevious.d.ts +4 -0
  20. package/dist/cjs/history/loadPrevious.d.ts.map +1 -0
  21. package/dist/cjs/history/loadPrevious.js +24 -0
  22. package/dist/cjs/history/loadPrevious.js.map +1 -0
  23. package/dist/cjs/index.d.ts +9 -0
  24. package/dist/cjs/index.d.ts.map +1 -0
  25. package/dist/cjs/index.js +21 -0
  26. package/dist/cjs/index.js.map +1 -0
  27. package/dist/cjs/package.json +1 -0
  28. package/dist/cjs/reporter/PrivateReporter.d.ts +16 -0
  29. package/dist/cjs/reporter/PrivateReporter.d.ts.map +1 -0
  30. package/dist/cjs/reporter/PrivateReporter.js +109 -0
  31. package/dist/cjs/reporter/PrivateReporter.js.map +1 -0
  32. package/dist/cjs/reporter/attachments.d.ts +9 -0
  33. package/dist/cjs/reporter/attachments.d.ts.map +1 -0
  34. package/dist/cjs/reporter/attachments.js +15 -0
  35. package/dist/cjs/reporter/attachments.js.map +1 -0
  36. package/dist/cjs/reporter/fingerprint.d.ts +12 -0
  37. package/dist/cjs/reporter/fingerprint.d.ts.map +1 -0
  38. package/dist/cjs/reporter/fingerprint.js +37 -0
  39. package/dist/cjs/reporter/fingerprint.js.map +1 -0
  40. package/dist/cjs/reporter/summary.d.ts +25 -0
  41. package/dist/cjs/reporter/summary.d.ts.map +1 -0
  42. package/dist/cjs/reporter/summary.js +105 -0
  43. package/dist/cjs/reporter/summary.js.map +1 -0
  44. package/dist/cjs/templates/summary.html.d.ts +3 -0
  45. package/dist/cjs/templates/summary.html.d.ts.map +1 -0
  46. package/dist/cjs/templates/summary.html.js +64 -0
  47. package/dist/cjs/templates/summary.html.js.map +1 -0
  48. package/dist/cjs/types/schema.d.ts +96 -0
  49. package/dist/cjs/types/schema.d.ts.map +1 -0
  50. package/dist/cjs/types/schema.js +3 -0
  51. package/dist/cjs/types/schema.js.map +1 -0
  52. package/dist/esm/bin/generate-report.d.ts +3 -0
  53. package/dist/esm/bin/generate-report.d.ts.map +1 -0
  54. package/dist/esm/bin/generate-report.js +4 -0
  55. package/dist/esm/bin/generate-report.js.map +1 -0
  56. package/dist/esm/cli/generateReport.d.ts +11 -0
  57. package/dist/esm/cli/generateReport.d.ts.map +1 -0
  58. package/dist/esm/cli/generateReport.js +54 -0
  59. package/dist/esm/cli/generateReport.js.map +1 -0
  60. package/dist/esm/config/withPrivateReporter.d.ts +4 -0
  61. package/dist/esm/config/withPrivateReporter.d.ts.map +1 -0
  62. package/dist/esm/config/withPrivateReporter.js +38 -0
  63. package/dist/esm/config/withPrivateReporter.js.map +1 -0
  64. package/dist/esm/history/diffRuns.d.ts +3 -0
  65. package/dist/esm/history/diffRuns.d.ts.map +1 -0
  66. package/dist/esm/history/diffRuns.js +13 -0
  67. package/dist/esm/history/diffRuns.js.map +1 -0
  68. package/dist/esm/history/loadPrevious.d.ts +4 -0
  69. package/dist/esm/history/loadPrevious.d.ts.map +1 -0
  70. package/dist/esm/history/loadPrevious.js +20 -0
  71. package/dist/esm/history/loadPrevious.js.map +1 -0
  72. package/dist/esm/index.d.ts +9 -0
  73. package/dist/esm/index.d.ts.map +1 -0
  74. package/dist/esm/index.js +8 -0
  75. package/dist/esm/index.js.map +1 -0
  76. package/dist/esm/package.json +1 -0
  77. package/dist/esm/reporter/PrivateReporter.d.ts +16 -0
  78. package/dist/esm/reporter/PrivateReporter.d.ts.map +1 -0
  79. package/dist/esm/reporter/PrivateReporter.js +105 -0
  80. package/dist/esm/reporter/PrivateReporter.js.map +1 -0
  81. package/dist/esm/reporter/attachments.d.ts +9 -0
  82. package/dist/esm/reporter/attachments.d.ts.map +1 -0
  83. package/dist/esm/reporter/attachments.js +11 -0
  84. package/dist/esm/reporter/attachments.js.map +1 -0
  85. package/dist/esm/reporter/fingerprint.d.ts +12 -0
  86. package/dist/esm/reporter/fingerprint.d.ts.map +1 -0
  87. package/dist/esm/reporter/fingerprint.js +32 -0
  88. package/dist/esm/reporter/fingerprint.js.map +1 -0
  89. package/dist/esm/reporter/summary.d.ts +25 -0
  90. package/dist/esm/reporter/summary.d.ts.map +1 -0
  91. package/dist/esm/reporter/summary.js +99 -0
  92. package/dist/esm/reporter/summary.js.map +1 -0
  93. package/dist/esm/templates/summary.html.d.ts +3 -0
  94. package/dist/esm/templates/summary.html.d.ts.map +1 -0
  95. package/dist/esm/templates/summary.html.js +61 -0
  96. package/dist/esm/templates/summary.html.js.map +1 -0
  97. package/dist/esm/types/schema.d.ts +96 -0
  98. package/dist/esm/types/schema.d.ts.map +1 -0
  99. package/dist/esm/types/schema.js +2 -0
  100. package/dist/esm/types/schema.js.map +1 -0
  101. package/examples/Jenkinsfile +82 -0
  102. package/examples/playwright.config.ts +19 -0
  103. package/package.json +78 -0
  104. package/schemas/failures.schema.json +82 -0
  105. package/schemas/run.schema.json +98 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ciach
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # @ciach/playwright-private-reporter
2
+
3
+ Jenkins-first Playwright reporting utilities.
4
+
5
+ ## What it gives you
6
+
7
+ - A `withPrivateReporter()` config wrapper for Playwright projects.
8
+ - A `PrivateReporter` implementation that emits `run.json`, `failures.json`, and `health.json`.
9
+ - A `generateReport` CLI that creates `summary.md` and a static `summary.html` suitable for Jenkins HTML Publisher.
10
+ - JSON schemas and examples for Jenkins + Playwright adoption.
11
+
12
+ ## Installation
13
+
14
+ Add the package to a Playwright repo:
15
+
16
+ ```bash
17
+ npm install --save-dev @ciach/playwright-private-reporter @playwright/test
18
+ ```
19
+
20
+ If your CI image does not already include browsers, install them as part of setup:
21
+
22
+ ```bash
23
+ npx playwright install --with-deps
24
+ ```
25
+
26
+ ## Consumer quick start
27
+
28
+ ### 1. Wrap your Playwright config
29
+
30
+ ```ts
31
+ import { defineConfig } from '@playwright/test';
32
+ import { withPrivateReporter } from '@ciach/playwright-private-reporter';
33
+
34
+ export default withPrivateReporter(
35
+ defineConfig({
36
+ testDir: './tests',
37
+ use: {
38
+ trace: 'retain-on-failure',
39
+ screenshot: 'only-on-failure',
40
+ video: 'retain-on-failure',
41
+ },
42
+ }),
43
+ {
44
+ projectName: 'payments-ui',
45
+ outputDir: 'artifacts',
46
+ enableHistoryDiff: true,
47
+ },
48
+ );
49
+ ```
50
+
51
+ See the full example in `examples/playwright.config.ts`.
52
+
53
+ ### 2. Run Playwright locally
54
+
55
+ ```bash
56
+ npx playwright test
57
+ npx playwright show-report
58
+ ```
59
+
60
+ Local runs keep developer-friendly terminal/html reporters. CI adds blob + JUnit + the private reporter automatically.
61
+
62
+ ### 3. Generate the Jenkins artifacts in CI
63
+
64
+ Run tests first:
65
+
66
+ ```bash
67
+ npx playwright test
68
+ ```
69
+
70
+ Merge sharded blob reports into HTML:
71
+
72
+ ```bash
73
+ npx playwright merge-reports --reporter html ./all-blob-reports
74
+ ```
75
+
76
+ Generate the private summary artifacts:
77
+
78
+ ```bash
79
+ npx playwright-private-reporter-generate
80
+ ```
81
+
82
+ ### 4. Publish from Jenkins
83
+
84
+ Use the example pipeline in `examples/Jenkinsfile` to:
85
+
86
+ - publish JUnit XML,
87
+ - publish `artifacts/internal-report/summary.html`,
88
+ - publish the merged `playwright-report/index.html`, and
89
+ - archive traces, screenshots, videos, blob zips, and XML.
90
+
91
+ ## Output files
92
+
93
+ After a CI run, expect these artifacts:
94
+
95
+ - `blob-report/`
96
+ - `playwright-report/`
97
+ - `artifacts/test-results/`
98
+ - `junit/results.xml`
99
+ - `artifacts/internal-report/run.json`
100
+ - `artifacts/internal-report/failures.json`
101
+ - `artifacts/internal-report/health.json`
102
+ - `artifacts/internal-report/summary.md`
103
+ - `artifacts/internal-report/summary.html`
104
+
105
+ ## How to test this package in this repo right now
106
+
107
+ From the repository root:
108
+
109
+ ```bash
110
+ npm run check:schemas
111
+ npm run check:examples
112
+ npm run test:private-reporter
113
+ ```
114
+
115
+ What those do:
116
+
117
+ - `check:schemas` parses the JSON schemas.
118
+ - `check:examples` verifies the example/docs files exist.
119
+ - `test:private-reporter` builds the package and runs the node-based tests for:
120
+ - `withPrivateReporter()` reporter injection,
121
+ - `PrivateReporter` artifact generation, and
122
+ - `generateReport` history-diff summary generation.
123
+
124
+ ## Smoke test in a consumer repo
125
+
126
+ Once installed in an actual Playwright project:
127
+
128
+ 1. add `withPrivateReporter(...)` to your `playwright.config.ts`,
129
+ 2. run `npx playwright test`,
130
+ 3. confirm `junit/results.xml` and `artifacts/internal-report/*.json` exist,
131
+ 4. merge blob reports if you shard on CI, and
132
+ 5. run `npx playwright-private-reporter-generate` to produce `summary.md` and `summary.html`.
133
+
134
+ ## Publishing
135
+
136
+ From the repository root:
137
+
138
+ ```bash
139
+ npm --workspace @ciach/playwright-private-reporter test
140
+ npm publish --workspace @ciach/playwright-private-reporter --access public
141
+ ```
142
+
143
+ `prepack` runs the full test suite before npm creates the publish tarball, so `npm publish` ships freshly built artifacts.
144
+
145
+ ## Example files
146
+ - Playwright config example: `examples/playwright.config.ts`
147
+ - Jenkins pipeline example: `examples/Jenkinsfile`
148
+ - Architecture/build spec: `../../docs/playwright-private-reporter-build-spec.md`
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=generate-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-report.d.ts","sourceRoot":"","sources":["../../../src/bin/generate-report.ts"],"names":[],"mappings":""}
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const generateReport_js_1 = require("../cli/generateReport.js");
5
+ void (0, generateReport_js_1.runFromCli)();
6
+ //# sourceMappingURL=generate-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-report.js","sourceRoot":"","sources":["../../../src/bin/generate-report.ts"],"names":[],"mappings":";;;AAEA,gEAAsD;AAEtD,KAAK,IAAA,8BAAU,GAAE,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { PrivateReporterOptions } from '../types/schema.js';
2
+ export type GenerateReportCliOptions = {
3
+ currentRunPath?: string;
4
+ currentFailuresPath?: string;
5
+ previousFailuresPath?: string;
6
+ outputDir?: string;
7
+ };
8
+ export declare function generateReport(reporterOptions: PrivateReporterOptions, cliOptions?: GenerateReportCliOptions): Promise<void>;
9
+ declare function runFromCli(): Promise<void>;
10
+ export { runFromCli };
11
+ //# sourceMappingURL=generateReport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateReport.d.ts","sourceRoot":"","sources":["../../../src/cli/generateReport.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAmB,sBAAsB,EAAc,MAAM,oBAAoB,CAAC;AAE9F,MAAM,MAAM,wBAAwB,GAAG;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAsB,cAAc,CAClC,eAAe,EAAE,sBAAsB,EACvC,UAAU,GAAE,wBAA6B,GACxC,OAAO,CAAC,IAAI,CAAC,CAwCf;AAED,iBAAe,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CASzC;AAGD,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateReport = generateReport;
4
+ exports.runFromCli = runFromCli;
5
+ const promises_1 = require("node:fs/promises");
6
+ const node_path_1 = require("node:path");
7
+ const loadPrevious_js_1 = require("../history/loadPrevious.js");
8
+ const diffRuns_js_1 = require("../history/diffRuns.js");
9
+ const summary_html_js_1 = require("../templates/summary.html.js");
10
+ async function generateReport(reporterOptions, cliOptions = {}) {
11
+ const currentRunPath = (0, node_path_1.resolve)(cliOptions.currentRunPath ?? 'artifacts/internal-report/run.json');
12
+ const currentFailuresPath = (0, node_path_1.resolve)(cliOptions.currentFailuresPath ?? 'artifacts/internal-report/failures.json');
13
+ const previousFailuresPath = cliOptions.previousFailuresPath
14
+ ? (0, node_path_1.resolve)(cliOptions.previousFailuresPath)
15
+ : undefined;
16
+ const outputDir = (0, node_path_1.resolve)(cliOptions.outputDir ?? 'artifacts/internal-report');
17
+ const runSummary = JSON.parse(await (0, promises_1.readFile)(currentRunPath, 'utf8'));
18
+ const failuresSummary = JSON.parse(await (0, promises_1.readFile)(currentFailuresPath, 'utf8'));
19
+ const previousFailures = previousFailuresPath
20
+ ? await (0, loadPrevious_js_1.loadPreviousFailuresSummary)(previousFailuresPath)
21
+ : undefined;
22
+ const diff = previousFailures ? (0, diffRuns_js_1.diffFailureGroups)(failuresSummary.groups, previousFailures.groups) : undefined;
23
+ if (diff) {
24
+ runSummary.history.newFailures = diff.newFailures.length;
25
+ runSummary.history.fixedFailures = diff.fixedFailures.length;
26
+ runSummary.history.stillFailing = diff.stillFailing.length;
27
+ }
28
+ const markdown = [
29
+ `# ${reporterOptions.summaryTitle ?? reporterOptions.projectName} summary`,
30
+ '',
31
+ `- Status: ${runSummary.run.status}`,
32
+ `- Passed: ${runSummary.counts.passed}`,
33
+ `- Failed: ${runSummary.counts.failed}`,
34
+ `- Failure groups: ${failuresSummary.groups.length}`,
35
+ diff ? `- New failures: ${diff.newFailures.length}` : undefined,
36
+ diff ? `- Fixed failures: ${diff.fixedFailures.length}` : undefined,
37
+ ]
38
+ .filter(Boolean)
39
+ .join('\n');
40
+ await (0, promises_1.mkdir)(outputDir, { recursive: true });
41
+ await Promise.all([
42
+ (0, promises_1.writeFile)((0, node_path_1.resolve)(outputDir, 'run.json'), JSON.stringify(runSummary, null, 2), 'utf8'),
43
+ (0, promises_1.writeFile)((0, node_path_1.resolve)(outputDir, 'summary.md'), markdown, 'utf8'),
44
+ (0, promises_1.writeFile)((0, node_path_1.resolve)(outputDir, 'summary.html'), (0, summary_html_js_1.renderSummaryHtml)(runSummary, failuresSummary), 'utf8'),
45
+ ]);
46
+ }
47
+ async function runFromCli() {
48
+ const projectName = process.env.PRIVATE_REPORT_PROJECT_NAME ?? 'playwright-project';
49
+ await generateReport({
50
+ projectName,
51
+ outputDir: process.env.PRIVATE_REPORT_OUTPUT_DIR ?? 'artifacts',
52
+ summaryTitle: process.env.PRIVATE_REPORT_SUMMARY_TITLE,
53
+ enableHistoryDiff: process.env.PRIVATE_REPORT_ENABLE_HISTORY_DIFF === 'true',
54
+ });
55
+ }
56
+ //# sourceMappingURL=generateReport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generateReport.js","sourceRoot":"","sources":["../../../src/cli/generateReport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { PlaywrightTestConfig } from '@playwright/test';
2
+ import type { PrivateReporterOptions } from '../types/schema.js';
3
+ export declare function withPrivateReporter(baseConfig: PlaywrightTestConfig, options: PrivateReporterOptions): PlaywrightTestConfig;
4
+ //# sourceMappingURL=withPrivateReporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withPrivateReporter.d.ts","sourceRoot":"","sources":["../../../src/config/withPrivateReporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAuB,MAAM,kBAAkB,CAAC;AAElF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAQjE,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,oBAAoB,EAChC,OAAO,EAAE,sBAAsB,GAC9B,oBAAoB,CAqCtB"}
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.withPrivateReporter = withPrivateReporter;
4
+ const DEFAULT_INTERNAL_REPORTER_PATH = '@ciach/playwright-private-reporter';
5
+ function hasReporter(reporters, name) {
6
+ return reporters.some((reporter) => reporter[0] === name);
7
+ }
8
+ function withPrivateReporter(baseConfig, options) {
9
+ const outputDir = options.outputDir ?? 'artifacts';
10
+ const ci = options.ci ?? process.env.CI === 'true';
11
+ const reporters = Array.isArray(baseConfig.reporter)
12
+ ? [...baseConfig.reporter]
13
+ : baseConfig.reporter
14
+ ? [baseConfig.reporter]
15
+ : [];
16
+ if (ci && !hasReporter(reporters, 'blob')) {
17
+ reporters.unshift(['blob', { outputDir: 'blob-report' }]);
18
+ }
19
+ if (!hasReporter(reporters, 'junit')) {
20
+ reporters.push(['junit', { outputFile: 'junit/results.xml' }]);
21
+ }
22
+ if (!hasReporter(reporters, DEFAULT_INTERNAL_REPORTER_PATH)) {
23
+ reporters.push([DEFAULT_INTERNAL_REPORTER_PATH, options]);
24
+ }
25
+ if (!ci && !hasReporter(reporters, 'html') && !hasReporter(reporters, 'list')) {
26
+ reporters.unshift(['list']);
27
+ reporters.push(['html', { outputFolder: 'playwright-report', open: 'never' }]);
28
+ }
29
+ return {
30
+ ...baseConfig,
31
+ outputDir: baseConfig.outputDir ?? `${outputDir}/test-results`,
32
+ reporter: reporters,
33
+ use: {
34
+ trace: 'retain-on-failure',
35
+ screenshot: 'only-on-failure',
36
+ video: 'retain-on-failure',
37
+ ...baseConfig.use,
38
+ },
39
+ };
40
+ }
41
+ //# sourceMappingURL=withPrivateReporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withPrivateReporter.js","sourceRoot":"","sources":["../../../src/config/withPrivateReporter.ts"],"names":[],"mappings":";;AAUA,kDAwCC;AA9CD,MAAM,8BAA8B,GAAG,oCAAoC,CAAC;AAE5E,SAAS,WAAW,CAAC,SAAgC,EAAE,IAAY;IACjE,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;AAC5D,CAAC;AAED,SAAgB,mBAAmB,CACjC,UAAgC,EAChC,OAA+B;IAE/B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,WAAW,CAAC;IACnD,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,KAAK,MAAM,CAAC;IACnD,MAAM,SAAS,GAA0B,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC;QACzE,CAAC,CAAC,CAAC,GAAI,UAAU,CAAC,QAAkC,CAAC;QACrD,CAAC,CAAC,UAAU,CAAC,QAAQ;YACnB,CAAC,CAAC,CAAC,UAAU,CAAC,QAA+B,CAAC;YAC9C,CAAC,CAAC,EAAE,CAAC;IAET,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC;QAC1C,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,EAAE,CAAC;QACrC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,mBAAmB,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;IAED,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,8BAA8B,CAAC,EAAE,CAAC;QAC5D,SAAS,CAAC,IAAI,CAAC,CAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC;QAC9E,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5B,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,YAAY,EAAE,mBAAmB,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IACjF,CAAC;IAED,OAAO;QACL,GAAG,UAAU;QACb,SAAS,EAAE,UAAU,CAAC,SAAS,IAAI,GAAG,SAAS,eAAe;QAC9D,QAAQ,EAAE,SAAS;QACnB,GAAG,EAAE;YACH,KAAK,EAAE,mBAAmB;YAC1B,UAAU,EAAE,iBAAiB;YAC7B,KAAK,EAAE,mBAAmB;YAC1B,GAAG,UAAU,CAAC,GAAG;SAClB;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { FailureGroup, HistoryDiff } from '../types/schema.js';
2
+ export declare function diffFailureGroups(current: FailureGroup[], previous: FailureGroup[]): HistoryDiff;
3
+ //# sourceMappingURL=diffRuns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diffRuns.d.ts","sourceRoot":"","sources":["../../../src/history/diffRuns.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEpE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,WAAW,CAahG"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.diffFailureGroups = diffFailureGroups;
4
+ function diffFailureGroups(current, previous) {
5
+ const previousByFingerprint = new Map(previous.map((group) => [group.fingerprint, group]));
6
+ const currentByFingerprint = new Map(current.map((group) => [group.fingerprint, group]));
7
+ const newFailures = current.filter((group) => !previousByFingerprint.has(group.fingerprint));
8
+ const stillFailing = current.filter((group) => previousByFingerprint.has(group.fingerprint));
9
+ const fixedFailures = previous.filter((group) => !currentByFingerprint.has(group.fingerprint));
10
+ return {
11
+ newFailures,
12
+ fixedFailures,
13
+ stillFailing,
14
+ };
15
+ }
16
+ //# sourceMappingURL=diffRuns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diffRuns.js","sourceRoot":"","sources":["../../../src/history/diffRuns.ts"],"names":[],"mappings":";;AAEA,8CAaC;AAbD,SAAgB,iBAAiB,CAAC,OAAuB,EAAE,QAAwB;IACjF,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3F,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IAEzF,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7F,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,qBAAqB,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAC7F,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;IAE/F,OAAO;QACL,WAAW;QACX,aAAa;QACb,YAAY;KACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { FailuresSummary, RunSummary } from '../types/schema.js';
2
+ export declare function loadPreviousRunSummary(path: string): Promise<RunSummary | undefined>;
3
+ export declare function loadPreviousFailuresSummary(path: string): Promise<FailuresSummary | undefined>;
4
+ //# sourceMappingURL=loadPrevious.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadPrevious.d.ts","sourceRoot":"","sources":["../../../src/history/loadPrevious.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEtE,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAO1F;AAED,wBAAsB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAOpG"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.loadPreviousRunSummary = loadPreviousRunSummary;
4
+ exports.loadPreviousFailuresSummary = loadPreviousFailuresSummary;
5
+ const promises_1 = require("node:fs/promises");
6
+ async function loadPreviousRunSummary(path) {
7
+ try {
8
+ const raw = await (0, promises_1.readFile)(path, 'utf8');
9
+ return JSON.parse(raw);
10
+ }
11
+ catch {
12
+ return undefined;
13
+ }
14
+ }
15
+ async function loadPreviousFailuresSummary(path) {
16
+ try {
17
+ const raw = await (0, promises_1.readFile)(path, 'utf8');
18
+ return JSON.parse(raw);
19
+ }
20
+ catch {
21
+ return undefined;
22
+ }
23
+ }
24
+ //# sourceMappingURL=loadPrevious.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loadPrevious.js","sourceRoot":"","sources":["../../../src/history/loadPrevious.ts"],"names":[],"mappings":";;AAIA,wDAOC;AAED,kEAOC;AApBD,+CAA4C;AAIrC,KAAK,UAAU,sBAAsB,CAAC,IAAY;IACvD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,2BAA2B,CAAC,IAAY;IAC5D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACzC,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { withPrivateReporter } from './config/withPrivateReporter.js';
2
+ export { PrivateReporter } from './reporter/PrivateReporter.js';
3
+ export { createFailureFingerprint, extractFirstMeaningfulStack, normalizeErrorMessage } from './reporter/fingerprint.js';
4
+ export { generateReport } from './cli/generateReport.js';
5
+ export { diffFailureGroups } from './history/diffRuns.js';
6
+ export { loadPreviousFailuresSummary, loadPreviousRunSummary } from './history/loadPrevious.js';
7
+ export type { AttachmentRecord, FailureGroup, FailuresSummary, HistoryDiff, PrivateReporterOptions, RunSummary, } from './types/schema.js';
8
+ export { PrivateReporter as default } from './reporter/PrivateReporter.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,wBAAwB,EAAE,2BAA2B,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AACzH,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAChG,YAAY,EACV,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,WAAW,EACX,sBAAsB,EACtB,UAAU,GACX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,eAAe,IAAI,OAAO,EAAE,MAAM,+BAA+B,CAAC"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.default = exports.loadPreviousRunSummary = exports.loadPreviousFailuresSummary = exports.diffFailureGroups = exports.generateReport = exports.normalizeErrorMessage = exports.extractFirstMeaningfulStack = exports.createFailureFingerprint = exports.PrivateReporter = exports.withPrivateReporter = void 0;
4
+ var withPrivateReporter_js_1 = require("./config/withPrivateReporter.js");
5
+ Object.defineProperty(exports, "withPrivateReporter", { enumerable: true, get: function () { return withPrivateReporter_js_1.withPrivateReporter; } });
6
+ var PrivateReporter_js_1 = require("./reporter/PrivateReporter.js");
7
+ Object.defineProperty(exports, "PrivateReporter", { enumerable: true, get: function () { return PrivateReporter_js_1.PrivateReporter; } });
8
+ var fingerprint_js_1 = require("./reporter/fingerprint.js");
9
+ Object.defineProperty(exports, "createFailureFingerprint", { enumerable: true, get: function () { return fingerprint_js_1.createFailureFingerprint; } });
10
+ Object.defineProperty(exports, "extractFirstMeaningfulStack", { enumerable: true, get: function () { return fingerprint_js_1.extractFirstMeaningfulStack; } });
11
+ Object.defineProperty(exports, "normalizeErrorMessage", { enumerable: true, get: function () { return fingerprint_js_1.normalizeErrorMessage; } });
12
+ var generateReport_js_1 = require("./cli/generateReport.js");
13
+ Object.defineProperty(exports, "generateReport", { enumerable: true, get: function () { return generateReport_js_1.generateReport; } });
14
+ var diffRuns_js_1 = require("./history/diffRuns.js");
15
+ Object.defineProperty(exports, "diffFailureGroups", { enumerable: true, get: function () { return diffRuns_js_1.diffFailureGroups; } });
16
+ var loadPrevious_js_1 = require("./history/loadPrevious.js");
17
+ Object.defineProperty(exports, "loadPreviousFailuresSummary", { enumerable: true, get: function () { return loadPrevious_js_1.loadPreviousFailuresSummary; } });
18
+ Object.defineProperty(exports, "loadPreviousRunSummary", { enumerable: true, get: function () { return loadPrevious_js_1.loadPreviousRunSummary; } });
19
+ var PrivateReporter_js_2 = require("./reporter/PrivateReporter.js");
20
+ Object.defineProperty(exports, "default", { enumerable: true, get: function () { return PrivateReporter_js_2.PrivateReporter; } });
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,0EAAsE;AAA7D,6HAAA,mBAAmB,OAAA;AAC5B,oEAAgE;AAAvD,qHAAA,eAAe,OAAA;AACxB,4DAAyH;AAAhH,0HAAA,wBAAwB,OAAA;AAAE,6HAAA,2BAA2B,OAAA;AAAE,uHAAA,qBAAqB,OAAA;AACrF,6DAAyD;AAAhD,mHAAA,cAAc,OAAA;AACvB,qDAA0D;AAAjD,gHAAA,iBAAiB,OAAA;AAC1B,6DAAgG;AAAvF,8HAAA,2BAA2B,OAAA;AAAE,yHAAA,sBAAsB,OAAA;AAS5D,oEAA2E;AAAlE,6GAAA,eAAe,OAAW"}
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1,16 @@
1
+ import type { Reporter, TestCase, TestResult } from '@playwright/test/reporter';
2
+ import type { PrivateReporterOptions } from '../types/schema.js';
3
+ export declare class PrivateReporter implements Reporter {
4
+ private readonly options;
5
+ private readonly failures;
6
+ private readonly counts;
7
+ private readonly healthErrors;
8
+ constructor(options: PrivateReporterOptions);
9
+ printsToStdio(): boolean;
10
+ onTestEnd(test: TestCase, result: TestResult): void;
11
+ onEnd(): Promise<void>;
12
+ private recordStatus;
13
+ private guard;
14
+ private guardAsync;
15
+ }
16
+ //# sourceMappingURL=PrivateReporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrivateReporter.d.ts","sourceRoot":"","sources":["../../../src/reporter/PrivateReporter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAKhF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEjE,qBAAa,eAAgB,YAAW,QAAQ;IAC9C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAyB;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAgB;gBAE1B,OAAO,EAAE,sBAAsB;IAI3C,aAAa,IAAI,OAAO;IAIxB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,GAAG,IAAI;IAmC7C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBnC,OAAO,CAAC,YAAY;IAuBpB,OAAO,CAAC,KAAK;YAQC,UAAU;CAOzB"}
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PrivateReporter = void 0;
4
+ const promises_1 = require("node:fs/promises");
5
+ const node_path_1 = require("node:path");
6
+ const attachments_js_1 = require("./attachments.js");
7
+ const fingerprint_js_1 = require("./fingerprint.js");
8
+ const summary_js_1 = require("./summary.js");
9
+ class PrivateReporter {
10
+ options;
11
+ failures = [];
12
+ counts = (0, summary_js_1.createEmptyCounts)();
13
+ healthErrors = [];
14
+ constructor(options) {
15
+ this.options = options;
16
+ }
17
+ printsToStdio() {
18
+ return false;
19
+ }
20
+ onTestEnd(test, result) {
21
+ this.guard(() => {
22
+ this.recordStatus(result.status);
23
+ if (!result.error) {
24
+ return;
25
+ }
26
+ const normalizedMessage = (0, fingerprint_js_1.normalizeErrorMessage)(result.error.message);
27
+ const firstMeaningfulStack = (0, fingerprint_js_1.extractFirstMeaningfulStack)(result.error.stack);
28
+ const attachments = (0, attachments_js_1.normalizeAttachments)(result.attachments);
29
+ this.failures.push({
30
+ fingerprint: (0, fingerprint_js_1.createFailureFingerprint)({
31
+ testFile: test.location.file,
32
+ titlePath: test.titlePath(),
33
+ projectName: test.parent.project?.()?.name,
34
+ normalizedMessage,
35
+ firstMeaningfulStack,
36
+ }),
37
+ title: test.title,
38
+ normalizedMessage,
39
+ firstMeaningfulStack,
40
+ testFile: test.location.file,
41
+ projectName: test.parent.project?.()?.name,
42
+ status: result.status === 'timedOut' ? 'timedOut' : 'failed',
43
+ id: test.id,
44
+ titlePath: test.titlePath(),
45
+ location: `${test.location.file}:${test.location.line}:${test.location.column}`,
46
+ retry: result.retry,
47
+ attachments,
48
+ });
49
+ });
50
+ }
51
+ async onEnd() {
52
+ await this.guardAsync(async () => {
53
+ const outputDir = (0, node_path_1.join)(this.options.outputDir ?? 'artifacts', 'internal-report');
54
+ await (0, promises_1.mkdir)(outputDir, { recursive: true });
55
+ const groupedFailures = (0, summary_js_1.summarizeFailures)(this.failures);
56
+ const runSummary = (0, summary_js_1.buildRunSummary)({
57
+ options: this.options,
58
+ counts: this.counts,
59
+ groupedFailures,
60
+ });
61
+ const failuresSummary = (0, summary_js_1.buildFailuresSummary)(this.options, groupedFailures);
62
+ await Promise.all([
63
+ (0, promises_1.writeFile)((0, node_path_1.join)(outputDir, 'run.json'), JSON.stringify(runSummary, null, 2), 'utf8'),
64
+ (0, promises_1.writeFile)((0, node_path_1.join)(outputDir, 'failures.json'), JSON.stringify(failuresSummary, null, 2), 'utf8'),
65
+ (0, promises_1.writeFile)((0, node_path_1.join)(outputDir, 'health.json'), JSON.stringify({ ok: this.healthErrors.length === 0, errors: this.healthErrors }, null, 2), 'utf8'),
66
+ ]);
67
+ });
68
+ }
69
+ recordStatus(status) {
70
+ switch (status) {
71
+ case 'passed':
72
+ this.counts.passed += 1;
73
+ break;
74
+ case 'failed':
75
+ this.counts.failed += 1;
76
+ break;
77
+ case 'skipped':
78
+ this.counts.skipped += 1;
79
+ break;
80
+ case 'timedOut':
81
+ this.counts.timedOut += 1;
82
+ break;
83
+ case 'interrupted':
84
+ this.counts.interrupted += 1;
85
+ break;
86
+ default:
87
+ this.counts.flaky += 1;
88
+ break;
89
+ }
90
+ }
91
+ guard(fn) {
92
+ try {
93
+ fn();
94
+ }
95
+ catch (error) {
96
+ this.healthErrors.push(error instanceof Error ? error.message : String(error));
97
+ }
98
+ }
99
+ async guardAsync(fn) {
100
+ try {
101
+ await fn();
102
+ }
103
+ catch (error) {
104
+ this.healthErrors.push(error instanceof Error ? error.message : String(error));
105
+ }
106
+ }
107
+ }
108
+ exports.PrivateReporter = PrivateReporter;
109
+ //# sourceMappingURL=PrivateReporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PrivateReporter.js","sourceRoot":"","sources":["../../../src/reporter/PrivateReporter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { AttachmentRecord } from '../types/schema.js';
2
+ export type PlaywrightLikeAttachment = {
3
+ name: string;
4
+ contentType?: string;
5
+ path?: string;
6
+ };
7
+ export declare function normalizeAttachments(attachments: PlaywrightLikeAttachment[] | undefined): AttachmentRecord[];
8
+ export declare function selectExampleAttachments(attachments: AttachmentRecord[], max?: number): AttachmentRecord[];
9
+ //# sourceMappingURL=attachments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.d.ts","sourceRoot":"","sources":["../../../src/reporter/attachments.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAE3D,MAAM,MAAM,wBAAwB,GAAG;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,WAAW,EAAE,wBAAwB,EAAE,GAAG,SAAS,GAClD,gBAAgB,EAAE,CAMpB;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,gBAAgB,EAAE,EAAE,GAAG,SAAI,GAAG,gBAAgB,EAAE,CAErG"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeAttachments = normalizeAttachments;
4
+ exports.selectExampleAttachments = selectExampleAttachments;
5
+ function normalizeAttachments(attachments) {
6
+ return (attachments ?? []).map((attachment) => ({
7
+ name: attachment.name,
8
+ contentType: attachment.contentType,
9
+ path: attachment.path,
10
+ }));
11
+ }
12
+ function selectExampleAttachments(attachments, max = 3) {
13
+ return attachments.filter((attachment) => Boolean(attachment.path)).slice(0, max);
14
+ }
15
+ //# sourceMappingURL=attachments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachments.js","sourceRoot":"","sources":["../../../src/reporter/attachments.ts"],"names":[],"mappings":";;AAQA,oDAQC;AAED,4DAEC;AAZD,SAAgB,oBAAoB,CAClC,WAAmD;IAEnD,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QAC9C,IAAI,EAAE,UAAU,CAAC,IAAI;QACrB,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,IAAI,EAAE,UAAU,CAAC,IAAI;KACtB,CAAC,CAAC,CAAC;AACN,CAAC;AAED,SAAgB,wBAAwB,CAAC,WAA+B,EAAE,GAAG,GAAG,CAAC;IAC/E,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACpF,CAAC"}
@@ -0,0 +1,12 @@
1
+ export type FingerprintParts = {
2
+ testFile: string;
3
+ titlePath: string[];
4
+ projectName?: string;
5
+ firstMeaningfulStack?: string;
6
+ normalizedMessage: string;
7
+ stepTitle?: string;
8
+ };
9
+ export declare function normalizeErrorMessage(message: string | undefined): string;
10
+ export declare function extractFirstMeaningfulStack(stack: string | undefined): string | undefined;
11
+ export declare function createFailureFingerprint(parts: FingerprintParts): string;
12
+ //# sourceMappingURL=fingerprint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../../../src/reporter/fingerprint.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAUzE;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CASzF;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAWxE"}