@arghajit/dummy 0.1.0
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 +259 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +26 -0
- package/dist/lib/report-types.d.ts +8 -0
- package/dist/lib/report-types.js +2 -0
- package/dist/playwright-pulse-reporter.d.ts +26 -0
- package/dist/playwright-pulse-reporter.js +304 -0
- package/dist/reporter/attachment-utils.d.ts +10 -0
- package/dist/reporter/attachment-utils.js +192 -0
- package/dist/reporter/index.d.ts +5 -0
- package/dist/reporter/index.js +9 -0
- package/dist/reporter/lib/report-types.d.ts +8 -0
- package/dist/reporter/lib/report-types.js +2 -0
- package/dist/reporter/playwright-pulse-reporter.d.ts +27 -0
- package/dist/reporter/playwright-pulse-reporter.js +454 -0
- package/dist/reporter/reporter/playwright-pulse-reporter.d.ts +1 -0
- package/dist/reporter/reporter/playwright-pulse-reporter.js +398 -0
- package/dist/reporter/types/index.d.ts +52 -0
- package/dist/reporter/types/index.js +2 -0
- package/dist/types/index.d.ts +65 -0
- package/dist/types/index.js +2 -0
- package/package.json +73 -0
- package/screenshots/127-0-0-1-5500-pulse-report-output-playwright-pulse-static-report-html-i-Phone-14-Pro-Max-1.png +0 -0
- package/screenshots/127-0-0-1-5500-pulse-report-output-playwright-pulse-static-report-html-i-Phone-14-Pro-Max.png +0 -0
- package/screenshots/Email-report.jpg +0 -0
- package/screenshots/Users-arghajitsingha-Downloads-pulse-report-1-playwright-pulse-static-report-html-1.png +0 -0
- package/screenshots/Users-arghajitsingha-Downloads-pulse-report-1-playwright-pulse-static-report-html-2.png +0 -0
- package/screenshots/Users-arghajitsingha-Downloads-pulse-report-1-playwright-pulse-static-report-html.png +0 -0
- package/screenshots/image.png +0 -0
- package/scripts/generate-static-report.mjs +2279 -0
- package/scripts/generate-trend.mjs +165 -0
- package/scripts/merge-pulse-report.js +81 -0
- package/scripts/sendReport.js +335 -0
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// input_file_0.ts
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.PlaywrightPulseReporter = void 0;
|
|
38
|
+
const fs = __importStar(require("fs/promises"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
const crypto_1 = require("crypto");
|
|
41
|
+
const attachment_utils_1 = require("./attachment-utils"); // Use relative path
|
|
42
|
+
const convertStatus = (status, testCase) => {
|
|
43
|
+
if ((testCase === null || testCase === void 0 ? void 0 : testCase.expectedStatus) === "failed") {
|
|
44
|
+
return "failed";
|
|
45
|
+
}
|
|
46
|
+
if ((testCase === null || testCase === void 0 ? void 0 : testCase.expectedStatus) === "skipped") {
|
|
47
|
+
return "skipped";
|
|
48
|
+
}
|
|
49
|
+
switch (status) {
|
|
50
|
+
case "passed":
|
|
51
|
+
return "passed";
|
|
52
|
+
case "failed":
|
|
53
|
+
case "timedOut":
|
|
54
|
+
case "interrupted":
|
|
55
|
+
return "failed";
|
|
56
|
+
case "skipped":
|
|
57
|
+
default:
|
|
58
|
+
return "skipped";
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const TEMP_SHARD_FILE_PREFIX = ".pulse-shard-results-";
|
|
62
|
+
const ATTACHMENTS_SUBDIR = "attachments";
|
|
63
|
+
class PlaywrightPulseReporter {
|
|
64
|
+
constructor(options = {}) {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
this.results = [];
|
|
67
|
+
this.baseOutputFile = "playwright-pulse-report.json";
|
|
68
|
+
this.isSharded = false;
|
|
69
|
+
this.shardIndex = undefined;
|
|
70
|
+
this.options = options;
|
|
71
|
+
this.baseOutputFile = (_a = options.outputFile) !== null && _a !== void 0 ? _a : this.baseOutputFile;
|
|
72
|
+
this.outputDir = (_b = options.outputDir) !== null && _b !== void 0 ? _b : "pulse-report";
|
|
73
|
+
this.attachmentsDir = path.join(this.outputDir, ATTACHMENTS_SUBDIR);
|
|
74
|
+
}
|
|
75
|
+
printsToStdio() {
|
|
76
|
+
return this.shardIndex === undefined || this.shardIndex === 0;
|
|
77
|
+
}
|
|
78
|
+
onBegin(config, suite) {
|
|
79
|
+
var _a;
|
|
80
|
+
this.config = config;
|
|
81
|
+
this.suite = suite;
|
|
82
|
+
this.runStartTime = Date.now();
|
|
83
|
+
const configDir = this.config.rootDir;
|
|
84
|
+
const configFileDir = this.config.configFile
|
|
85
|
+
? path.dirname(this.config.configFile)
|
|
86
|
+
: configDir;
|
|
87
|
+
this.outputDir = path.resolve(configFileDir, (_a = this.options.outputDir) !== null && _a !== void 0 ? _a : "pulse-report");
|
|
88
|
+
this.attachmentsDir = path.resolve(this.outputDir, ATTACHMENTS_SUBDIR);
|
|
89
|
+
this.options.outputDir = this.outputDir;
|
|
90
|
+
const totalShards = this.config.shard ? this.config.shard.total : 1;
|
|
91
|
+
this.isSharded = totalShards > 1;
|
|
92
|
+
this.shardIndex = this.config.shard
|
|
93
|
+
? this.config.shard.current - 1
|
|
94
|
+
: undefined;
|
|
95
|
+
this._ensureDirExists(this.outputDir)
|
|
96
|
+
.then(() => {
|
|
97
|
+
if (this.shardIndex === undefined || this.shardIndex === 0) {
|
|
98
|
+
console.log(`PlaywrightPulseReporter: Starting test run with ${suite.allTests().length} tests${this.isSharded ? ` across ${totalShards} shards` : ""}. Pulse outputting to ${this.outputDir}`);
|
|
99
|
+
if (this.shardIndex === undefined ||
|
|
100
|
+
(this.isSharded && this.shardIndex === 0)) {
|
|
101
|
+
return this._cleanupTemporaryFiles();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
.catch((err) => console.error("Pulse Reporter: Error during initialization:", err));
|
|
106
|
+
}
|
|
107
|
+
onTestBegin(test) {
|
|
108
|
+
// console.log(`Starting test: ${test.title}`);
|
|
109
|
+
}
|
|
110
|
+
async processStep(step, testId, browserName, testCase) {
|
|
111
|
+
var _a, _b, _c, _d;
|
|
112
|
+
let stepStatus = "passed";
|
|
113
|
+
let errorMessage = ((_a = step.error) === null || _a === void 0 ? void 0 : _a.message) || undefined;
|
|
114
|
+
if ((_c = (_b = step.error) === null || _b === void 0 ? void 0 : _b.message) === null || _c === void 0 ? void 0 : _c.startsWith("Test is skipped:")) {
|
|
115
|
+
stepStatus = "skipped";
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
stepStatus = convertStatus(step.error ? "failed" : "passed", testCase);
|
|
119
|
+
}
|
|
120
|
+
const duration = step.duration;
|
|
121
|
+
const startTime = new Date(step.startTime);
|
|
122
|
+
const endTime = new Date(startTime.getTime() + Math.max(0, duration));
|
|
123
|
+
let codeLocation = "";
|
|
124
|
+
if (step.location) {
|
|
125
|
+
codeLocation = `${path.relative(this.config.rootDir, step.location.file)}:${step.location.line}:${step.location.column}`;
|
|
126
|
+
}
|
|
127
|
+
let stepTitle = step.title;
|
|
128
|
+
return {
|
|
129
|
+
id: `${testId}_step_${startTime.toISOString()}-${duration}-${(0, crypto_1.randomUUID)()}`,
|
|
130
|
+
title: stepTitle,
|
|
131
|
+
status: stepStatus,
|
|
132
|
+
duration: duration,
|
|
133
|
+
startTime: startTime,
|
|
134
|
+
endTime: endTime,
|
|
135
|
+
browser: browserName,
|
|
136
|
+
errorMessage: errorMessage,
|
|
137
|
+
stackTrace: ((_d = step.error) === null || _d === void 0 ? void 0 : _d.stack) || undefined,
|
|
138
|
+
codeLocation: codeLocation || undefined,
|
|
139
|
+
isHook: step.category === "hook",
|
|
140
|
+
hookType: step.category === "hook"
|
|
141
|
+
? step.title.toLowerCase().includes("before")
|
|
142
|
+
? "before"
|
|
143
|
+
: "after"
|
|
144
|
+
: undefined,
|
|
145
|
+
steps: [],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
async onTestEnd(test, result) {
|
|
149
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
150
|
+
const project = (_a = test.parent) === null || _a === void 0 ? void 0 : _a.project();
|
|
151
|
+
const browserName = ((_b = project === null || project === void 0 ? void 0 : project.use) === null || _b === void 0 ? void 0 : _b.defaultBrowserType) || (project === null || project === void 0 ? void 0 : project.name) || "unknown";
|
|
152
|
+
const testStatus = convertStatus(result.status, test);
|
|
153
|
+
const startTime = new Date(result.startTime);
|
|
154
|
+
const endTime = new Date(startTime.getTime() + result.duration);
|
|
155
|
+
const testIdForFiles = test.id ||
|
|
156
|
+
`${test
|
|
157
|
+
.titlePath()
|
|
158
|
+
.join("_")
|
|
159
|
+
.replace(/[^a-zA-Z0-9]/g, "_")}_${startTime.getTime()}`;
|
|
160
|
+
const processAllSteps = async (steps) => {
|
|
161
|
+
let processed = [];
|
|
162
|
+
for (const step of steps) {
|
|
163
|
+
const processedStep = await this.processStep(step, testIdForFiles, browserName, test);
|
|
164
|
+
processed.push(processedStep);
|
|
165
|
+
if (step.steps && step.steps.length > 0) {
|
|
166
|
+
processedStep.steps = await processAllSteps(step.steps);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return processed;
|
|
170
|
+
};
|
|
171
|
+
let codeSnippet = undefined;
|
|
172
|
+
try {
|
|
173
|
+
if (((_c = test.location) === null || _c === void 0 ? void 0 : _c.file) && ((_d = test.location) === null || _d === void 0 ? void 0 : _d.line) && ((_e = test.location) === null || _e === void 0 ? void 0 : _e.column)) {
|
|
174
|
+
const relativePath = path.relative(this.config.rootDir, test.location.file);
|
|
175
|
+
codeSnippet = `Test defined at: ${relativePath}:${test.location.line}:${test.location.column}`;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch (e) {
|
|
179
|
+
console.warn(`Pulse Reporter: Could not extract code snippet for ${test.title}`, e);
|
|
180
|
+
}
|
|
181
|
+
const stdoutMessages = [];
|
|
182
|
+
if (result.stdout && result.stdout.length > 0) {
|
|
183
|
+
result.stdout.forEach((item) => {
|
|
184
|
+
stdoutMessages.push(typeof item === "string" ? item : item.toString());
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
const stderrMessages = [];
|
|
188
|
+
if (result.stderr && result.stderr.length > 0) {
|
|
189
|
+
result.stderr.forEach((item) => {
|
|
190
|
+
stderrMessages.push(typeof item === "string" ? item : item.toString());
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
const uniqueTestId = test.id;
|
|
194
|
+
const pulseResult = {
|
|
195
|
+
id: uniqueTestId,
|
|
196
|
+
runId: "TBD",
|
|
197
|
+
name: test.titlePath().join(" > "),
|
|
198
|
+
suiteName: (project === null || project === void 0 ? void 0 : project.name) || ((_f = this.config.projects[0]) === null || _f === void 0 ? void 0 : _f.name) || "Default Suite",
|
|
199
|
+
status: testStatus,
|
|
200
|
+
duration: result.duration,
|
|
201
|
+
startTime: startTime,
|
|
202
|
+
endTime: endTime,
|
|
203
|
+
browser: browserName,
|
|
204
|
+
retries: result.retry,
|
|
205
|
+
steps: ((_g = result.steps) === null || _g === void 0 ? void 0 : _g.length) ? await processAllSteps(result.steps) : [],
|
|
206
|
+
errorMessage: (_h = result.error) === null || _h === void 0 ? void 0 : _h.message,
|
|
207
|
+
stackTrace: (_j = result.error) === null || _j === void 0 ? void 0 : _j.stack,
|
|
208
|
+
codeSnippet: codeSnippet,
|
|
209
|
+
tags: test.tags.map((tag) => tag.startsWith("@") ? tag.substring(1) : tag),
|
|
210
|
+
screenshots: [],
|
|
211
|
+
videoPath: undefined,
|
|
212
|
+
tracePath: undefined,
|
|
213
|
+
stdout: stdoutMessages.length > 0 ? stdoutMessages : undefined,
|
|
214
|
+
stderr: stderrMessages.length > 0 ? stderrMessages : undefined,
|
|
215
|
+
};
|
|
216
|
+
try {
|
|
217
|
+
(0, attachment_utils_1.attachFiles)(testIdForFiles, result, pulseResult, this.options);
|
|
218
|
+
}
|
|
219
|
+
catch (attachError) {
|
|
220
|
+
console.error(`Pulse Reporter: Error processing attachments for test ${pulseResult.name} (ID: ${testIdForFiles}): ${attachError.message}`);
|
|
221
|
+
}
|
|
222
|
+
const existingTestIndex = this.results.findIndex((r) => r.id === uniqueTestId);
|
|
223
|
+
if (existingTestIndex !== -1) {
|
|
224
|
+
if (pulseResult.retries >= this.results[existingTestIndex].retries) {
|
|
225
|
+
this.results[existingTestIndex] = pulseResult;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
this.results.push(pulseResult);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
onError(error) {
|
|
233
|
+
var _a;
|
|
234
|
+
console.error(`PlaywrightPulseReporter: Error encountered (Shard: ${(_a = this.shardIndex) !== null && _a !== void 0 ? _a : "Main"}):`, (error === null || error === void 0 ? void 0 : error.message) || error);
|
|
235
|
+
if (error === null || error === void 0 ? void 0 : error.stack) {
|
|
236
|
+
console.error(error.stack);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
async _writeShardResults() {
|
|
240
|
+
if (this.shardIndex === undefined) {
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const tempFilePath = path.join(this.outputDir, `${TEMP_SHARD_FILE_PREFIX}${this.shardIndex}.json`);
|
|
244
|
+
try {
|
|
245
|
+
await fs.writeFile(tempFilePath, JSON.stringify(this.results, (key, value) => (value instanceof Date ? value.toISOString() : value), 2));
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
console.error(`Pulse Reporter: Shard ${this.shardIndex} failed to write temporary results to ${tempFilePath}`, error);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
async _mergeShardResults(finalRunData) {
|
|
252
|
+
let allShardProcessedResults = [];
|
|
253
|
+
const totalShards = this.config.shard ? this.config.shard.total : 1;
|
|
254
|
+
for (let i = 0; i < totalShards; i++) {
|
|
255
|
+
const tempFilePath = path.join(this.outputDir, `${TEMP_SHARD_FILE_PREFIX}${i}.json`);
|
|
256
|
+
try {
|
|
257
|
+
const content = await fs.readFile(tempFilePath, "utf-8");
|
|
258
|
+
const shardResults = JSON.parse(content);
|
|
259
|
+
allShardProcessedResults =
|
|
260
|
+
allShardProcessedResults.concat(shardResults);
|
|
261
|
+
}
|
|
262
|
+
catch (error) {
|
|
263
|
+
if ((error === null || error === void 0 ? void 0 : error.code) === "ENOENT") {
|
|
264
|
+
console.warn(`Pulse Reporter: Shard results file not found: ${tempFilePath}. This might be normal if a shard had no tests or failed early.`);
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
console.error(`Pulse Reporter: Could not read/parse results from shard ${i} (${tempFilePath}). Error:`, error);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
let finalUniqueResultsMap = new Map();
|
|
272
|
+
for (const result of allShardProcessedResults) {
|
|
273
|
+
const existing = finalUniqueResultsMap.get(result.id);
|
|
274
|
+
if (!existing || result.retries >= existing.retries) {
|
|
275
|
+
finalUniqueResultsMap.set(result.id, result);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
const finalResultsList = Array.from(finalUniqueResultsMap.values());
|
|
279
|
+
finalResultsList.forEach((r) => (r.runId = finalRunData.id));
|
|
280
|
+
finalRunData.passed = finalResultsList.filter((r) => r.status === "passed").length;
|
|
281
|
+
finalRunData.failed = finalResultsList.filter((r) => r.status === "failed").length;
|
|
282
|
+
finalRunData.skipped = finalResultsList.filter((r) => r.status === "skipped").length;
|
|
283
|
+
finalRunData.totalTests = finalResultsList.length;
|
|
284
|
+
const reviveDates = (key, value) => {
|
|
285
|
+
const isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/;
|
|
286
|
+
if (typeof value === "string" && isoDateRegex.test(value)) {
|
|
287
|
+
const date = new Date(value);
|
|
288
|
+
return !isNaN(date.getTime()) ? date : value;
|
|
289
|
+
}
|
|
290
|
+
return value;
|
|
291
|
+
};
|
|
292
|
+
const properlyTypedResults = JSON.parse(JSON.stringify(finalResultsList), reviveDates);
|
|
293
|
+
return {
|
|
294
|
+
run: finalRunData,
|
|
295
|
+
results: properlyTypedResults,
|
|
296
|
+
metadata: { generatedAt: new Date().toISOString() },
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
async _cleanupTemporaryFiles() {
|
|
300
|
+
try {
|
|
301
|
+
const files = await fs.readdir(this.outputDir);
|
|
302
|
+
const tempFiles = files.filter((f) => f.startsWith(TEMP_SHARD_FILE_PREFIX));
|
|
303
|
+
if (tempFiles.length > 0) {
|
|
304
|
+
await Promise.all(tempFiles.map((f) => fs.unlink(path.join(this.outputDir, f))));
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
if ((error === null || error === void 0 ? void 0 : error.code) !== "ENOENT") {
|
|
309
|
+
console.warn("Pulse Reporter: Warning during cleanup of temporary files:", error.message);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
async _ensureDirExists(dirPath) {
|
|
314
|
+
try {
|
|
315
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
if (error.code !== "EEXIST") {
|
|
319
|
+
console.error(`Pulse Reporter: Failed to ensure directory exists: ${dirPath}`, error);
|
|
320
|
+
throw error;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
async onEnd(result) {
|
|
325
|
+
var _a, _b, _c;
|
|
326
|
+
if (this.shardIndex !== undefined) {
|
|
327
|
+
await this._writeShardResults();
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const runEndTime = Date.now();
|
|
331
|
+
const duration = runEndTime - this.runStartTime;
|
|
332
|
+
const runId = `run-${this.runStartTime}-${(0, crypto_1.randomUUID)()}`;
|
|
333
|
+
const runData = {
|
|
334
|
+
id: runId,
|
|
335
|
+
timestamp: new Date(this.runStartTime),
|
|
336
|
+
totalTests: 0,
|
|
337
|
+
passed: 0,
|
|
338
|
+
failed: 0,
|
|
339
|
+
skipped: 0,
|
|
340
|
+
duration,
|
|
341
|
+
};
|
|
342
|
+
let finalReport = undefined; // Initialize as undefined
|
|
343
|
+
if (this.isSharded) {
|
|
344
|
+
finalReport = await this._mergeShardResults(runData);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
this.results.forEach((r) => (r.runId = runId));
|
|
348
|
+
runData.passed = this.results.filter((r) => r.status === "passed").length;
|
|
349
|
+
runData.failed = this.results.filter((r) => r.status === "failed").length;
|
|
350
|
+
runData.skipped = this.results.filter((r) => r.status === "skipped").length;
|
|
351
|
+
runData.totalTests = this.results.length;
|
|
352
|
+
const reviveDates = (key, value) => {
|
|
353
|
+
const isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/;
|
|
354
|
+
if (typeof value === "string" && isoDateRegex.test(value)) {
|
|
355
|
+
const date = new Date(value);
|
|
356
|
+
return !isNaN(date.getTime()) ? date : value;
|
|
357
|
+
}
|
|
358
|
+
return value;
|
|
359
|
+
};
|
|
360
|
+
const properlyTypedResults = JSON.parse(JSON.stringify(this.results), reviveDates);
|
|
361
|
+
finalReport = {
|
|
362
|
+
run: runData,
|
|
363
|
+
results: properlyTypedResults,
|
|
364
|
+
metadata: { generatedAt: new Date().toISOString() },
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
if (!finalReport) {
|
|
368
|
+
console.error("PlaywrightPulseReporter: CRITICAL - finalReport object was not generated. Cannot create summary.");
|
|
369
|
+
const errorSummary = `
|
|
370
|
+
PlaywrightPulseReporter: Run Finished
|
|
371
|
+
-----------------------------------------
|
|
372
|
+
Overall Status: ERROR (Report data missing)
|
|
373
|
+
Total Tests: N/A
|
|
374
|
+
Passed: N/A
|
|
375
|
+
Failed: N/A
|
|
376
|
+
Skipped: N/A
|
|
377
|
+
Duration: N/A
|
|
378
|
+
-----------------------------------------`;
|
|
379
|
+
if (this.printsToStdio()) {
|
|
380
|
+
console.log(errorSummary);
|
|
381
|
+
}
|
|
382
|
+
const errorReport = {
|
|
383
|
+
run: {
|
|
384
|
+
id: runId,
|
|
385
|
+
timestamp: new Date(this.runStartTime),
|
|
386
|
+
totalTests: 0,
|
|
387
|
+
passed: 0,
|
|
388
|
+
failed: 0,
|
|
389
|
+
skipped: 0,
|
|
390
|
+
duration: duration,
|
|
391
|
+
},
|
|
392
|
+
results: [],
|
|
393
|
+
metadata: {
|
|
394
|
+
generatedAt: new Date().toISOString(),
|
|
395
|
+
},
|
|
396
|
+
};
|
|
397
|
+
const finalOutputPathOnError = path.join(this.outputDir, this.baseOutputFile);
|
|
398
|
+
try {
|
|
399
|
+
await this._ensureDirExists(this.outputDir);
|
|
400
|
+
await fs.writeFile(finalOutputPathOnError, JSON.stringify(errorReport, null, 2));
|
|
401
|
+
console.warn(`PlaywrightPulseReporter: Wrote an error report to ${finalOutputPathOnError} as finalReport was missing.`);
|
|
402
|
+
}
|
|
403
|
+
catch (writeError) {
|
|
404
|
+
console.error(`PlaywrightPulseReporter: Failed to write error report: ${writeError.message}`);
|
|
405
|
+
}
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
const reportRunData = finalReport.run;
|
|
409
|
+
const finalRunStatus = ((_a = reportRunData === null || reportRunData === void 0 ? void 0 : reportRunData.failed) !== null && _a !== void 0 ? _a : 0) > 0
|
|
410
|
+
? "failed"
|
|
411
|
+
: ((_b = reportRunData === null || reportRunData === void 0 ? void 0 : reportRunData.totalTests) !== null && _b !== void 0 ? _b : 0) === 0 && result.status !== "passed"
|
|
412
|
+
? result.status === "interrupted"
|
|
413
|
+
? "interrupted"
|
|
414
|
+
: "no tests or error"
|
|
415
|
+
: "passed";
|
|
416
|
+
const summary = `
|
|
417
|
+
PlaywrightPulseReporter: Run Finished
|
|
418
|
+
-----------------------------------------
|
|
419
|
+
Overall Status: ${finalRunStatus.toUpperCase()}
|
|
420
|
+
Total Tests: ${(reportRunData === null || reportRunData === void 0 ? void 0 : reportRunData.totalTests) || 0}
|
|
421
|
+
Passed: ${reportRunData === null || reportRunData === void 0 ? void 0 : reportRunData.passed}
|
|
422
|
+
Failed: ${reportRunData === null || reportRunData === void 0 ? void 0 : reportRunData.failed}
|
|
423
|
+
Skipped: ${reportRunData === null || reportRunData === void 0 ? void 0 : reportRunData.skipped}
|
|
424
|
+
Duration: ${(((_c = reportRunData === null || reportRunData === void 0 ? void 0 : reportRunData.duration) !== null && _c !== void 0 ? _c : 0) / 1000).toFixed(2)}s
|
|
425
|
+
-----------------------------------------`;
|
|
426
|
+
if (this.printsToStdio()) {
|
|
427
|
+
console.log(summary);
|
|
428
|
+
}
|
|
429
|
+
const finalOutputPath = path.join(this.outputDir, this.baseOutputFile);
|
|
430
|
+
try {
|
|
431
|
+
await this._ensureDirExists(this.outputDir);
|
|
432
|
+
await fs.writeFile(finalOutputPath, JSON.stringify(finalReport, (key, value) => {
|
|
433
|
+
if (value instanceof Date)
|
|
434
|
+
return value.toISOString();
|
|
435
|
+
if (typeof value === "bigint")
|
|
436
|
+
return value.toString();
|
|
437
|
+
return value;
|
|
438
|
+
}, 2));
|
|
439
|
+
if (this.printsToStdio()) {
|
|
440
|
+
console.log(`PlaywrightPulseReporter: JSON report written to ${finalOutputPath}`);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
catch (error) {
|
|
444
|
+
console.error(`Pulse Reporter: Failed to write final JSON report to ${finalOutputPath}. Error: ${error.message}`);
|
|
445
|
+
}
|
|
446
|
+
finally {
|
|
447
|
+
if (this.isSharded) {
|
|
448
|
+
await this._cleanupTemporaryFiles();
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
exports.PlaywrightPulseReporter = PlaywrightPulseReporter;
|
|
454
|
+
exports.default = PlaywrightPulseReporter;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|