@arghajit/dummy 0.3.37 → 0.3.39
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/dist/lib/report-types.d.ts +2 -0
- package/dist/reporter/playwright-pulse-reporter.d.ts +1 -1
- package/dist/reporter/playwright-pulse-reporter.js +21 -104
- package/dist/types/index.d.ts +45 -0
- package/package.json +2 -2
- package/scripts/config-reader.mjs +98 -126
- package/scripts/generate-email-report.mjs +47 -6
- package/scripts/generate-report.mjs +94 -31
- package/scripts/generate-static-report.mjs +99 -32
- package/scripts/generate-trend.mjs +2 -0
- package/scripts/merge-pulse-report.js +2 -0
- package/scripts/merge-sequential-reports.mjs +205 -0
- package/scripts/sendReport.mjs +33 -1
|
@@ -10,6 +10,7 @@ export declare class PlaywrightPulseReporter implements Reporter {
|
|
|
10
10
|
private outputDir;
|
|
11
11
|
private attachmentsDir;
|
|
12
12
|
private baseOutputFile;
|
|
13
|
+
private individualReportsSubDir;
|
|
13
14
|
private isSharded;
|
|
14
15
|
private shardIndex;
|
|
15
16
|
private resetOnEachRun;
|
|
@@ -46,6 +47,5 @@ export declare class PlaywrightPulseReporter implements Reporter {
|
|
|
46
47
|
private _cleanupStaleRunReports;
|
|
47
48
|
private _ensureDirExists;
|
|
48
49
|
onEnd(result: FullResult): Promise<void>;
|
|
49
|
-
private _mergeAllRunReports;
|
|
50
50
|
}
|
|
51
51
|
export default PlaywrightPulseReporter;
|
|
@@ -64,20 +64,21 @@ const convertStatus = (status, testCase) => {
|
|
|
64
64
|
};
|
|
65
65
|
const TEMP_SHARD_FILE_PREFIX = ".pulse-shard-results-";
|
|
66
66
|
const ATTACHMENTS_SUBDIR = "attachments";
|
|
67
|
-
const INDIVIDUAL_REPORTS_SUBDIR = "pulse-results";
|
|
68
67
|
class PlaywrightPulseReporter {
|
|
69
68
|
constructor(options = {}) {
|
|
70
|
-
var _a, _b, _c;
|
|
69
|
+
var _a, _b, _c, _d;
|
|
71
70
|
this.results = [];
|
|
72
71
|
this._pendingTestEnds = [];
|
|
73
72
|
this.baseOutputFile = "playwright-pulse-report.json";
|
|
73
|
+
this.individualReportsSubDir = "pulse-results";
|
|
74
74
|
this.isSharded = false;
|
|
75
75
|
this.shardIndex = undefined;
|
|
76
76
|
this.options = options;
|
|
77
77
|
this.baseOutputFile = (_a = options.outputFile) !== null && _a !== void 0 ? _a : this.baseOutputFile;
|
|
78
78
|
this.outputDir = (_b = options.outputDir) !== null && _b !== void 0 ? _b : "pulse-report";
|
|
79
|
+
this.individualReportsSubDir = (_c = options.individualReportsSubDir) !== null && _c !== void 0 ? _c : "pulse-results";
|
|
79
80
|
this.attachmentsDir = path.join(this.outputDir, ATTACHMENTS_SUBDIR);
|
|
80
|
-
this.resetOnEachRun = (
|
|
81
|
+
this.resetOnEachRun = (_d = options.resetOnEachRun) !== null && _d !== void 0 ? _d : true;
|
|
81
82
|
}
|
|
82
83
|
printsToStdio() {
|
|
83
84
|
return this.shardIndex === undefined || this.shardIndex === 0;
|
|
@@ -488,7 +489,11 @@ class PlaywrightPulseReporter {
|
|
|
488
489
|
return {
|
|
489
490
|
run: finalRunData,
|
|
490
491
|
results: properlyTypedResults,
|
|
491
|
-
metadata: {
|
|
492
|
+
metadata: {
|
|
493
|
+
generatedAt: new Date().toISOString(),
|
|
494
|
+
reportDescription: this.options.reportDescription,
|
|
495
|
+
logo: this.options.logo,
|
|
496
|
+
},
|
|
492
497
|
};
|
|
493
498
|
}
|
|
494
499
|
async _cleanupTemporaryFiles() {
|
|
@@ -520,7 +525,7 @@ class PlaywrightPulseReporter {
|
|
|
520
525
|
* Cleaning up at `onBegin` time guarantees each run starts with a fresh slate.
|
|
521
526
|
*/
|
|
522
527
|
async _cleanupStaleRunReports() {
|
|
523
|
-
const pulseResultsDir = path.join(this.outputDir,
|
|
528
|
+
const pulseResultsDir = path.join(this.outputDir, this.individualReportsSubDir);
|
|
524
529
|
try {
|
|
525
530
|
const files = await fs.readdir(pulseResultsDir);
|
|
526
531
|
const staleFiles = files.filter((f) => f.startsWith("playwright-pulse-report-") && f.endsWith(".json"));
|
|
@@ -588,7 +593,11 @@ class PlaywrightPulseReporter {
|
|
|
588
593
|
run: runData,
|
|
589
594
|
// Use the de-duplicated results
|
|
590
595
|
results: finalResults,
|
|
591
|
-
metadata: {
|
|
596
|
+
metadata: {
|
|
597
|
+
generatedAt: new Date().toISOString(),
|
|
598
|
+
reportDescription: this.options.reportDescription,
|
|
599
|
+
logo: this.options.logo,
|
|
600
|
+
},
|
|
592
601
|
};
|
|
593
602
|
}
|
|
594
603
|
if (!finalReport) {
|
|
@@ -617,7 +626,7 @@ class PlaywrightPulseReporter {
|
|
|
617
626
|
}
|
|
618
627
|
else {
|
|
619
628
|
// Logic for appending/merging reports
|
|
620
|
-
const pulseResultsDir = path.join(this.outputDir,
|
|
629
|
+
const pulseResultsDir = path.join(this.outputDir, this.individualReportsSubDir);
|
|
621
630
|
const individualReportPath = path.join(pulseResultsDir, `playwright-pulse-report-${Date.now()}.json`);
|
|
622
631
|
try {
|
|
623
632
|
await this._ensureDirExists(pulseResultsDir);
|
|
@@ -625,111 +634,19 @@ class PlaywrightPulseReporter {
|
|
|
625
634
|
if (this.printsToStdio()) {
|
|
626
635
|
console.log(`PlaywrightPulseReporter: Individual run report for merging written to ${individualReportPath}`);
|
|
627
636
|
}
|
|
628
|
-
|
|
637
|
+
// DEFERRED MERGING:
|
|
638
|
+
// We do not call _mergeAllRunReports() here anymore when resetOnEachRun is false.
|
|
639
|
+
// The individual JSON files in pulse-results/ will be collected and merged
|
|
640
|
+
// into the main JSON when the user next runs one of the report generator commands.
|
|
629
641
|
}
|
|
630
642
|
catch (error) {
|
|
631
|
-
console.error(`Pulse Reporter: Failed to write
|
|
643
|
+
console.error(`Pulse Reporter: Failed to write report. Error: ${error.message}`);
|
|
632
644
|
}
|
|
633
645
|
}
|
|
634
646
|
if (this.isSharded) {
|
|
635
647
|
await this._cleanupTemporaryFiles();
|
|
636
648
|
}
|
|
637
649
|
}
|
|
638
|
-
async _mergeAllRunReports() {
|
|
639
|
-
const pulseResultsDir = path.join(this.outputDir, INDIVIDUAL_REPORTS_SUBDIR);
|
|
640
|
-
const finalOutputPath = path.join(this.outputDir, this.baseOutputFile);
|
|
641
|
-
let reportFiles;
|
|
642
|
-
try {
|
|
643
|
-
const allFiles = await fs.readdir(pulseResultsDir);
|
|
644
|
-
reportFiles = allFiles.filter((file) => file.startsWith("playwright-pulse-report-") && file.endsWith(".json"));
|
|
645
|
-
}
|
|
646
|
-
catch (error) {
|
|
647
|
-
if (error.code === "ENOENT") {
|
|
648
|
-
if (this.printsToStdio()) {
|
|
649
|
-
console.log(`Pulse Reporter: No individual reports directory found at ${pulseResultsDir}. Skipping merge.`);
|
|
650
|
-
}
|
|
651
|
-
return;
|
|
652
|
-
}
|
|
653
|
-
console.error(`Pulse Reporter: Error reading report directory ${pulseResultsDir}:`, error);
|
|
654
|
-
return;
|
|
655
|
-
}
|
|
656
|
-
if (reportFiles.length === 0) {
|
|
657
|
-
if (this.printsToStdio()) {
|
|
658
|
-
console.log("Pulse Reporter: No matching JSON report files found to merge.");
|
|
659
|
-
}
|
|
660
|
-
return;
|
|
661
|
-
}
|
|
662
|
-
const allResultsFromAllFiles = [];
|
|
663
|
-
let latestTimestamp = new Date(0);
|
|
664
|
-
let lastRunEnvironment = undefined;
|
|
665
|
-
let totalDuration = 0;
|
|
666
|
-
for (const file of reportFiles) {
|
|
667
|
-
const filePath = path.join(pulseResultsDir, file);
|
|
668
|
-
try {
|
|
669
|
-
const content = await fs.readFile(filePath, "utf-8");
|
|
670
|
-
const json = JSON.parse(content);
|
|
671
|
-
if (json.run) {
|
|
672
|
-
const runTimestamp = new Date(json.run.timestamp);
|
|
673
|
-
if (runTimestamp > latestTimestamp) {
|
|
674
|
-
latestTimestamp = runTimestamp;
|
|
675
|
-
lastRunEnvironment = json.run.environment || undefined;
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
if (json.results) {
|
|
679
|
-
allResultsFromAllFiles.push(...json.results);
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
catch (err) {
|
|
683
|
-
console.warn(`Pulse Reporter: Could not parse report file ${filePath}. Skipping. Error: ${err.message}`);
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
// De-duplicate the results from ALL merged files using the helper function
|
|
687
|
-
const finalMergedResults = this._getFinalizedResults(allResultsFromAllFiles);
|
|
688
|
-
// Sum the duration from the final, de-duplicated list of tests
|
|
689
|
-
totalDuration = finalMergedResults.reduce((acc, r) => acc + (r.duration || 0), 0);
|
|
690
|
-
const combinedRun = {
|
|
691
|
-
id: `merged-${Date.now()}`,
|
|
692
|
-
timestamp: latestTimestamp,
|
|
693
|
-
environment: lastRunEnvironment,
|
|
694
|
-
// Recalculate counts based on the truly final, de-duplicated list
|
|
695
|
-
totalTests: finalMergedResults.length,
|
|
696
|
-
passed: finalMergedResults.filter((r) => (r.final_status || r.status) === "passed").length,
|
|
697
|
-
failed: finalMergedResults.filter((r) => (r.final_status || r.status) === "failed").length,
|
|
698
|
-
skipped: finalMergedResults.filter((r) => (r.final_status || r.status) === "skipped").length,
|
|
699
|
-
flaky: finalMergedResults.filter((r) => (r.final_status || r.status) === "flaky").length,
|
|
700
|
-
duration: totalDuration,
|
|
701
|
-
};
|
|
702
|
-
const finalReport = {
|
|
703
|
-
run: combinedRun,
|
|
704
|
-
results: finalMergedResults, // Use the de-duplicated list
|
|
705
|
-
metadata: {
|
|
706
|
-
generatedAt: new Date().toISOString(),
|
|
707
|
-
},
|
|
708
|
-
};
|
|
709
|
-
try {
|
|
710
|
-
await fs.writeFile(finalOutputPath, JSON.stringify(finalReport, (key, value) => {
|
|
711
|
-
if (value instanceof Date)
|
|
712
|
-
return value.toISOString();
|
|
713
|
-
return value;
|
|
714
|
-
}, 2));
|
|
715
|
-
if (this.printsToStdio()) {
|
|
716
|
-
console.log(`PlaywrightPulseReporter: ✅ Merged report with ${finalMergedResults.length} total results saved to ${finalOutputPath}`);
|
|
717
|
-
}
|
|
718
|
-
// Clean up the pulse-results directory after a successful merge
|
|
719
|
-
try {
|
|
720
|
-
await fs.rm(pulseResultsDir, { recursive: true, force: true });
|
|
721
|
-
if (this.printsToStdio()) {
|
|
722
|
-
console.log(`PlaywrightPulseReporter: Cleaned up individual reports directory at ${pulseResultsDir}`);
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
catch (cleanupErr) {
|
|
726
|
-
console.warn(`Pulse Reporter: Could not clean up individual reports directory. Error: ${cleanupErr.message}`);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
729
|
-
catch (err) {
|
|
730
|
-
console.error(`Pulse Reporter: Failed to write final merged report to ${finalOutputPath}. Error: ${err.message}`);
|
|
731
|
-
}
|
|
732
|
-
}
|
|
733
650
|
}
|
|
734
651
|
exports.PlaywrightPulseReporter = PlaywrightPulseReporter;
|
|
735
652
|
exports.default = PlaywrightPulseReporter;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -81,10 +81,55 @@ export interface TrendDataPoint {
|
|
|
81
81
|
flaky?: number;
|
|
82
82
|
}
|
|
83
83
|
export interface PlaywrightPulseReporterOptions {
|
|
84
|
+
/**
|
|
85
|
+
* The name of the output JSON file. Kindly do not change.
|
|
86
|
+
* @default "playwright-pulse-report.json"
|
|
87
|
+
*/
|
|
84
88
|
outputFile?: string;
|
|
89
|
+
/**
|
|
90
|
+
* The directory where the report files will be generated.
|
|
91
|
+
*
|
|
92
|
+
* Mostly useful while using sharding
|
|
93
|
+
*
|
|
94
|
+
* @default "pulse-report"
|
|
95
|
+
*/
|
|
85
96
|
outputDir?: string;
|
|
97
|
+
/**
|
|
98
|
+
* Whether to embed images directly as base64 strings in the report.
|
|
99
|
+
* @default false
|
|
100
|
+
*/
|
|
86
101
|
base64Images?: boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Whether to reset the output directory before each run.
|
|
104
|
+
*
|
|
105
|
+
* Mostly useful while running multiple test suites in a single run with `&&` operator.
|
|
106
|
+
*
|
|
107
|
+
* example: `npx playwright test test1.spec.ts && npx playwright test test2.spec.ts`
|
|
108
|
+
*
|
|
109
|
+
* If `resetOnEachRun` is set to `false`, then the report of `test2.spec.ts` will be merged with `test1.spec.ts` report.
|
|
110
|
+
*
|
|
111
|
+
* @default true
|
|
112
|
+
*/
|
|
87
113
|
resetOnEachRun?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* A custom description to embed or display in the report.
|
|
116
|
+
*
|
|
117
|
+
* If not added, the component will not appear in the html reports
|
|
118
|
+
*/
|
|
119
|
+
reportDescription?: string;
|
|
120
|
+
/**
|
|
121
|
+
* Path to a custom logo image file to use in the report, which will be displayed in the header of the html report's logo and favicon.
|
|
122
|
+
*
|
|
123
|
+
* If not added, the default logo will be used.
|
|
124
|
+
*/
|
|
125
|
+
logo?: string;
|
|
126
|
+
/**
|
|
127
|
+
* The subdirectory within `outputDir` where individual run reports are stored.
|
|
128
|
+
* Only used when `resetOnEachRun` is `false`.
|
|
129
|
+
*
|
|
130
|
+
* @default "pulse-results"
|
|
131
|
+
*/
|
|
132
|
+
individualReportsSubDir?: string;
|
|
88
133
|
}
|
|
89
134
|
export interface EnvDetails {
|
|
90
135
|
host: string;
|
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.39",
|
|
5
5
|
"description": "A Playwright reporter and dashboard for visualizing test results.",
|
|
6
6
|
"homepage": "https://arghajit47.github.io/playwright-pulse/",
|
|
7
7
|
"repository": {
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"generate-report": "scripts/generate-report.mjs",
|
|
41
41
|
"merge-pulse-report": "scripts/merge-pulse-report.js",
|
|
42
42
|
"send-email": "scripts/sendReport.mjs",
|
|
43
|
-
"generate-trend": "scripts/generate-trend.mjs",
|
|
44
43
|
"generate-email-report": "scripts/generate-email-report.mjs",
|
|
44
|
+
"generate-trend": "scripts/generate-trend.mjs",
|
|
45
45
|
"pulse-logo": "scripts/terminal-logo.mjs"
|
|
46
46
|
},
|
|
47
47
|
"exports": {
|
|
@@ -22,159 +22,131 @@ async function findPlaywrightConfig() {
|
|
|
22
22
|
return { path: null, exists: false };
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
async function
|
|
25
|
+
async function extractReporterOptionsFromConfig(configPath) {
|
|
26
26
|
let fileContent = "";
|
|
27
27
|
try {
|
|
28
28
|
fileContent = fs.readFileSync(configPath, "utf-8");
|
|
29
29
|
} catch (e) {
|
|
30
|
-
|
|
31
|
-
return null;
|
|
30
|
+
return {};
|
|
32
31
|
}
|
|
33
32
|
|
|
33
|
+
const options = {};
|
|
34
|
+
|
|
34
35
|
// 1. Strategy: Text Parsing (Safe & Fast)
|
|
35
|
-
// We try to read the file as text first. This finds the outputDir without
|
|
36
|
-
// triggering any Node.js warnings or errors.
|
|
37
36
|
try {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
const outputDirMatch = fileContent.match(/outputDir:\s*["']([^"']+)["']/);
|
|
38
|
+
if (outputDirMatch && outputDirMatch[1]) options.outputDir = outputDirMatch[1];
|
|
39
|
+
|
|
40
|
+
const outputFileMatch = fileContent.match(/outputFile:\s*["']([^"']+)["']/);
|
|
41
|
+
if (outputFileMatch && outputFileMatch[1]) options.outputFile = outputFileMatch[1];
|
|
42
|
+
|
|
43
|
+
const resetOnEachRunMatch = fileContent.match(/resetOnEachRun:\s*(true|false)/);
|
|
44
|
+
if (resetOnEachRunMatch) options.resetOnEachRun = resetOnEachRunMatch[1] === "true";
|
|
45
|
+
|
|
46
|
+
const individualReportsSubDirMatch = fileContent.match(/individualReportsSubDir:\s*["']([^"']+)["']/);
|
|
47
|
+
if (individualReportsSubDirMatch && individualReportsSubDirMatch[1]) options.individualReportsSubDir = individualReportsSubDirMatch[1];
|
|
48
|
+
} catch (e) { }
|
|
49
|
+
|
|
50
|
+
// 2. Safety Check and Dynamic Import
|
|
51
|
+
if (Object.keys(options).length < 3) {
|
|
52
|
+
// Check if we can safely import()
|
|
53
|
+
let canImport = true;
|
|
54
|
+
if (configPath.endsWith(".js")) {
|
|
55
|
+
let isModulePackage = false;
|
|
56
|
+
try {
|
|
57
|
+
const pkgPath = path.resolve(process.cwd(), "package.json");
|
|
58
|
+
if (fs.existsSync(pkgPath)) {
|
|
59
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
60
|
+
isModulePackage = pkg.type === "module";
|
|
61
|
+
}
|
|
62
|
+
} catch (e) {}
|
|
47
63
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// We explicitly check for this and ABORT the import if found.
|
|
52
|
-
if (configPath.endsWith(".js")) {
|
|
53
|
-
let isModulePackage = false;
|
|
54
|
-
try {
|
|
55
|
-
const pkgPath = path.resolve(process.cwd(), "package.json");
|
|
56
|
-
if (fs.existsSync(pkgPath)) {
|
|
57
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
58
|
-
isModulePackage = pkg.type === "module";
|
|
59
|
-
}
|
|
60
|
-
} catch (e) {}
|
|
61
|
-
|
|
62
|
-
if (!isModulePackage) {
|
|
63
|
-
// Heuristic: Check for ESM syntax (import/export at start of lines)
|
|
64
|
-
const hasEsmSyntax =
|
|
65
|
-
/^\s*import\s+/m.test(fileContent) ||
|
|
66
|
-
/^\s*export\s+/m.test(fileContent);
|
|
67
|
-
|
|
68
|
-
if (hasEsmSyntax) {
|
|
69
|
-
// We found ESM syntax in a .js file within a CJS project.
|
|
70
|
-
// Attempting to import this WILL trigger the Node.js warning.
|
|
71
|
-
// Since regex failed to find outputDir, and we can't import safely, we abort now.
|
|
72
|
-
return null;
|
|
64
|
+
if (!isModulePackage) {
|
|
65
|
+
const hasEsmSyntax = /^\s*import\s+/m.test(fileContent) || /^\s*export\s+/m.test(fileContent);
|
|
66
|
+
if (hasEsmSyntax) canImport = false;
|
|
73
67
|
}
|
|
74
68
|
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// 3. Strategy: Dynamic Import
|
|
78
|
-
// If we passed the safety check, we try to import the config.
|
|
79
|
-
try {
|
|
80
|
-
let config;
|
|
81
|
-
const configDir = dirname(configPath);
|
|
82
|
-
const originalDirname = global.__dirname;
|
|
83
|
-
const originalFilename = global.__filename;
|
|
84
69
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
70
|
+
if (canImport) {
|
|
71
|
+
try {
|
|
72
|
+
let config;
|
|
73
|
+
const configDir = dirname(configPath);
|
|
74
|
+
const originalDirname = global.__dirname;
|
|
75
|
+
const originalFilename = global.__filename;
|
|
88
76
|
|
|
89
|
-
if (configPath.endsWith(".ts")) {
|
|
90
77
|
try {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
// Handle Default Export
|
|
109
|
-
if (config && config.default) {
|
|
110
|
-
config = config.default;
|
|
111
|
-
}
|
|
78
|
+
global.__dirname = configDir;
|
|
79
|
+
global.__filename = configPath;
|
|
80
|
+
|
|
81
|
+
if (configPath.endsWith(".ts")) {
|
|
82
|
+
try {
|
|
83
|
+
const { register } = await import("node:module");
|
|
84
|
+
const { pathToFileURL } = await import("node:url");
|
|
85
|
+
register("ts-node/esm", pathToFileURL("./"));
|
|
86
|
+
config = await import(pathToFileURL(configPath).href);
|
|
87
|
+
} catch (tsError) {
|
|
88
|
+
const tsNode = await import("ts-node");
|
|
89
|
+
tsNode.register({ transpileOnly: true, compilerOptions: { module: "commonjs" } });
|
|
90
|
+
config = require(configPath);
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
config = await import(pathToFileURL(configPath).href);
|
|
94
|
+
}
|
|
112
95
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
reporterName.includes("@arghajit/dummy"))
|
|
133
|
-
) {
|
|
134
|
-
if (reporterOptions && reporterOptions.outputDir) {
|
|
135
|
-
return path.resolve(process.cwd(), reporterOptions.outputDir);
|
|
96
|
+
if (config && config.default) config = config.default;
|
|
97
|
+
|
|
98
|
+
if (config) {
|
|
99
|
+
if (config.reporter) {
|
|
100
|
+
const reporters = Array.isArray(config.reporter) ? config.reporter : [config.reporter];
|
|
101
|
+
for (const reporter of reporters) {
|
|
102
|
+
const reporterName = Array.isArray(reporter) ? reporter[0] : reporter;
|
|
103
|
+
const reporterOptions = Array.isArray(reporter) ? reporter[1] : null;
|
|
104
|
+
|
|
105
|
+
if (typeof reporterName === "string" &&
|
|
106
|
+
(reporterName.includes("playwright-pulse-report") ||
|
|
107
|
+
reporterName.includes("@arghajit/playwright-pulse-report"))) {
|
|
108
|
+
if (reporterOptions) {
|
|
109
|
+
if (reporterOptions.outputDir) options.outputDir = reporterOptions.outputDir;
|
|
110
|
+
if (reporterOptions.outputFile) options.outputFile = reporterOptions.outputFile;
|
|
111
|
+
if (reporterOptions.resetOnEachRun !== undefined) options.resetOnEachRun = reporterOptions.resetOnEachRun;
|
|
112
|
+
if (reporterOptions.individualReportsSubDir) options.individualReportsSubDir = reporterOptions.individualReportsSubDir;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
136
115
|
}
|
|
137
116
|
}
|
|
117
|
+
if (config.outputDir && !options.outputDir) options.outputDir = config.outputDir;
|
|
138
118
|
}
|
|
119
|
+
} finally {
|
|
120
|
+
global.__dirname = originalDirname;
|
|
121
|
+
global.__filename = originalFilename;
|
|
139
122
|
}
|
|
140
|
-
|
|
141
|
-
// Check for Global outputDir
|
|
142
|
-
if (config.outputDir) {
|
|
143
|
-
return path.resolve(process.cwd(), config.outputDir);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
} finally {
|
|
147
|
-
// Clean up globals
|
|
148
|
-
global.__dirname = originalDirname;
|
|
149
|
-
global.__filename = originalFilename;
|
|
123
|
+
} catch (error) {}
|
|
150
124
|
}
|
|
151
|
-
} catch (error) {
|
|
152
|
-
// SILENT CATCH: Do NOT log anything here.
|
|
153
|
-
return null;
|
|
154
125
|
}
|
|
155
126
|
|
|
156
|
-
return
|
|
127
|
+
return options;
|
|
157
128
|
}
|
|
158
129
|
|
|
159
|
-
export async function
|
|
160
|
-
if (customOutputDirFromArgs) {
|
|
161
|
-
console.log(`Using custom outputDir from CLI: ${customOutputDirFromArgs}`);
|
|
162
|
-
return path.resolve(process.cwd(), customOutputDirFromArgs);
|
|
163
|
-
}
|
|
164
|
-
|
|
130
|
+
export async function getReporterConfig(customOutputDirFromArgs = null) {
|
|
165
131
|
const { path: configPath, exists } = await findPlaywrightConfig();
|
|
166
|
-
|
|
167
|
-
`Config file search result: ${exists ? configPath : "not found"}`
|
|
168
|
-
);
|
|
132
|
+
let options = {};
|
|
169
133
|
|
|
170
134
|
if (exists) {
|
|
171
|
-
|
|
172
|
-
if (outputDirFromConfig) {
|
|
173
|
-
console.log(`Using outputDir from config: ${outputDirFromConfig}`);
|
|
174
|
-
return outputDirFromConfig;
|
|
175
|
-
}
|
|
135
|
+
options = await extractReporterOptionsFromConfig(configPath);
|
|
176
136
|
}
|
|
177
137
|
|
|
178
|
-
|
|
179
|
-
|
|
138
|
+
const outputDir = customOutputDirFromArgs
|
|
139
|
+
? path.resolve(process.cwd(), customOutputDirFromArgs)
|
|
140
|
+
: path.resolve(process.cwd(), options.outputDir || DEFAULT_OUTPUT_DIR);
|
|
141
|
+
|
|
142
|
+
const outputFile = options.outputFile || "playwright-pulse-report.json";
|
|
143
|
+
const resetOnEachRun = options.resetOnEachRun !== undefined ? options.resetOnEachRun : true;
|
|
144
|
+
const individualReportsSubDir = options.individualReportsSubDir || "pulse-results";
|
|
145
|
+
|
|
146
|
+
return { outputDir, outputFile, resetOnEachRun, individualReportsSubDir };
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export async function getOutputDir(customOutputDirFromArgs = null) {
|
|
150
|
+
const config = await getReporterConfig(customOutputDirFromArgs);
|
|
151
|
+
return config.outputDir;
|
|
180
152
|
}
|