@arghajit/dummy 0.3.40 → 0.3.42
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.
|
@@ -601,7 +601,8 @@ class PlaywrightPulseReporter {
|
|
|
601
601
|
else {
|
|
602
602
|
// Logic for appending/merging reports
|
|
603
603
|
const pulseResultsDir = path.join(this.outputDir, this.individualReportsSubDir);
|
|
604
|
-
const
|
|
604
|
+
const shardPrefix = this.baseOutputFile.replace(".json", "-");
|
|
605
|
+
const individualReportPath = path.join(pulseResultsDir, `${shardPrefix}${Date.now()}.json`);
|
|
605
606
|
try {
|
|
606
607
|
await this._ensureDirExists(pulseResultsDir);
|
|
607
608
|
await fs.writeFile(individualReportPath, JSON.stringify(finalReport, jsonReplacer, 2));
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arghajit/dummy",
|
|
3
3
|
"author": "Arghajit Singha",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.42",
|
|
5
5
|
"description": "A Playwright reporter and dashboard for visualizing test results.",
|
|
6
6
|
"homepage": "https://arghajit47.github.io/playwright-pulse/",
|
|
7
7
|
"repository": {
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
],
|
|
36
36
|
"license": "MIT",
|
|
37
37
|
"bin": {
|
|
38
|
-
"logo": "
|
|
38
|
+
"logo": "scripts/terminal-logo.mjs",
|
|
39
39
|
"generate-pulse-report": "scripts/generate-static-report.mjs",
|
|
40
40
|
"generate-report": "scripts/generate-report.mjs",
|
|
41
41
|
"merge-pulse-report": "scripts/merge-pulse-report.mjs",
|
|
@@ -34,17 +34,34 @@ async function extractReporterOptionsFromConfig(configPath) {
|
|
|
34
34
|
|
|
35
35
|
// 1. Strategy: Text Parsing (Safe & Fast)
|
|
36
36
|
try {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
37
|
+
// Find the Pulse/Dummy reporter block
|
|
38
|
+
// It usually looks like ["@arghajit/playwright-pulse-report", { ... }] or ["playwright-pulse-report", { ... }]
|
|
39
|
+
const reporterBlockRegex = /\[\s*["'](?:@arghajit\/)?(?:playwright-pulse-report|dummy)["']\s*,\s*(\{[\s\S]*?\})\s*,?\s*\]/g;
|
|
40
|
+
let match;
|
|
41
|
+
while ((match = reporterBlockRegex.exec(fileContent)) !== null) {
|
|
42
|
+
const block = match[1];
|
|
43
|
+
|
|
44
|
+
const outputDirMatch = block.match(/outputDir:\s*["']([^"']+)["']/);
|
|
45
|
+
if (outputDirMatch && outputDirMatch[1]) options.outputDir = outputDirMatch[1];
|
|
46
|
+
|
|
47
|
+
const outputFileMatch = block.match(/outputFile:\s*["']([^"']+)["']/);
|
|
48
|
+
if (outputFileMatch && outputFileMatch[1]) options.outputFile = outputFileMatch[1];
|
|
49
|
+
|
|
50
|
+
const resetOnEachRunMatch = block.match(/resetOnEachRun:\s*(true|false)/);
|
|
51
|
+
if (resetOnEachRunMatch) options.resetOnEachRun = resetOnEachRunMatch[1] === "true";
|
|
52
|
+
|
|
53
|
+
const individualReportsSubDirMatch = block.match(/individualReportsSubDir:\s*["']([^"']+)["']/);
|
|
54
|
+
if (individualReportsSubDirMatch && individualReportsSubDirMatch[1]) options.individualReportsSubDir = individualReportsSubDirMatch[1];
|
|
55
|
+
|
|
56
|
+
// If we found any Pulse-specific options, we're likely in the right block
|
|
57
|
+
if (Object.keys(options).length > 0) break;
|
|
58
|
+
}
|
|
45
59
|
|
|
46
|
-
|
|
47
|
-
if (
|
|
60
|
+
// Fallback for global outputDir if not found in reporter block
|
|
61
|
+
if (!options.outputDir) {
|
|
62
|
+
const globalOutputDirMatch = fileContent.match(/outputDir:\s*["']([^"']+)["']/);
|
|
63
|
+
if (globalOutputDirMatch && globalOutputDirMatch[1]) options.outputDir = globalOutputDirMatch[1];
|
|
64
|
+
}
|
|
48
65
|
} catch (e) { }
|
|
49
66
|
|
|
50
67
|
// 2. Safety Check and Dynamic Import
|
|
@@ -104,7 +121,8 @@ async function extractReporterOptionsFromConfig(configPath) {
|
|
|
104
121
|
|
|
105
122
|
if (typeof reporterName === "string" &&
|
|
106
123
|
(reporterName.includes("playwright-pulse-report") ||
|
|
107
|
-
reporterName.includes("@arghajit/playwright-pulse-report")
|
|
124
|
+
reporterName.includes("@arghajit/playwright-pulse-report") ||
|
|
125
|
+
reporterName.includes("@arghajit/dummy"))) {
|
|
108
126
|
if (reporterOptions) {
|
|
109
127
|
if (reporterOptions.outputDir) options.outputDir = reporterOptions.outputDir;
|
|
110
128
|
if (reporterOptions.outputFile) options.outputFile = reporterOptions.outputFile;
|
|
@@ -4,8 +4,8 @@ import * as path from "path";
|
|
|
4
4
|
import { getReporterConfig } from "./config-reader.mjs";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* Reads all
|
|
8
|
-
* and merges them into a single
|
|
7
|
+
* Reads all `<outputFile>-*.json` files in the `pulse-results` directory
|
|
8
|
+
* and merges them into a single `<outputFile>.json`.
|
|
9
9
|
* It resolves duplicate tests using exactly the same logic as the reporter.
|
|
10
10
|
*
|
|
11
11
|
* @param {string} customOutputDir The base report directory override (from CLI).
|
|
@@ -25,12 +25,15 @@ export async function mergeSequentialReportsIfNeeded(customOutputDir) {
|
|
|
25
25
|
const pulseResultsDir = path.join(outputDir, individualReportsSubDir);
|
|
26
26
|
const finalOutputPath = path.join(outputDir, baseOutputFile);
|
|
27
27
|
|
|
28
|
+
// Use the actual outputFile name as seed for shard files (e.g. "results.json" -> "results-")
|
|
29
|
+
const shardPrefix = baseOutputFile.replace(".json", "-");
|
|
30
|
+
|
|
28
31
|
let reportFiles;
|
|
29
32
|
try {
|
|
30
33
|
const allFiles = await fs.readdir(pulseResultsDir);
|
|
31
34
|
reportFiles = allFiles.filter(
|
|
32
35
|
(file) =>
|
|
33
|
-
file.startsWith(
|
|
36
|
+
file.startsWith(shardPrefix) && file.endsWith(".json"),
|
|
34
37
|
);
|
|
35
38
|
} catch (error) {
|
|
36
39
|
if (error.code === "ENOENT") {
|
|
@@ -64,15 +67,24 @@ export async function mergeSequentialReportsIfNeeded(customOutputDir) {
|
|
|
64
67
|
const content = await fs.readFile(filePath, "utf-8");
|
|
65
68
|
const json = JSON.parse(content);
|
|
66
69
|
|
|
70
|
+
let currentRunId = `run-${Date.now()}`;
|
|
67
71
|
if (json.run) {
|
|
72
|
+
if (json.run.id) currentRunId = json.run.id;
|
|
73
|
+
|
|
68
74
|
const runTimestamp = new Date(json.run.timestamp);
|
|
69
75
|
if (runTimestamp > latestTimestamp) {
|
|
70
76
|
latestTimestamp = runTimestamp;
|
|
71
77
|
lastRunEnvironment = json.run.environment || undefined;
|
|
72
78
|
}
|
|
73
79
|
}
|
|
80
|
+
|
|
74
81
|
if (json.results) {
|
|
75
|
-
|
|
82
|
+
// Tag each result with its runId to ensure we can sum them up if they have same IDs but different runs
|
|
83
|
+
const resultsWithRunId = json.results.map((r) => ({
|
|
84
|
+
...r,
|
|
85
|
+
runId: currentRunId,
|
|
86
|
+
}));
|
|
87
|
+
allResultsFromAllFiles.push(...resultsWithRunId);
|
|
76
88
|
}
|
|
77
89
|
} catch (err) {
|
|
78
90
|
console.warn(
|
|
@@ -90,7 +102,7 @@ export async function mergeSequentialReportsIfNeeded(customOutputDir) {
|
|
|
90
102
|
);
|
|
91
103
|
|
|
92
104
|
const combinedRun = {
|
|
93
|
-
id: `run-${Date.now()}
|
|
105
|
+
id: `run-${Date.now()}`,
|
|
94
106
|
timestamp: latestTimestamp.toISOString(),
|
|
95
107
|
environment: lastRunEnvironment,
|
|
96
108
|
totalTests: finalMergedResults.length,
|
|
@@ -155,10 +167,12 @@ function getFinalizedResults(allResults) {
|
|
|
155
167
|
const resultsMap = new Map();
|
|
156
168
|
|
|
157
169
|
for (const result of allResults) {
|
|
158
|
-
|
|
159
|
-
|
|
170
|
+
// Unique key is runId + testId to support summation of tests across different sequential runs
|
|
171
|
+
const compositeId = `${result.runId || "unknown"}-${result.id}`;
|
|
172
|
+
if (!resultsMap.has(compositeId)) {
|
|
173
|
+
resultsMap.set(compositeId, []);
|
|
160
174
|
}
|
|
161
|
-
resultsMap.get(
|
|
175
|
+
resultsMap.get(compositeId).push(result);
|
|
162
176
|
}
|
|
163
177
|
|
|
164
178
|
const finalResults = [];
|