ortoni-report 4.0.2-beta.1 → 4.1.0-test.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.
- package/dist/{chunk-INS3E7E6.mjs → chunk-4RZ5C7KY.mjs} +402 -296
- package/dist/{cli/cli.js → cli.js} +392 -190
- package/dist/cli.mjs +195 -0
- package/dist/index.html +2 -2
- package/dist/ortoni-report.d.mts +8 -1
- package/dist/ortoni-report.d.ts +8 -1
- package/dist/ortoni-report.js +204 -89
- package/dist/ortoni-report.mjs +18 -15
- package/package.json +11 -4
- package/dist/chunk-45EJSEX2.mjs +0 -632
- package/dist/chunk-75EAJL2U.mjs +0 -632
- package/dist/chunk-A6HCKATU.mjs +0 -76
- package/dist/chunk-FGIYOFIC.mjs +0 -632
- package/dist/chunk-FHKWBHU6.mjs +0 -633
- package/dist/chunk-GLICR3VS.mjs +0 -637
- package/dist/chunk-HFO6XSKC.mjs +0 -633
- package/dist/chunk-HOZD6YIV.mjs +0 -634
- package/dist/chunk-IJO2YIFE.mjs +0 -637
- package/dist/chunk-JEIWNUQY.mjs +0 -632
- package/dist/chunk-JPLAGYR7.mjs +0 -632
- package/dist/chunk-NM6ULN2O.mjs +0 -632
- package/dist/chunk-OZS6QIJS.mjs +0 -638
- package/dist/chunk-P57227VN.mjs +0 -633
- package/dist/chunk-QMTRYN5N.js +0 -635
- package/dist/chunk-TI33PMMQ.mjs +0 -639
- package/dist/chunk-Z5NBP5TS.mjs +0 -635
- package/dist/cli/cli.cjs +0 -678
- package/dist/cli/cli.d.cts +0 -1
- package/dist/cli/cli.mjs +0 -103
- package/dist/ortoni-report.cjs +0 -2134
- package/dist/ortoni-report.d.cts +0 -111
- /package/dist/{cli/cli.d.mts → cli.d.mts} +0 -0
- /package/dist/{cli/cli.d.ts → cli.d.ts} +0 -0
package/dist/ortoni-report.d.mts
CHANGED
|
@@ -78,6 +78,13 @@ interface OrtoniReportConfig {
|
|
|
78
78
|
* @example { "key": "value" } as string
|
|
79
79
|
*/
|
|
80
80
|
meta?: Record<string, string>;
|
|
81
|
+
/**
|
|
82
|
+
* Save the history of the reports in a SQL file to be used in future reports.
|
|
83
|
+
* The history file will be saved in the report folder.
|
|
84
|
+
* @default true
|
|
85
|
+
* @example false (to disable)
|
|
86
|
+
*/
|
|
87
|
+
saveHistory?: boolean;
|
|
81
88
|
}
|
|
82
89
|
|
|
83
90
|
declare class OrtoniReport implements Reporter {
|
|
@@ -96,7 +103,7 @@ declare class OrtoniReport implements Reporter {
|
|
|
96
103
|
private shouldGenerateReport;
|
|
97
104
|
private showConsoleLogs;
|
|
98
105
|
private skipTraceViewer;
|
|
99
|
-
private
|
|
106
|
+
private shardConfig;
|
|
100
107
|
constructor(ortoniConfig?: OrtoniReportConfig);
|
|
101
108
|
private reportsCount;
|
|
102
109
|
onBegin(config: FullConfig, _suite: Suite): Promise<void>;
|
package/dist/ortoni-report.d.ts
CHANGED
|
@@ -78,6 +78,13 @@ interface OrtoniReportConfig {
|
|
|
78
78
|
* @example { "key": "value" } as string
|
|
79
79
|
*/
|
|
80
80
|
meta?: Record<string, string>;
|
|
81
|
+
/**
|
|
82
|
+
* Save the history of the reports in a SQL file to be used in future reports.
|
|
83
|
+
* The history file will be saved in the report folder.
|
|
84
|
+
* @default true
|
|
85
|
+
* @example false (to disable)
|
|
86
|
+
*/
|
|
87
|
+
saveHistory?: boolean;
|
|
81
88
|
}
|
|
82
89
|
|
|
83
90
|
declare class OrtoniReport implements Reporter {
|
|
@@ -96,7 +103,7 @@ declare class OrtoniReport implements Reporter {
|
|
|
96
103
|
private shouldGenerateReport;
|
|
97
104
|
private showConsoleLogs;
|
|
98
105
|
private skipTraceViewer;
|
|
99
|
-
private
|
|
106
|
+
private shardConfig;
|
|
100
107
|
constructor(ortoniConfig?: OrtoniReportConfig);
|
|
101
108
|
private reportsCount;
|
|
102
109
|
onBegin(config: FullConfig, _suite: Suite): Promise<void>;
|
package/dist/ortoni-report.js
CHANGED
|
@@ -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 =
|
|
49
|
-
if (!
|
|
50
|
-
|
|
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 (
|
|
53
|
-
|
|
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
|
-
|
|
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
|
-
|
|
66
|
-
|
|
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 =
|
|
70
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
85
|
-
const traceViewerAssetsTargetFolder =
|
|
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
|
-
|
|
90
|
-
for (const file of
|
|
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
|
-
|
|
94
|
-
|
|
95
|
-
|
|
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 =
|
|
99
|
-
for (const file of
|
|
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
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
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
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
|
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
|
|
373
|
+
// src/helpers/resultProcessor.ts
|
|
262
374
|
var import_ansi_to_html = __toESM(require("ansi-to-html"));
|
|
263
|
-
var
|
|
375
|
+
var import_path5 = __toESM(require("path"));
|
|
264
376
|
|
|
265
377
|
// src/utils/attachFiles.ts
|
|
266
|
-
var
|
|
267
|
-
var
|
|
378
|
+
var import_path3 = __toESM(require("path"));
|
|
379
|
+
var import_fs4 = __toESM(require("fs"));
|
|
268
380
|
|
|
269
381
|
// src/helpers/markdownConverter.ts
|
|
270
|
-
var
|
|
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 =
|
|
1397
|
-
const markdownContent = hasMarkdown ?
|
|
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
|
-
|
|
1512
|
+
import_fs3.default.writeFileSync(htmlOutputPath, drawerHtml.trim(), "utf-8");
|
|
1401
1513
|
if (hasMarkdown) {
|
|
1402
|
-
|
|
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 =
|
|
1521
|
+
const attachmentsFolder = import_path3.default.join(
|
|
1410
1522
|
folderPath,
|
|
1411
1523
|
"ortoni-data",
|
|
1412
1524
|
"attachments",
|
|
1413
1525
|
subFolder
|
|
1414
1526
|
);
|
|
1415
|
-
if (!
|
|
1416
|
-
|
|
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 ?
|
|
1426
|
-
const relativePath =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
1636
|
+
var import_path4 = __toESM(require("path"));
|
|
1525
1637
|
function normalizeFilePath(filePath) {
|
|
1526
|
-
const normalizedPath =
|
|
1527
|
-
return
|
|
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 =
|
|
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
|
|
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)" });
|
|
@@ -1631,7 +1743,7 @@ var TestResultProcessor = class {
|
|
|
1631
1743
|
}
|
|
1632
1744
|
processSteps(steps) {
|
|
1633
1745
|
return steps.map((step) => {
|
|
1634
|
-
const stepLocation = step.location ? `${
|
|
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
|
|
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(
|
|
1765
|
+
res.sendFile(import_path6.default.resolve(reportFolder, reportFilename));
|
|
1654
1766
|
} catch (error) {
|
|
1655
|
-
console.error("Ortoni
|
|
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
|
|
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
|
|
1788
|
+
`Ortoni Report: Port ${port} is already in use. Trying a different port...`
|
|
1677
1789
|
);
|
|
1678
1790
|
} else {
|
|
1679
|
-
console.error("Ortoni
|
|
1791
|
+
console.error("Ortoni Report: Server error:", error);
|
|
1680
1792
|
}
|
|
1681
1793
|
});
|
|
1682
1794
|
} catch (error) {
|
|
1683
|
-
console.error("Ortoni
|
|
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
|
|
1813
|
+
console.error("Ortoni Report: Error opening the browser:", error);
|
|
1702
1814
|
}
|
|
1703
1815
|
}
|
|
1704
1816
|
|
|
@@ -1996,7 +2108,7 @@ var DatabaseManager = class {
|
|
|
1996
2108
|
};
|
|
1997
2109
|
|
|
1998
2110
|
// src/ortoni-report.ts
|
|
1999
|
-
var
|
|
2111
|
+
var import_path7 = __toESM(require("path"));
|
|
2000
2112
|
var OrtoniReport = class {
|
|
2001
2113
|
constructor(ortoniConfig = {}) {
|
|
2002
2114
|
this.ortoniConfig = ortoniConfig;
|
|
@@ -2027,9 +2139,9 @@ var OrtoniReport = class {
|
|
|
2027
2139
|
this.testResultProcessor = new TestResultProcessor(config.rootDir);
|
|
2028
2140
|
this.fileManager.ensureReportDirectory();
|
|
2029
2141
|
await this.dbManager.initialize(
|
|
2030
|
-
|
|
2142
|
+
import_path7.default.join(this.folderPath, "ortoni-data-history.sqlite")
|
|
2031
2143
|
);
|
|
2032
|
-
this.
|
|
2144
|
+
this.shardConfig = config?.shard;
|
|
2033
2145
|
}
|
|
2034
2146
|
onStdOut(chunk, _test, _result) {
|
|
2035
2147
|
if (this.reportsCount == 1 && this.showConsoleLogs) {
|
|
@@ -2046,7 +2158,7 @@ var OrtoniReport = class {
|
|
|
2046
2158
|
);
|
|
2047
2159
|
this.results.push(testResult);
|
|
2048
2160
|
} catch (error) {
|
|
2049
|
-
console.error("
|
|
2161
|
+
console.error("Ortoni Report: Error processing test end:", error);
|
|
2050
2162
|
}
|
|
2051
2163
|
}
|
|
2052
2164
|
printsToStdio() {
|
|
@@ -2065,8 +2177,8 @@ var OrtoniReport = class {
|
|
|
2065
2177
|
(r) => r.status !== "skipped"
|
|
2066
2178
|
);
|
|
2067
2179
|
const totalDuration = result.duration;
|
|
2068
|
-
if (this.
|
|
2069
|
-
const shard = this.
|
|
2180
|
+
if (this.shardConfig && this.shardConfig.total > 1) {
|
|
2181
|
+
const shard = this.shardConfig;
|
|
2070
2182
|
const shardFile = `ortoni-shard-${shard.current}-of-${shard.total}.json`;
|
|
2071
2183
|
const shardData = {
|
|
2072
2184
|
status: result.status,
|
|
@@ -2083,8 +2195,11 @@ var OrtoniReport = class {
|
|
|
2083
2195
|
meta: this.ortoniConfig.meta
|
|
2084
2196
|
}
|
|
2085
2197
|
};
|
|
2086
|
-
this.fileManager.writeRawFile(
|
|
2087
|
-
|
|
2198
|
+
const shardFilePath = this.fileManager.writeRawFile(
|
|
2199
|
+
shardFile,
|
|
2200
|
+
shardData
|
|
2201
|
+
);
|
|
2202
|
+
console.info(`Ortoni Report: Shard data written to ${shardFilePath}`);
|
|
2088
2203
|
this.shouldGenerateReport = false;
|
|
2089
2204
|
return;
|
|
2090
2205
|
}
|
|
@@ -2097,21 +2212,21 @@ var OrtoniReport = class {
|
|
|
2097
2212
|
this.results,
|
|
2098
2213
|
this.projectSet
|
|
2099
2214
|
);
|
|
2100
|
-
this.outputPath = this.fileManager.writeReportFile(
|
|
2215
|
+
this.outputPath = await this.fileManager.writeReportFile(
|
|
2101
2216
|
this.outputFilename,
|
|
2102
2217
|
finalReportData
|
|
2103
2218
|
);
|
|
2104
2219
|
} else {
|
|
2105
|
-
console.error("
|
|
2220
|
+
console.error("Ortoni Report: Error saving test run to database");
|
|
2106
2221
|
}
|
|
2107
2222
|
} else {
|
|
2108
2223
|
console.error(
|
|
2109
|
-
"
|
|
2224
|
+
"Ortoni Report: Report generation skipped due to error in Playwright worker!"
|
|
2110
2225
|
);
|
|
2111
2226
|
}
|
|
2112
2227
|
} catch (error) {
|
|
2113
2228
|
this.shouldGenerateReport = false;
|
|
2114
|
-
console.error("
|
|
2229
|
+
console.error("Ortoni Report: Error generating report:", error);
|
|
2115
2230
|
}
|
|
2116
2231
|
}
|
|
2117
2232
|
async onExit() {
|
|
@@ -2119,7 +2234,7 @@ var OrtoniReport = class {
|
|
|
2119
2234
|
await this.dbManager.close();
|
|
2120
2235
|
if (this.shouldGenerateReport) {
|
|
2121
2236
|
this.fileManager.copyTraceViewerAssets(this.skipTraceViewer);
|
|
2122
|
-
console.info(`Ortoni
|
|
2237
|
+
console.info(`Ortoni Report generated at ${this.outputPath}`);
|
|
2123
2238
|
this.serverManager.startServer(
|
|
2124
2239
|
this.folderPath,
|
|
2125
2240
|
this.outputFilename,
|
|
@@ -2129,7 +2244,7 @@ var OrtoniReport = class {
|
|
|
2129
2244
|
});
|
|
2130
2245
|
}
|
|
2131
2246
|
} catch (error) {
|
|
2132
|
-
console.error("
|
|
2247
|
+
console.error("Ortoni Report: Error in onExit:", error);
|
|
2133
2248
|
}
|
|
2134
2249
|
}
|
|
2135
2250
|
};
|