ortoni-report 4.0.2-beta.1 → 4.0.3

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.
Files changed (62) hide show
  1. package/changelog.md +27 -0
  2. package/dist/{chunk-INS3E7E6.mjs → chunk-4RZ5C7KY.mjs} +402 -296
  3. package/dist/{cli/cli.js → cli.js} +405 -190
  4. package/dist/cli.mjs +208 -0
  5. package/dist/helpers/HTMLGenerator.d.ts +89 -0
  6. package/dist/helpers/HTMLGenerator.js +163 -0
  7. package/dist/helpers/databaseManager.d.ts +35 -0
  8. package/dist/helpers/databaseManager.js +268 -0
  9. package/dist/helpers/fileManager.d.ts +8 -0
  10. package/dist/helpers/fileManager.js +60 -0
  11. package/dist/helpers/markdownConverter.d.ts +1 -0
  12. package/dist/helpers/markdownConverter.js +14 -0
  13. package/dist/helpers/resultProcessor.d.ts +10 -0
  14. package/dist/helpers/resultProcessor.js +60 -0
  15. package/dist/helpers/serverManager.d.ts +6 -0
  16. package/dist/helpers/serverManager.js +15 -0
  17. package/dist/helpers/templateLoader.d.ts +15 -0
  18. package/dist/helpers/templateLoader.js +88 -0
  19. package/dist/index.html +1 -1
  20. package/dist/mergeData.d.ts +13 -0
  21. package/dist/mergeData.js +182 -0
  22. package/dist/ortoni-report.d.mts +8 -1
  23. package/dist/ortoni-report.d.ts +8 -1
  24. package/dist/ortoni-report.js +211 -96
  25. package/dist/ortoni-report.mjs +25 -22
  26. package/dist/{ortoni-report.d.cts → types/reporterConfig.d.ts} +8 -33
  27. package/dist/types/reporterConfig.js +1 -0
  28. package/dist/types/testResults.d.ts +31 -0
  29. package/dist/types/testResults.js +1 -0
  30. package/dist/utils/attachFiles.d.ts +4 -0
  31. package/dist/utils/attachFiles.js +87 -0
  32. package/dist/utils/expressServer.d.ts +1 -0
  33. package/dist/utils/expressServer.js +61 -0
  34. package/dist/utils/groupProjects.d.ts +3 -0
  35. package/dist/utils/groupProjects.js +30 -0
  36. package/dist/utils/utils.d.ts +15 -0
  37. package/dist/utils/utils.js +84 -0
  38. package/package.json +11 -4
  39. package/readme.md +60 -75
  40. package/dist/chunk-45EJSEX2.mjs +0 -632
  41. package/dist/chunk-75EAJL2U.mjs +0 -632
  42. package/dist/chunk-A6HCKATU.mjs +0 -76
  43. package/dist/chunk-FGIYOFIC.mjs +0 -632
  44. package/dist/chunk-FHKWBHU6.mjs +0 -633
  45. package/dist/chunk-GLICR3VS.mjs +0 -637
  46. package/dist/chunk-HFO6XSKC.mjs +0 -633
  47. package/dist/chunk-HOZD6YIV.mjs +0 -634
  48. package/dist/chunk-IJO2YIFE.mjs +0 -637
  49. package/dist/chunk-JEIWNUQY.mjs +0 -632
  50. package/dist/chunk-JPLAGYR7.mjs +0 -632
  51. package/dist/chunk-NM6ULN2O.mjs +0 -632
  52. package/dist/chunk-OZS6QIJS.mjs +0 -638
  53. package/dist/chunk-P57227VN.mjs +0 -633
  54. package/dist/chunk-QMTRYN5N.js +0 -635
  55. package/dist/chunk-TI33PMMQ.mjs +0 -639
  56. package/dist/chunk-Z5NBP5TS.mjs +0 -635
  57. package/dist/cli/cli.cjs +0 -678
  58. package/dist/cli/cli.d.cts +0 -1
  59. package/dist/cli/cli.mjs +0 -103
  60. package/dist/ortoni-report.cjs +0 -2134
  61. /package/dist/{cli/cli.d.mts → cli.d.mts} +0 -0
  62. /package/dist/{cli/cli.d.ts → cli.d.ts} +0 -0
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  var __create = Object.create;
3
2
  var __defProp = Object.defineProperty;
