ortoni-report 4.0.0 → 4.0.1-beta.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.
@@ -0,0 +1,111 @@
1
+ import { Reporter, FullConfig, Suite, TestCase, TestResult, TestError, FullResult } from '@playwright/test/reporter';
2
+
3
+ /**
4
+ * Configuration options for OrtoniReport.
5
+ */
6
+ interface OrtoniReportConfig {
7
+ /**
8
+ * Open the report in local host (Trace viewer is accessible only in localhost)
9
+ * @example "always"| "never"| "on-failure";
10
+ * @default "never"
11
+ */
12
+ open?: "always" | "never" | "on-failure";
13
+ /**
14
+ * The title of the HTML report.
15
+ * @example "Ortoni Playwright Test Report"
16
+ */
17
+ title?: string;
18
+ /**
19
+ * Add project on the list of the tests? (Filtering projects still works if hidden)
20
+ * @example true to display, false to hide.
21
+ * @default false
22
+ */
23
+ showProject?: boolean;
24
+ /**
25
+ * The name of the project.
26
+ * @example "Ortoni Project"
27
+ */
28
+ projectName?: string;
29
+ /**
30
+ * The name of the author.
31
+ * @example "Koushik Chatterjee"
32
+ */
33
+ authorName?: string;
34
+ /**
35
+ * The type of tests being run.
36
+ * @example "Regression"
37
+ */
38
+ testType?: string;
39
+ /**
40
+ * If true, images will be encoded in base64.
41
+ * Not recommended to use if many screenshots are present.
42
+ * @default false
43
+ * @example true
44
+ */
45
+ base64Image?: boolean;
46
+ /**
47
+ * The local relative of the logo image.
48
+ * Recommended to keep within the report genrated folder.
49
+ * @default "ortoni-report/logo.png"
50
+ * @example "logo.png"
51
+ */
52
+ logo?: string;
53
+ /**
54
+ * The filename to the html report.
55
+ * @example "index.html"
56
+ * @default "ortoni-report.html"
57
+ */
58
+ filename?: string;
59
+ /**
60
+ * The folder name.
61
+ * @example "report"
62
+ * @default "ortoni-report"
63
+ */
64
+ folderPath?: string;
65
+ /**
66
+ * Port to connect
67
+ * @example 3600
68
+ */
69
+ port?: number;
70
+ /**
71
+ * Display console logs?
72
+ * @example boolean
73
+ * @default true
74
+ */
75
+ stdIO?: boolean;
76
+ /**
77
+ * Metadata for the report. ['Test Cycle': 'Cycle 1', 'Test Environment':'QA', etc]
78
+ * @example { "key": "value" } as string
79
+ */
80
+ meta?: Record<string, string>;
81
+ }
82
+
83
+ declare class OrtoniReport implements Reporter {
84
+ private ortoniConfig;
85
+ private testResultProcessor;
86
+ private htmlGenerator;
87
+ private fileManager;
88
+ private serverManager;
89
+ private results;
90
+ private projectSet;
91
+ private overAllStatus;
92
+ private folderPath;
93
+ private outputFilename;
94
+ private outputPath;
95
+ private dbManager;
96
+ private shouldGenerateReport;
97
+ private showConsoleLogs;
98
+ private skipTraceViewer;
99
+ private config;
100
+ constructor(ortoniConfig?: OrtoniReportConfig);
101
+ private reportsCount;
102
+ onBegin(config: FullConfig, _suite: Suite): Promise<void>;
103
+ onStdOut(chunk: string | Buffer, _test: void | TestCase, _result: void | TestResult): void;
104
+ onTestEnd(test: TestCase, result: TestResult): void;
105
+ printsToStdio(): boolean;
106
+ onError(error: TestError): void;
107
+ onEnd(result: FullResult): Promise<void>;
108
+ onExit(): Promise<void>;
109
+ }
110
+
111
+ export { OrtoniReport, type OrtoniReportConfig, OrtoniReport as default };
@@ -96,6 +96,7 @@ declare class OrtoniReport implements Reporter {
96
96
  private shouldGenerateReport;
97
97
  private showConsoleLogs;
98
98
  private skipTraceViewer;
99
+ private shardConfig;
99
100
  constructor(ortoniConfig?: OrtoniReportConfig);
100
101
  private reportsCount;
101
102
  onBegin(config: FullConfig, _suite: Suite): Promise<void>;
@@ -96,6 +96,7 @@ declare class OrtoniReport implements Reporter {
96
96
  private shouldGenerateReport;
97
97
  private showConsoleLogs;
98
98
  private skipTraceViewer;
99
+ private shardConfig;
99
100
  constructor(ortoniConfig?: OrtoniReportConfig);
100
101
  private reportsCount;
101
102
  onBegin(config: FullConfig, _suite: Suite): Promise<void>;
@@ -55,14 +55,20 @@ var FileManager = class {
55
55
  }
56
56
  }
57
57
  writeReportFile(filename, data) {
58
- const templatePath = import_path.default.resolve(__dirname, "index.html");
58
+ const templatePath = import_path.default.join(__dirname, "..", "index.html");
59
59
  let html = import_fs.default.readFileSync(templatePath, "utf-8");
60
60
  const reportJSON = JSON.stringify({
61
61
  data
62
62
  });
63
63
  html = html.replace("__ORTONI_TEST_REPORTDATA__", reportJSON);
64
+ import_fs.default.writeFileSync(filename, html);
65
+ return filename;
66
+ }
67
+ writeRawFile(filename, data) {
64
68
  const outputPath = import_path.default.join(process.cwd(), this.folderPath, filename);
65
- import_fs.default.writeFileSync(outputPath, html);
69
+ import_fs.default.mkdirSync(import_path.default.dirname(outputPath), { recursive: true });
70
+ const content = typeof data === "string" ? data : JSON.stringify(data, null, 2);
71
+ import_fs.default.writeFileSync(outputPath, content, "utf-8");
66
72
  return outputPath;
67
73
  }
68
74
  copyTraceViewerAssets(skip) {
@@ -209,13 +215,11 @@ var HTMLGenerator = class {
209
215
  meta: this.ortoniConfig.meta
210
216
  },
211
217
  preferences: {
212
- theme: this.ortoniConfig.preferredTheme,
213
218
  logo: this.ortoniConfig.logo || void 0,
214
219
  showProject: this.ortoniConfig.showProject || false
215
220
  },
216
221
  analytics: {
217
222
  reportData: await this.getReportData()
218
- // chartTrendData: await this.chartTrendData(),
219
223
  }
220
224
  };
221
225
  }
