@arghajit/dummy 0.1.0-beta-21 → 0.1.0-beta-23

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.
@@ -26,5 +26,6 @@ export declare class PlaywrightPulseReporter implements Reporter {
26
26
  private _cleanupTemporaryFiles;
27
27
  private _ensureDirExists;
28
28
  onEnd(result: FullResult): Promise<void>;
29
+ private _mergeAllRunReports;
29
30
  }
30
31
  export default PlaywrightPulseReporter;
@@ -36,7 +36,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.PlaywrightPulseReporter = void 0;
37
37
  const fs = __importStar(require("fs/promises"));
38
38
  const path = __importStar(require("path"));
39
- const fsSync = __importStar(require("fs"));
40
39
  const crypto_1 = require("crypto");
41
40
  const ua_parser_js_1 = require("ua-parser-js");
42
41
  const os = __importStar(require("os"));
@@ -61,6 +60,7 @@ const convertStatus = (status, testCase) => {
61
60
  };
62
61
  const TEMP_SHARD_FILE_PREFIX = ".pulse-shard-results-";
63
62
  const ATTACHMENTS_SUBDIR = "attachments";
63
+ const INDIVIDUAL_REPORTS_SUBDIR = "pulse-results";
64
64
  class PlaywrightPulseReporter {
65
65
  constructor(options = {}) {
66
66
  var _a, _b, _c;
@@ -72,7 +72,7 @@ class PlaywrightPulseReporter {
72
72
  this.baseOutputFile = (_a = options.outputFile) !== null && _a !== void 0 ? _a : this.baseOutputFile;
73
73
  this.outputDir = (_b = options.outputDir) !== null && _b !== void 0 ? _b : "pulse-report";
74
74
  this.attachmentsDir = path.join(this.outputDir, ATTACHMENTS_SUBDIR);
75
- this.resetOnEachRun = (_c = options.resetOnEachRun) !== null && _c !== void 0 ? _c : false;
75
+ this.resetOnEachRun = (_c = options.resetOnEachRun) !== null && _c !== void 0 ? _c : true;
76
76
  }
77
77
  printsToStdio() {
78
78
  return this.shardIndex === undefined || this.shardIndex === 0;
@@ -96,7 +96,7 @@ class PlaywrightPulseReporter {
96
96
  : undefined;
97
97
  this._ensureDirExists(this.outputDir)
98
98
  .then(() => {
99
- if (this.shardIndex === undefined || this.shardIndex === 0) {
99
+ if (this.printsToStdio()) {
100
100
  console.log(`PlaywrightPulseReporter: Starting test run with ${suite.allTests().length} tests${this.isSharded ? ` across ${totalShards} shards` : ""}. Pulse outputting to ${this.outputDir}`);
101
101
  if (this.shardIndex === undefined ||
102
102
  (this.isSharded && this.shardIndex === 0)) {
@@ -262,27 +262,19 @@ class PlaywrightPulseReporter {
262
262
  stderr: stderrMessages.length > 0 ? stderrMessages : undefined,
263
263
  ...testSpecificData,
264
264
  };
265
- // --- CORRECTED ATTACHMENT PROCESSING LOGIC ---
266
265
  for (const [index, attachment] of result.attachments.entries()) {
267
266
  if (!attachment.path)
268
267
  continue;
269
268
  try {
270
- // Create a sanitized, unique folder name for this specific test
271
269
  const testSubfolder = test.id.replace(/[^a-zA-Z0-9_-]/g, "_");
272
- // Sanitize the original attachment name to create a safe filename
273
270
  const safeAttachmentName = path
274
271
  .basename(attachment.path)
275
272
  .replace(/[^a-zA-Z0-9_.-]/g, "_");
276
- // Create a unique filename to prevent collisions, especially in retries
277
273
  const uniqueFileName = `${index}-${Date.now()}-${safeAttachmentName}`;
278
- // This is the relative path that will be stored in the JSON report
279
274
  const relativeDestPath = path.join(ATTACHMENTS_SUBDIR, testSubfolder, uniqueFileName);
280
- // This is the absolute path used for the actual file system operation
281
275
  const absoluteDestPath = path.join(this.outputDir, relativeDestPath);
282
- // Ensure the unique, test-specific attachment directory exists
283
276
  await this._ensureDirExists(path.dirname(absoluteDestPath));
284
277
  await fs.copyFile(attachment.path, absoluteDestPath);
285
- // Categorize the attachment based on its content type
286
278
  if (attachment.contentType.startsWith("image/")) {
287
279
  (_j = pulseResult.screenshots) === null || _j === void 0 ? void 0 : _j.push(relativeDestPath);
288
280
  }
@@ -294,8 +286,8 @@ class PlaywrightPulseReporter {
294
286
  }
295
287
  else {
296
288
  (_l = pulseResult.attachments) === null || _l === void 0 ? void 0 : _l.push({
297
- name: attachment.name, // The original, human-readable name
298
- path: relativeDestPath, // The safe, relative path for linking
289
+ name: attachment.name,
290
+ path: relativeDestPath,
299
291
  contentType: attachment.contentType,
300
292
  });
301
293
  }
@@ -442,9 +434,6 @@ class PlaywrightPulseReporter {
442
434
  let finalReport = undefined;
443
435
  if (this.isSharded) {
444
436
  finalReport = await this._mergeShardResults(runData);
445
- if (finalReport && finalReport.run && !finalReport.run.environment) {
446
- finalReport.run.environment = environmentDetails;
447
- }
448
437
  }
449
438
  else {
450
439
  this.results.forEach((r) => (r.runId = runId));
@@ -452,18 +441,9 @@ class PlaywrightPulseReporter {
452
441
  runData.failed = this.results.filter((r) => r.status === "failed").length;
453
442
  runData.skipped = this.results.filter((r) => r.status === "skipped").length;
454
443
  runData.totalTests = this.results.length;
455
- const reviveDates = (key, value) => {
456
- const isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?Z$/;
457
- if (typeof value === "string" && isoDateRegex.test(value)) {
458
- const date = new Date(value);
459
- return !isNaN(date.getTime()) ? date : value;
460
- }
461
- return value;
462
- };
463
- const properlyTypedResults = JSON.parse(JSON.stringify(this.results), reviveDates);
464
444
  finalReport = {
465
445
  run: runData,
466
- results: properlyTypedResults,
446
+ results: this.results,
467
447
  metadata: { generatedAt: new Date().toISOString() },
468
448
  };
469
449
  }
@@ -471,17 +451,18 @@ class PlaywrightPulseReporter {
471
451
  console.error("PlaywrightPulseReporter: CRITICAL - finalReport object was not generated. Cannot create summary.");
472
452
  return;
473
453
  }
474
- if (this.resetOnEachRun == true) {
454
+ const jsonReplacer = (key, value) => {
455
+ if (value instanceof Date)
456
+ return value.toISOString();
457
+ if (typeof value === "bigint")
458
+ return value.toString();
459
+ return value;
460
+ };
461
+ if (this.resetOnEachRun) {
475
462
  const finalOutputPath = path.join(this.outputDir, this.baseOutputFile);
476
463
  try {
477
464
  await this._ensureDirExists(this.outputDir);
478
- await fs.writeFile(finalOutputPath, JSON.stringify(finalReport, (key, value) => {
479
- if (value instanceof Date)
480
- return value.toISOString();
481
- if (typeof value === "bigint")
482
- return value.toString();
483
- return value;
484
- }, 2));
465
+ await fs.writeFile(finalOutputPath, JSON.stringify(finalReport, jsonReplacer, 2));
485
466
  if (this.printsToStdio()) {
486
467
  console.log(`PlaywrightPulseReporter: JSON report written to ${finalOutputPath}`);
487
468
  }
@@ -489,100 +470,110 @@ class PlaywrightPulseReporter {
489
470
  catch (error) {
490
471
  console.error(`Pulse Reporter: Failed to write final JSON report to ${finalOutputPath}. Error: ${error.message}`);
491
472
  }
492
- finally {
493
- if (this.isSharded) {
494
- await this._cleanupTemporaryFiles();
495
- }
496
- }
497
473
  }
498
474
  else {
499
- console.warn("PlaywrightPulseReporter: resetOnEachRun is set to false. The finalReport will display all the results present in '/pulse-results'.");
500
- const finalOutputPath = path.join(`${this.outputDir}/pulse-results`, `playwright-pulse-report-${Date.now()}.json`);
475
+ // Logic for appending/merging reports
476
+ const pulseResultsDir = path.join(this.outputDir, INDIVIDUAL_REPORTS_SUBDIR);
477
+ const individualReportPath = path.join(pulseResultsDir, `playwright-pulse-report-${Date.now()}.json`);
501
478
  try {
502
- await this._ensureDirExists(this.outputDir);
503
- await fs.writeFile(finalOutputPath, JSON.stringify(finalReport, (key, value) => {
504
- if (value instanceof Date)
505
- return value.toISOString();
506
- if (typeof value === "bigint")
507
- return value.toString();
508
- return value;
509
- }, 2));
479
+ await this._ensureDirExists(pulseResultsDir);
480
+ await fs.writeFile(individualReportPath, JSON.stringify(finalReport, jsonReplacer, 2));
510
481
  if (this.printsToStdio()) {
511
- console.log(`PlaywrightPulseReporter: JSON report written to ${finalOutputPath}`);
482
+ console.log(`PlaywrightPulseReporter: Individual run report for merging written to ${individualReportPath}`);
512
483
  }
484
+ await this._mergeAllRunReports();
513
485
  }
514
486
  catch (error) {
515
- console.error(`Pulse Reporter: Failed to write final JSON report to ${finalOutputPath}. Error: ${error.message}`);
487
+ console.error(`Pulse Reporter: Failed to write or merge report. Error: ${error.message}`);
516
488
  }
517
- finally {
518
- if (this.isSharded) {
519
- await this._cleanupTemporaryFiles();
489
+ }
490
+ if (this.isSharded) {
491
+ await this._cleanupTemporaryFiles();
492
+ }
493
+ }
494
+ async _mergeAllRunReports() {
495
+ const pulseResultsDir = path.join(this.outputDir, INDIVIDUAL_REPORTS_SUBDIR);
496
+ const finalOutputPath = path.join(this.outputDir, this.baseOutputFile);
497
+ let reportFiles;
498
+ try {
499
+ const allFiles = await fs.readdir(pulseResultsDir);
500
+ reportFiles = allFiles.filter((file) => file.startsWith("playwright-pulse-report-") && file.endsWith(".json"));
501
+ }
502
+ catch (error) {
503
+ if (error.code === "ENOENT") {
504
+ if (this.printsToStdio()) {
505
+ console.log(`Pulse Reporter: No individual reports directory found at ${pulseResultsDir}. Skipping merge.`);
520
506
  }
507
+ return;
521
508
  }
509
+ console.error(`Pulse Reporter: Error reading report directory ${pulseResultsDir}:`, error);
510
+ return;
522
511
  }
523
- }
524
- }
525
- exports.PlaywrightPulseReporter = PlaywrightPulseReporter;
526
- function falseResetOnEachRun() {
527
- const REPORT_DIR = "./pulse-report"; // Or change this to your reports directory
528
- const OUTPUT_FILE = "playwright-pulse-report.json";
529
- function getReportFiles(dir) {
530
- return fsSync
531
- .readdirSync(dir)
532
- .filter((file) => file.startsWith("playwright-pulse-report-") && file.endsWith(".json"));
533
- }
534
- function mergeReports(files) {
535
- var _a;
536
- let combinedRun = {
512
+ if (reportFiles.length === 0) {
513
+ if (this.printsToStdio()) {
514
+ console.log("Pulse Reporter: No matching JSON report files found to merge.");
515
+ }
516
+ return;
517
+ }
518
+ const combinedRun = {
519
+ id: `merged-${Date.now()}`,
520
+ timestamp: new Date(0),
537
521
  totalTests: 0,
538
522
  passed: 0,
539
523
  failed: 0,
540
524
  skipped: 0,
541
525
  duration: 0,
542
- environment: {},
526
+ environment: undefined,
543
527
  };
544
- let combinedResults = [];
545
- let latestTimestamp = "";
546
- let latestGeneratedAt = "";
547
- for (const file of files) {
548
- const filePath = path.join(`${REPORT_DIR}/pulse-results`, file);
549
- const json = JSON.parse(fsSync.readFileSync(filePath, "utf-8"));
550
- const run = json.run || {};
551
- combinedRun.totalTests += run.totalTests || 0;
552
- combinedRun.passed += run.passed || 0;
553
- combinedRun.failed += run.failed || 0;
554
- combinedRun.skipped += run.skipped || 0;
555
- combinedRun.duration += run.duration || 0;
556
- combinedRun.environment = run.environment || {};
557
- if (json.results) {
558
- combinedResults.push(...json.results);
528
+ const allResults = [];
529
+ let latestTimestamp = new Date(0);
530
+ for (const file of reportFiles) {
531
+ const filePath = path.join(pulseResultsDir, file);
532
+ try {
533
+ const content = await fs.readFile(filePath, "utf-8");
534
+ const json = JSON.parse(content);
535
+ if (json.run) {
536
+ combinedRun.totalTests += json.run.totalTests || 0;
537
+ combinedRun.passed += json.run.passed || 0;
538
+ combinedRun.failed += json.run.failed || 0;
539
+ combinedRun.skipped += json.run.skipped || 0;
540
+ combinedRun.duration += json.run.duration || 0;
541
+ const runTimestamp = new Date(json.run.timestamp);
542
+ if (runTimestamp > latestTimestamp) {
543
+ latestTimestamp = runTimestamp;
544
+ combinedRun.environment = json.run.environment || undefined;
545
+ }
546
+ }
547
+ if (json.results) {
548
+ allResults.push(...json.results);
549
+ }
559
550
  }
560
- if (run.timestamp > latestTimestamp)
561
- latestTimestamp = run.timestamp;
562
- if (((_a = json.metadata) === null || _a === void 0 ? void 0 : _a.generatedAt) > latestGeneratedAt)
563
- latestGeneratedAt = json.metadata.generatedAt;
564
- }
565
- const finalJson = {
566
- run: {
567
- id: `merged-${Date.now()}`,
568
- timestamp: latestTimestamp,
569
- ...combinedRun,
570
- },
571
- results: combinedResults,
551
+ catch (err) {
552
+ console.warn(`Pulse Reporter: Could not parse report file ${filePath}. Skipping. Error: ${err.message}`);
553
+ }
554
+ }
555
+ combinedRun.timestamp = latestTimestamp;
556
+ const finalReport = {
557
+ run: combinedRun,
558
+ results: allResults,
572
559
  metadata: {
573
- generatedAt: latestGeneratedAt,
560
+ generatedAt: new Date().toISOString(),
574
561
  },
575
562
  };
576
- return finalJson;
577
- }
578
- // Main execution
579
- const reportFiles = getReportFiles(REPORT_DIR);
580
- if (reportFiles.length === 0) {
581
- console.log("No matching JSON report files found.");
582
- process.exit(1);
563
+ try {
564
+ await fs.writeFile(finalOutputPath, JSON.stringify(finalReport, (key, value) => {
565
+ if (value instanceof Date)
566
+ return value.toISOString();
567
+ return value;
568
+ }, 2));
569
+ if (this.printsToStdio()) {
570
+ console.log(`PlaywrightPulseReporter: ✅ Merged report with ${allResults.length} total results saved to ${finalOutputPath}`);
571
+ }
572
+ }
573
+ catch (err) {
574
+ console.error(`Pulse Reporter: Failed to write final merged report to ${finalOutputPath}. Error: ${err.message}`);
575
+ }
583
576
  }
584
- const merged = mergeReports(reportFiles);
585
- fsSync.writeFileSync(path.join(REPORT_DIR, OUTPUT_FILE), JSON.stringify(merged, null, 2));
586
- console.log(`✅ Merged report saved as ${OUTPUT_FILE}`);
587
577
  }
578
+ exports.PlaywrightPulseReporter = PlaywrightPulseReporter;
588
579
  exports.default = PlaywrightPulseReporter;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@arghajit/dummy",
3
3
  "author": "Arghajit Singha",
4
- "version": "0.1.0-beta-21",
4
+ "version": "0.1.0-beta-23",
5
5
  "description": "A Playwright reporter and dashboard for visualizing test results.",
6
6
  "homepage": "https://playwright-pulse-report.netlify.app/",
7
7
  "keywords": [