4
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -38,69 +37,131 @@ __export(ortoni_report_exports, {
38
37
  module.exports = __toCommonJS(ortoni_report_exports);
39
38
 
40
39
  // src/helpers/fileManager.ts
40
+ var import_fs2 = __toESM(require("fs"));
41
+ var import_path2 = __toESM(require("path"));
42
+
43
+ // src/helpers/templateLoader.ts
41
44
  var import_fs = __toESM(require("fs"));
42
45
  var import_path = __toESM(require("path"));
46
+ var import_meta = {};
47
+ async function readBundledTemplate(pkgName = "ortoni-report") {
48
+ const packagedRel = "dist/index.html";
49
+ try {
50
+ if (typeof require === "function") {
51
+ const resolved = require.resolve(`${pkgName}/${packagedRel}`);
52
+ if (import_fs.default.existsSync(resolved)) {
53
+ return import_fs.default.readFileSync(resolved, "utf-8");
54
+ }
55
+ }
56
+ } catch {
57
+ }
58
+ try {
59
+ const moduleNS = await import("module");
60
+ if (moduleNS && typeof moduleNS.createRequire === "function") {
61
+ const createRequire = moduleNS.createRequire;
62
+ const req = createRequire(
63
+ // @ts-ignore
64
+ typeof __filename !== "undefined" ? __filename : import_meta.url
65
+ );
66
+ const resolved = req.resolve(`${pkgName}/${packagedRel}`);
67
+ if (import_fs.default.existsSync(resolved)) {
68
+ return import_fs.default.readFileSync(resolved, "utf-8");
69
+ }
70
+ }
71
+ } catch {
72
+ }
73
+ try {
74
+ const here = import_path.default.resolve(__dirname, "../dist/index.html");
75
+ if (import_fs.default.existsSync(here)) return import_fs.default.readFileSync(here, "utf-8");
76
+ } catch {
77
+ }
78
+ try {
79
+ const nm = import_path.default.join(process.cwd(), "node_modules", pkgName, packagedRel);
80
+ if (import_fs.default.existsSync(nm)) return import_fs.default.readFileSync(nm, "utf-8");
81
+ } catch {
82
+ }
83
+ try {
84
+ const alt = import_path.default.join(process.cwd(), "dist", "index.html");
85
+ if (import_fs.default.existsSync(alt)) return import_fs.default.readFileSync(alt, "utf-8");
86
+ } catch {
87
+ }
88
+ throw new Error(
89
+ `ortoni-report template not found (tried:
90
+ - require.resolve('${pkgName}/${packagedRel}')
91
+ - import('module').createRequire(...).resolve('${pkgName}/${packagedRel}')
92
+ - relative ../dist/index.html
93
+ - ${import_path.default.join(
94
+ process.cwd(),
95
+ "node_modules",
96
+ pkgName,
97
+ packagedRel
98
+ )}
99
+ - ${import_path.default.join(process.cwd(), "dist", "index.html")}
100
+ Ensure 'dist/index.html' is present in the published package and package.json 'files' includes 'dist/'.`
101
+ );
102
+ }
103
+
104
+ // src/helpers/fileManager.ts
43
105
  var FileManager = class {
44
106
  constructor(folderPath) {
45
107
  this.folderPath = folderPath;
46
108
  }
47
109
  ensureReportDirectory() {
48
- const ortoniDataFolder = import_path.default.join(this.folderPath, "ortoni-data");
49
- if (!import_fs.default.existsSync(this.folderPath)) {
50
- import_fs.default.mkdirSync(this.folderPath, { recursive: true });
110
+ const ortoniDataFolder = import_path2.default.join(this.folderPath, "ortoni-data");
111
+ if (!import_fs2.default.existsSync(this.folderPath)) {
112
+ import_fs2.default.mkdirSync(this.folderPath, { recursive: true });
51
113
  } else {
52
- if (import_fs.default.existsSync(ortoniDataFolder)) {
53
- import_fs.default.rmSync(ortoniDataFolder, { recursive: true, force: true });
114
+ if (import_fs2.default.existsSync(ortoniDataFolder)) {
115
+ import_fs2.default.rmSync(ortoniDataFolder, { recursive: true, force: true });
54
116
  }
55
117
  }
56
118
  }
57
- writeReportFile(filename, data) {
58
- const templatePath = import_path.default.join(__dirname, "..", "index.html");
59
- console.log("temp path - " + templatePath);
60
- let html = import_fs.default.readFileSync(templatePath, "utf-8");
119
+ async writeReportFile(filename, data) {
120
+ let html = await readBundledTemplate();
61
121
  const reportJSON = JSON.stringify({
62
122
  data
63
123
  });
64
124
  html = html.replace("__ORTONI_TEST_REPORTDATA__", reportJSON);
65
- import_fs.default.writeFileSync(filename, html);
66
- return filename;
125
+ const outputPath = import_path2.default.join(process.cwd(), this.folderPath, filename);
126
+ import_fs2.default.writeFileSync(outputPath, html);
127
+ return outputPath;
67
128
  }
68
129
  writeRawFile(filename, data) {
69
- const outputPath = import_path.default.join(process.cwd(), this.folderPath, filename);
70
- import_fs.default.mkdirSync(import_path.default.dirname(outputPath), { recursive: true });
130
+ const outputPath = import_path2.default.join(process.cwd(), this.folderPath, filename);
131
+ import_fs2.default.mkdirSync(import_path2.default.dirname(outputPath), { recursive: true });
71
132
  const content = typeof data === "string" ? data : JSON.stringify(data, null, 2);
72
- import_fs.default.writeFileSync(outputPath, content, "utf-8");
133
+ import_fs2.default.writeFileSync(outputPath, content, "utf-8");
73
134
  return outputPath;
74
135
  }
75
136
  copyTraceViewerAssets(skip) {
76
137
  if (skip) return;
77
- const traceViewerFolder = import_path.default.join(
138
+ const traceViewerFolder = import_path2.default.join(
78
139
  require.resolve("playwright-core"),
79
140
  "..",
80
141
  "lib",
81
142
  "vite",
82
143
  "traceViewer"
83
144
  );
84
- const traceViewerTargetFolder = import_path.default.join(this.folderPath, "trace");
85
- const traceViewerAssetsTargetFolder = import_path.default.join(
145
+ const traceViewerTargetFolder = import_path2.default.join(this.folderPath, "trace");
146
+ const traceViewerAssetsTargetFolder = import_path2.default.join(
86
147
  traceViewerTargetFolder,
87
148
  "assets"
88
149
  );
89
- import_fs.default.mkdirSync(traceViewerAssetsTargetFolder, { recursive: true });
90
- for (const file of import_fs.default.readdirSync(traceViewerFolder)) {
150
+ import_fs2.default.mkdirSync(traceViewerAssetsTargetFolder, { recursive: true });
151
+ for (const file of import_fs2.default.readdirSync(traceViewerFolder)) {
91
152
  if (file.endsWith(".map") || file.includes("watch") || file.includes("assets"))
92
153
  continue;
93
- import_fs.default.copyFileSync(
94
- import_path.default.join(traceViewerFolder, file),
95
- import_path.default.join(traceViewerTargetFolder, file)
154
+ import_fs2.default.copyFileSync(
155
+ import_path2.default.join(traceViewerFolder, file),
156
+ import_path2.default.join(traceViewerTargetFolder, file)
96
157
  );
97
158
  }
98
- const assetsFolder = import_path.default.join(traceViewerFolder, "assets");
99
- for (const file of import_fs.default.readdirSync(assetsFolder)) {
159
+ const assetsFolder = import_path2.default.join(traceViewerFolder, "assets");
160
+ for (const file of import_fs2.default.readdirSync(assetsFolder)) {
100
161
  if (file.endsWith(".map") || file.includes("xtermModule")) continue;
101
- import_fs.default.copyFileSync(
102
- import_path.default.join(assetsFolder, file),
103
- import_path.default.join(traceViewerAssetsTargetFolder, file)
162
+ import_fs2.default.copyFileSync(
163
+ import_path2.default.join(assetsFolder, file),
164
+ import_path2.default.join(traceViewerAssetsTargetFolder, file)
104
165
  );
105
166
  }
106
167
  }
@@ -149,13 +210,46 @@ var HTMLGenerator = class {
149
210
  );
150
211
  return data;
151
212
  }
213
+ /**
214
+ * Return safe analytics/report data.
215
+ * If no dbManager is provided, return empty defaults and a note explaining why.
216
+ */
152
217
  async getReportData() {
153
- return {
154
- summary: await this.dbManager.getSummaryData(),
155
- trends: await this.dbManager.getTrends(),
156
- flakyTests: await this.dbManager.getFlakyTests(),
157
- slowTests: await this.dbManager.getSlowTests()
158
- };
218
+ if (!this.dbManager) {
219
+ return {
220
+ summary: {},
221
+ trends: {},
222
+ flakyTests: [],
223
+ slowTests: [],
224
+ note: "Test history/trends are unavailable (saveHistory disabled or DB not initialized)."
225
+ };
226
+ }
227
+ try {
228
+ const [summary, trends, flakyTests, slowTests] = await Promise.all([
229
+ this.dbManager.getSummaryData ? this.dbManager.getSummaryData() : Promise.resolve({}),
230
+ this.dbManager.getTrends ? this.dbManager.getTrends() : Promise.resolve({}),
231
+ this.dbManager.getFlakyTests ? this.dbManager.getFlakyTests() : Promise.resolve([]),
232
+ this.dbManager.getSlowTests ? this.dbManager.getSlowTests() : Promise.resolve([])
233
+ ]);
234
+ return {
235
+ summary: summary ?? {},
236
+ trends: trends ?? {},
237
+ flakyTests: flakyTests ?? [],
238
+ slowTests: slowTests ?? []
239
+ };
240
+ } catch (err) {
241
+ console.warn(
242
+ "HTMLGenerator: failed to read analytics from DB, continuing without history.",
243
+ err
244
+ );
245
+ return {
246
+ summary: {},
247
+ trends: {},
248
+ flakyTests: [],
249
+ slowTests: [],
250
+ note: "Test history/trends could not be loaded due to a DB error."
251
+ };
252
+ }
159
253
  }
160
254
  async prepareReportData(filteredResults, totalDuration, results, projectSet) {
161
255
  const totalTests = filteredResults.length;
@@ -164,10 +258,10 @@ var HTMLGenerator = class {
164
258
  const failed = filteredResults.filter(
165
259
  (r) => r.status === "failed" || r.status === "timedOut"
166
260
  ).length;
167
- const successRate = ((passedTests + flakyTests) / totalTests * 100).toFixed(2);
261
+ const successRate = totalTests === 0 ? "0.00" : ((passedTests + flakyTests) / totalTests * 100).toFixed(2);
168
262
  const allTags = /* @__PURE__ */ new Set();
169
263
  results.forEach(
170
- (result) => result.testTags.forEach((tag) => allTags.add(tag))
264
+ (result) => (result.testTags || []).forEach((tag) => allTags.add(tag))
171
265
  );
172
266
  const projectResults = this.calculateProjectResults(
173
267
  filteredResults,
@@ -178,13 +272,31 @@ var HTMLGenerator = class {
178
272
  const testHistories = await Promise.all(
179
273
  results.map(async (result) => {
180
274
  const testId = `${result.filePath}:${result.projectName}:${result.title}`;
181
- const history = await this.dbManager.getTestHistory(testId);
182
- return {
183
- testId,
184
- history
185
- };
275
+ if (!this.dbManager || !this.dbManager.getTestHistory) {
276
+ return {
277
+ testId,
278
+ history: []
279
+ };
280
+ }
281
+ try {
282
+ const history = await this.dbManager.getTestHistory(testId);
283
+ return {
284
+ testId,
285
+ history: history ?? []
286
+ };
287
+ } catch (err) {
288
+ console.warn(
289
+ `HTMLGenerator: failed to read history for ${testId}`,
290
+ err
291
+ );
292
+ return {
293
+ testId,
294
+ history: []
295
+ };
296
+ }
186
297
  })
187
298
  );
299
+ const reportData = await this.getReportData();
188
300
  return {
189
301
  summary: {
190
302
  overAllResult: {
@@ -220,7 +332,7 @@ var HTMLGenerator = class {
220
332
  showProject: this.ortoniConfig.showProject || false
221
333
  },
222
334
  analytics: {
223
- reportData: await this.getReportData()
335
+ reportData
224
336
  }
225
337
  };
226
338
  }
@@ -258,16 +370,16 @@ var HTMLGenerator = class {
258
370
  }
259
371
  };
260
372
 
261
- // src/helpers/resultProcessor .ts
373
+ // src/helpers/resultProcessor.ts
262
374
  var import_ansi_to_html = __toESM(require("ansi-to-html"));
263
- var import_path4 = __toESM(require("path"));
375
+ var import_path5 = __toESM(require("path"));
264
376
 
265
377
  // src/utils/attachFiles.ts
266
- var import_path2 = __toESM(require("path"));
267
- var import_fs3 = __toESM(require("fs"));
378
+ var import_path3 = __toESM(require("path"));
379
+ var import_fs4 = __toESM(require("fs"));
268
380
 
269
381
  // src/helpers/markdownConverter.ts
270
- var import_fs2 = __toESM(require("fs"));
382
+ var import_fs3 = __toESM(require("fs"));
271
383
 
272
384
  // node_modules/marked/lib/marked.esm.js
273
385
  function M() {
@@ -1393,27 +1505,27 @@ var Qt = b.lex;
1393
1505
 
1394
1506
  // src/helpers/markdownConverter.ts
1395
1507
  function convertMarkdownToHtml(markdownPath, htmlOutputPath) {
1396
- const hasMarkdown = import_fs2.default.existsSync(markdownPath);
1397
- const markdownContent = hasMarkdown ? import_fs2.default.readFileSync(markdownPath, "utf-8") : "";
1508
+ const hasMarkdown = import_fs3.default.existsSync(markdownPath);
1509
+ const markdownContent = hasMarkdown ? import_fs3.default.readFileSync(markdownPath, "utf-8") : "";
1398
1510
  const markdownHtml = hasMarkdown ? k(markdownContent) : "";
1399
1511
  const drawerHtml = `${markdownHtml || ""}`;
1400
- import_fs2.default.writeFileSync(htmlOutputPath, drawerHtml.trim(), "utf-8");
1512
+ import_fs3.default.writeFileSync(htmlOutputPath, drawerHtml.trim(), "utf-8");
1401
1513
  if (hasMarkdown) {
1402
- import_fs2.default.unlinkSync(markdownPath);
1514
+ import_fs3.default.unlinkSync(markdownPath);
1403
1515
  }
1404
1516
  }
1405
1517
 
1406
1518
  // src/utils/attachFiles.ts
1407
1519
  function attachFiles(subFolder, result, testResult, config, steps, errors) {
1408
1520
  const folderPath = config.folderPath || "ortoni-report";
1409
- const attachmentsFolder = import_path2.default.join(
1521
+ const attachmentsFolder = import_path3.default.join(
1410
1522
  folderPath,
1411
1523
  "ortoni-data",
1412
1524
  "attachments",
1413
1525
  subFolder
1414
1526
  );
1415
- if (!import_fs3.default.existsSync(attachmentsFolder)) {
1416
- import_fs3.default.mkdirSync(attachmentsFolder, { recursive: true });
1527
+ if (!import_fs4.default.existsSync(attachmentsFolder)) {
1528
+ import_fs4.default.mkdirSync(attachmentsFolder, { recursive: true });
1417
1529
  }
1418
1530
  if (!result.attachments) return;
1419
1531
  const { base64Image } = config;
@@ -1422,14 +1534,14 @@ function attachFiles(subFolder, result, testResult, config, steps, errors) {
1422
1534
  result.attachments.forEach((attachment) => {
1423
1535
  const { contentType, name, path: attachmentPath, body } = attachment;
1424
1536
  if (!attachmentPath && !body) return;
1425
- const fileName = attachmentPath ? import_path2.default.basename(attachmentPath) : `${name}.${getFileExtension(contentType)}`;
1426
- const relativePath = import_path2.default.join(
1537
+ const fileName = attachmentPath ? import_path3.default.basename(attachmentPath) : `${name}.${getFileExtension(contentType)}`;
1538
+ const relativePath = import_path3.default.join(
1427
1539
  "ortoni-data",
1428
1540
  "attachments",
1429
1541
  subFolder,
1430
1542
  fileName
1431
1543
  );
1432
- const fullPath = import_path2.default.join(attachmentsFolder, fileName);
1544
+ const fullPath = import_path3.default.join(attachmentsFolder, fileName);
1433
1545
  if (contentType === "image/png") {
1434
1546
  handleImage(
1435
1547
  attachmentPath,
@@ -1472,13 +1584,13 @@ function handleImage(attachmentPath, body, base64Image, fullPath, relativePath,
1472
1584
  let screenshotPath = "";
1473
1585
  if (attachmentPath) {
1474
1586
  try {
1475
- const screenshotContent = import_fs3.default.readFileSync(
1587
+ const screenshotContent = import_fs4.default.readFileSync(
1476
1588
  attachmentPath,
1477
1589
  base64Image ? "base64" : void 0
1478
1590
  );
1479
1591
  screenshotPath = base64Image ? `data:image/png;base64,${screenshotContent}` : relativePath;
1480
1592
  if (!base64Image) {
1481
- import_fs3.default.copyFileSync(attachmentPath, fullPath);
1593
+ import_fs4.default.copyFileSync(attachmentPath, fullPath);
1482
1594
  }
1483
1595
  } catch (error) {
1484
1596
  console.error(
@@ -1495,7 +1607,7 @@ function handleImage(attachmentPath, body, base64Image, fullPath, relativePath,
1495
1607
  }
1496
1608
  function handleAttachment(attachmentPath, fullPath, relativePath, resultKey, testResult, steps, errors) {
1497
1609
  if (attachmentPath) {
1498
- import_fs3.default.copyFileSync(attachmentPath, fullPath);
1610
+ import_fs4.default.copyFileSync(attachmentPath, fullPath);
1499
1611
  if (resultKey === "videoPath") {
1500
1612
  testResult[resultKey]?.push(relativePath);
1501
1613
  } else if (resultKey === "tracePath") {
@@ -1521,13 +1633,13 @@ function getFileExtension(contentType) {
1521
1633
  }
1522
1634
 
1523
1635
  // src/utils/utils.ts
1524
- var import_path3 = __toESM(require("path"));
1636
+ var import_path4 = __toESM(require("path"));
1525
1637
  function normalizeFilePath(filePath) {
1526
- const normalizedPath = import_path3.default.normalize(filePath);
1527
- return import_path3.default.basename(normalizedPath);
1638
+ const normalizedPath = import_path4.default.normalize(filePath);
1639
+ return import_path4.default.basename(normalizedPath);
1528
1640
  }
1529
1641
  function ensureHtmlExtension(filename) {
1530
- const ext = import_path3.default.extname(filename);
1642
+ const ext = import_path4.default.extname(filename);
1531
1643
  if (ext && ext.toLowerCase() === ".html") {
1532
1644
  return filename;
1533
1645
  }
@@ -1575,7 +1687,7 @@ function extractSuites(titlePath) {
1575
1687
  };
1576
1688
  }
1577
1689
 
1578
- // src/helpers/resultProcessor .ts
1690
+ // src/helpers/resultProcessor.ts
1579
1691
  var TestResultProcessor = class {
1580
1692
  constructor(projectRoot) {
1581
1693
  this.ansiToHtml = new import_ansi_to_html.default({ fg: "var(--snippet-color)" });
@@ -1620,7 +1732,7 @@ var TestResultProcessor = class {
1620
1732
  testId: `${filePath}:${projectName}:${title}`
1621
1733
  };
1622
1734
  attachFiles(
1623
- test.id,
1735
+ import_path5.default.join(test.id, `retry-${result.retry}`),
1624
1736
  result,
1625
1737
  testResult,
1626
1738
  ortoniConfig,
@@ -1631,7 +1743,7 @@ var TestResultProcessor = class {
1631
1743
  }
1632
1744
  processSteps(steps) {
1633
1745
  return steps.map((step) => {
1634
- const stepLocation = step.location ? `${import_path4.default.relative(this.projectRoot, step.location.file)}:${step.location.line}:${step.location.column}` : "";
1746
+ const stepLocation = step.location ? `${import_path5.default.relative(this.projectRoot, step.location.file)}:${step.location.line}:${step.location.column}` : "";
1635
1747
  return {
1636
1748
  snippet: this.ansiToHtml.toHtml(escapeHtml(step.error?.snippet || "")),
1637
1749
  title: step.title,
@@ -1643,16 +1755,16 @@ var TestResultProcessor = class {
1643
1755
 
1644
1756
  // src/utils/expressServer.ts
1645
1757
  var import_express = __toESM(require("express"));
1646
- var import_path5 = __toESM(require("path"));
1758
+ var import_path6 = __toESM(require("path"));
1647
1759
  var import_child_process = require("child_process");
1648
1760
  function startReportServer(reportFolder, reportFilename, port = 2004, open2) {
1649
1761
  const app = (0, import_express.default)();
1650
- app.use(import_express.default.static(reportFolder));
1762
+ app.use(import_express.default.static(reportFolder, { index: false }));
1651
1763
  app.get("/", (_req, res) => {
1652
1764
  try {
1653
- res.sendFile(import_path5.default.resolve(reportFolder, reportFilename));
1765
+ res.sendFile(import_path6.default.resolve(reportFolder, reportFilename));
1654
1766
  } catch (error) {
1655
- console.error("Ortoni-Report: Error sending report file:", error);
1767
+ console.error("Ortoni Report: Error sending report file:", error);
1656
1768
  res.status(500).send("Error loading report");
1657
1769
  }
1658
1770
  });
@@ -1666,21 +1778,21 @@ Press Ctrl+C to stop.`
1666
1778
  try {
1667
1779
  openBrowser(`http://localhost:${port}`);
1668
1780
  } catch (error) {
1669
- console.error("Ortoni-Report: Error opening browser:", error);
1781
+ console.error("Ortoni Report: Error opening browser:", error);
1670
1782
  }
1671
1783
  }
1672
1784
  });
1673
1785
  server.on("error", (error) => {
1674
1786
  if (error.code === "EADDRINUSE") {
1675
1787
  console.error(
1676
- `Ortoni-Report: Port ${port} is already in use. Trying a different port...`
1788
+ `Ortoni Report: Port ${port} is already in use. Trying a different port...`
1677
1789
  );
1678
1790
  } else {
1679
- console.error("Ortoni-Report: Server error:", error);
1791
+ console.error("Ortoni Report: Server error:", error);
1680
1792
  }
1681
1793
  });
1682
1794
  } catch (error) {
1683
- console.error("Ortoni-Report: Error starting the server:", error);
1795
+ console.error("Ortoni Report: Error starting the server:", error);
1684
1796
  }
1685
1797
  }
1686
1798
  function openBrowser(url) {
@@ -1698,7 +1810,7 @@ function openBrowser(url) {
1698
1810
  (0, import_child_process.spawn)(command, [url]);
1699
1811
  }
1700
1812
  } catch (error) {
1701
- console.error("Ortoni-Report: Error opening the browser:", error);
1813
+ console.error("Ortoni Report: Error opening the browser:", error);
1702
1814
  }
1703
1815
  }
1704
1816
 
@@ -1707,7 +1819,7 @@ var ServerManager = class {
1707
1819
  constructor(ortoniConfig) {
1708
1820
  this.ortoniConfig = ortoniConfig;
1709
1821
  }
1710
- startServer(folderPath, outputFilename, overAllStatus) {
1822
+ async startServer(folderPath, outputFilename, overAllStatus) {
1711
1823
  const openOption = this.ortoniConfig.open || "never";
1712
1824
  const hasFailures = overAllStatus === "failed";
1713
1825
  if (openOption === "always" || openOption === "on-failure" && hasFailures) {
@@ -1717,6 +1829,8 @@ var ServerManager = class {
1717
1829
  this.ortoniConfig.port,
1718
1830
  openOption
1719
1831
  );
1832
+ await new Promise((_resolve) => {
1833
+ });
1720
1834
  }
1721
1835
  }
1722
1836
  };
@@ -1996,7 +2110,7 @@ var DatabaseManager = class {
1996
2110
  };
1997
2111
 
1998
2112
  // src/ortoni-report.ts
1999
- var import_path6 = __toESM(require("path"));
2113
+ var import_path7 = __toESM(require("path"));
2000
2114
  var OrtoniReport = class {
2001
2115
  constructor(ortoniConfig = {}) {
2002
2116
  this.ortoniConfig = ortoniConfig;
@@ -2027,9 +2141,9 @@ var OrtoniReport = class {
2027
2141
  this.testResultProcessor = new TestResultProcessor(config.rootDir);
2028
2142
  this.fileManager.ensureReportDirectory();
2029
2143
  await this.dbManager.initialize(
2030
- import_path6.default.join(this.folderPath, "ortoni-data-history.sqlite")
2144
+ import_path7.default.join(this.folderPath, "ortoni-data-history.sqlite")
2031
2145
  );
2032
- this.config = config?.shard;
2146
+ this.shardConfig = config?.shard;
2033
2147
  }
2034
2148
  onStdOut(chunk, _test, _result) {
2035
2149
  if (this.reportsCount == 1 && this.showConsoleLogs) {
@@ -2046,7 +2160,7 @@ var OrtoniReport = class {
2046
2160
  );
2047
2161
  this.results.push(testResult);
2048
2162
  } catch (error) {
2049
- console.error("OrtoniReport: Error processing test end:", error);
2163
+ console.error("Ortoni Report: Error processing test end:", error);
2050
2164
  }
2051
2165
  }
2052
2166
  printsToStdio() {
@@ -2065,12 +2179,12 @@ var OrtoniReport = class {
2065
2179
  (r) => r.status !== "skipped"
2066
2180
  );
2067
2181
  const totalDuration = result.duration;
2068
- if (this.config && this.config.total > 1) {
2069
- const shard = this.config;
2182
+ if (this.shardConfig && this.shardConfig.total > 1) {
2183
+ const shard = this.shardConfig;
2070
2184
  const shardFile = `ortoni-shard-${shard.current}-of-${shard.total}.json`;
2071
2185
  const shardData = {
2072
- status: result.status,
2073
- duration: totalDuration,
2186
+ // status: result.status,
2187
+ totalDuration,
2074
2188
  results: this.results,
2075
2189
  projectSet: Array.from(this.projectSet),
2076
2190
  userConfig: {
@@ -2083,8 +2197,11 @@ var OrtoniReport = class {
2083
2197
  meta: this.ortoniConfig.meta
2084
2198
  }
2085
2199
  };
2086
- this.fileManager.writeRawFile(shardFile, shardData);
2087
- console.log(`\u{1F4E6} OrtoniReport wrote shard file: ${shardFile}`);
2200
+ const shardFilePath = this.fileManager.writeRawFile(
2201
+ shardFile,
2202
+ shardData
2203
+ );
2204
+ console.info(`Ortoni Report: Shard data written to ${shardFilePath}`);
2088
2205
  this.shouldGenerateReport = false;
2089
2206
  return;
2090
2207
  }
@@ -2097,21 +2214,21 @@ var OrtoniReport = class {
2097
2214
  this.results,
2098
2215
  this.projectSet
2099
2216
  );
2100
- this.outputPath = this.fileManager.writeReportFile(
2217
+ this.outputPath = await this.fileManager.writeReportFile(
2101
2218
  this.outputFilename,
2102
2219
  finalReportData
2103
2220
  );
2104
2221
  } else {
2105
- console.error("OrtoniReport: Error saving test run to database");
2222
+ console.error("Ortoni Report: Error saving test run to database");
2106
2223
  }
2107
2224
  } else {
2108
2225
  console.error(
2109
- "OrtoniReport: Report generation skipped due to error in Playwright worker!"
2226
+ "Ortoni Report: Report generation skipped due to error in Playwright worker!"
2110
2227
  );
2111
2228
  }
2112
2229
  } catch (error) {
2113
2230
  this.shouldGenerateReport = false;
2114
- console.error("OrtoniReport: Error generating report:", error);
2231
+ console.error("Ortoni Report: Error generating report:", error);
2115
2232
  }
2116
2233
  }
2117
2234
  async onExit() {
@@ -2119,17 +2236,15 @@ var OrtoniReport = class {
2119
2236
  await this.dbManager.close();
2120
2237
  if (this.shouldGenerateReport) {
2121
2238
  this.fileManager.copyTraceViewerAssets(this.skipTraceViewer);
2122
- console.info(`Ortoni HTML report generated at ${this.outputPath}`);
2123
- this.serverManager.startServer(
2239
+ console.info(`Ortoni Report generated at ${this.outputPath}`);
2240
+ await this.serverManager.startServer(
2124
2241
  this.folderPath,
2125
2242
  this.outputFilename,
2126
2243
  this.overAllStatus
2127
2244
  );
2128
- await new Promise((_resolve) => {
2129
- });
2130
2245
  }
2131
2246
  } catch (error) {
2132
- console.error("OrtoniReport: Error in onExit:", error);
2247
+ console.error("Ortoni Report: Error in onExit:", error);
2133
2248
  }
2134
2249
  }
2135
2250
  };