@@ -1647,7 +1651,7 @@ function startReportServer(reportFolder, reportFilename, port = 2004, open2) {
1647
1651
  try {
1648
1652
  res.sendFile(import_path5.default.resolve(reportFolder, reportFilename));
1649
1653
  } catch (error) {
1650
- console.error("Ortoni-Report: Error sending report file:", error);
1654
+ console.error("Ortoni Report: Error sending report file:", error);
1651
1655
  res.status(500).send("Error loading report");
1652
1656
  }
1653
1657
  });
@@ -1661,21 +1665,21 @@ Press Ctrl+C to stop.`
1661
1665
  try {
1662
1666
  openBrowser(`http://localhost:${port}`);
1663
1667
  } catch (error) {
1664
- console.error("Ortoni-Report: Error opening browser:", error);
1668
+ console.error("Ortoni Report: Error opening browser:", error);
1665
1669
  }
1666
1670
  }
1667
1671
  });
1668
1672
  server.on("error", (error) => {
1669
1673
  if (error.code === "EADDRINUSE") {
1670
1674
  console.error(
1671
- `Ortoni-Report: Port ${port} is already in use. Trying a different port...`
1675
+ `Ortoni Report: Port ${port} is already in use. Trying a different port...`
1672
1676
  );
1673
1677
  } else {
1674
- console.error("Ortoni-Report: Server error:", error);
1678
+ console.error("Ortoni Report: Server error:", error);
1675
1679
  }
1676
1680
  });
1677
1681
  } catch (error) {
1678
- console.error("Ortoni-Report: Error starting the server:", error);
1682
+ console.error("Ortoni Report: Error starting the server:", error);
1679
1683
  }
1680
1684
  }
1681
1685
  function openBrowser(url) {
@@ -1693,7 +1697,7 @@ function openBrowser(url) {
1693
1697
  (0, import_child_process.spawn)(command, [url]);
1694
1698
  }
1695
1699
  } catch (error) {
1696
- console.error("Ortoni-Report: Error opening the browser:", error);
1700
+ console.error("Ortoni Report: Error opening the browser:", error);
1697
1701
  }
1698
1702
  }
1699
1703
 
@@ -2024,6 +2028,7 @@ var OrtoniReport = class {
2024
2028
  await this.dbManager.initialize(
2025
2029
  import_path6.default.join(this.folderPath, "ortoni-data-history.sqlite")
2026
2030
  );
2031
+ this.shardConfig = config?.shard;
2027
2032
  }
2028
2033
  onStdOut(chunk, _test, _result) {
2029
2034
  if (this.reportsCount == 1 && this.showConsoleLogs) {
@@ -2040,7 +2045,7 @@ var OrtoniReport = class {
2040
2045
  );
2041
2046
  this.results.push(testResult);
2042
2047
  } catch (error) {
2043
- console.error("OrtoniReport: Error processing test end:", error);
2048
+ console.error("Ortoni Report: Error processing test end:", error);
2044
2049
  }
2045
2050
  }
2046
2051
  printsToStdio() {
@@ -2059,6 +2064,28 @@ var OrtoniReport = class {
2059
2064
  (r) => r.status !== "skipped"
2060
2065
  );
2061
2066
  const totalDuration = result.duration;
2067
+ if (this.shardConfig && this.shardConfig.total > 1) {
2068
+ const shard = this.shardConfig;
2069
+ const shardFile = `ortoni-shard-${shard.current}-of-${shard.total}.json`;
2070
+ const shardData = {
2071
+ status: result.status,
2072
+ duration: totalDuration,
2073
+ results: this.results,
2074
+ projectSet: Array.from(this.projectSet),
2075
+ userConfig: {
2076
+ projectName: this.ortoniConfig.projectName,
2077
+ authorName: this.ortoniConfig.authorName,
2078
+ type: this.ortoniConfig.testType,
2079
+ title: this.ortoniConfig.title
2080
+ },
2081
+ userMeta: {
2082
+ meta: this.ortoniConfig.meta
2083
+ }
2084
+ };
2085
+ this.fileManager.writeRawFile(shardFile, shardData);
2086
+ this.shouldGenerateReport = false;
2087
+ return;
2088
+ }
2062
2089
  const runId = await this.dbManager.saveTestRun();
2063
2090
  if (runId !== null) {
2064
2091
  await this.dbManager.saveTestResults(runId, this.results);
@@ -2073,16 +2100,16 @@ var OrtoniReport = class {
2073
2100
  finalReportData
2074
2101
  );
2075
2102
  } else {
2076
- console.error("OrtoniReport: Error saving test run to database");
2103
+ console.error("Ortoni Report: Error saving test run to database");
2077
2104
  }
2078
2105
  } else {
2079
2106
  console.error(
2080
- "OrtoniReport: Report generation skipped due to error in Playwright worker!"
2107
+ "Ortoni Report: Report generation skipped due to error in Playwright worker!"
2081
2108
  );
2082
2109
  }
2083
2110
  } catch (error) {
2084
2111
  this.shouldGenerateReport = false;
2085
- console.error("OrtoniReport: Error generating report:", error);
2112
+ console.error("Ortoni Report: Error generating report:", error);
2086
2113
  }
2087
2114
  }
2088
2115
  async onExit() {
@@ -2090,7 +2117,7 @@ var OrtoniReport = class {
2090
2117
  await this.dbManager.close();
2091
2118
  if (this.shouldGenerateReport) {
2092
2119
  this.fileManager.copyTraceViewerAssets(this.skipTraceViewer);
2093
- console.info(`Ortoni HTML report generated at ${this.outputPath}`);
2120
+ console.info(`Ortoni Report generated at ${this.outputPath}`);
2094
2121
  this.serverManager.startServer(
2095
2122
  this.folderPath,
2096
2123
  this.outputFilename,
@@ -2100,7 +2127,7 @@ var OrtoniReport = class {
2100
2127
  });
2101
2128
  }
2102
2129
  } catch (error) {
2103
- console.error("OrtoniReport: Error in onExit:", error);
2130
+ console.error("Ortoni Report: Error in onExit:", error);
2104
2131
  }
2105
2132
  }
2106
2133
  };