@testomatio/reporter 1.2.0-beta-2 → 1.2.0-beta-4
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/lib/pipe/html.js
CHANGED
|
@@ -4,6 +4,7 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
const chalk = require('chalk');
|
|
6
6
|
const handlebars = require('handlebars');
|
|
7
|
+
const fileUrl = require('file-url');
|
|
7
8
|
|
|
8
9
|
const { fileSystem, isSameTest, ansiRegExp } = require('../utils/utils');
|
|
9
10
|
const { HTML_REPORT } = require('../constants');
|
|
@@ -14,17 +15,14 @@ class HtmlPipe {
|
|
|
14
15
|
this.title = params.title || process.env.TESTOMATIO_TITLE;
|
|
15
16
|
this.apiKey = params.apiKey || process.env.TESTOMATIO;
|
|
16
17
|
this.isHtml = process.env.TESTOMATIO_HTML_REPORT_SAVE;
|
|
17
|
-
this.data = {};
|
|
18
18
|
|
|
19
|
-
debug('HTML Pipe: ', this.apiKey ? 'API KEY' : '*no api key*');
|
|
20
|
-
if (!this.apiKey) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
19
|
+
debug('HTML Pipe: ', this.apiKey ? 'API KEY' : '*no api key provided*');
|
|
23
20
|
|
|
24
21
|
this.isEnabled = false;
|
|
25
22
|
this.htmlOutputPath = "";
|
|
23
|
+
this.fullHtmlOutputPath = "";
|
|
24
|
+
this.filenameMsg = "";
|
|
26
25
|
this.tests = [];
|
|
27
|
-
this.data = {};
|
|
28
26
|
|
|
29
27
|
if (this.isHtml) {
|
|
30
28
|
this.isEnabled = true;
|
|
@@ -35,10 +33,9 @@ class HtmlPipe {
|
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
if (process.env.TESTOMATIO_HTML_FILENAME && !process.env.TESTOMATIO_HTML_FILENAME.endsWith(".html")) {
|
|
38
|
-
console.log(
|
|
39
|
-
chalk.blue(`The name must include the extension ".html". The default report name is used!`)
|
|
40
|
-
);
|
|
41
36
|
this.htmlReportName = HTML_REPORT.REPORT_DEFAULT_NAME;
|
|
37
|
+
this.filenameMsg = "HTML filename must include the extension \".html\"." +
|
|
38
|
+
` The default report name "${this.htmlReportDir}/${HTML_REPORT.REPORT_DEFAULT_NAME}" is used!`;
|
|
42
39
|
}
|
|
43
40
|
|
|
44
41
|
if (!process.env.TESTOMATIO_HTML_FILENAME) {
|
|
@@ -90,79 +87,116 @@ class HtmlPipe {
|
|
|
90
87
|
if (!this.isEnabled) return;
|
|
91
88
|
|
|
92
89
|
if (this.isHtml) {
|
|
90
|
+
// GENERATE HTML reports based on the results data
|
|
91
|
+
this.buildReport({
|
|
92
|
+
runParams,
|
|
93
|
+
tests: this.tests,
|
|
94
|
+
outputPath: this.htmlOutputPath,
|
|
95
|
+
templatePath: this.templateHtmlPath,
|
|
96
|
+
warningMsg: this.filenameMsg
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Generates an HTML report based on provided test data and a template.
|
|
102
|
+
* @param {object} opts - Test options used to generate the HTML report:
|
|
103
|
+
* runParams, tests, outputPath, templatePath
|
|
104
|
+
* @returns {void} - This function does not return anything.
|
|
105
|
+
*/
|
|
93
106
|
|
|
94
|
-
|
|
107
|
+
buildReport(opts) {
|
|
108
|
+
const { runParams, tests, outputPath, templatePath, warningMsg: msg } = opts;
|
|
109
|
+
|
|
110
|
+
debug('HTML tests data:', tests);
|
|
95
111
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (!test.suite_title || test.suite_title.trim() === "") {
|
|
101
|
-
test.suite_title = "Unknown suite";
|
|
102
|
-
}
|
|
112
|
+
if (!outputPath) {
|
|
113
|
+
console.log(chalk.yellow(`🚨 HTML export path is not set, ignoring...`));
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
103
116
|
|
|
104
|
-
|
|
105
|
-
test.title = "Unknown test title";
|
|
106
|
-
}
|
|
117
|
+
console.log(chalk.yellow(`⏳ The test results will be added to the HTML report. It will take some time...`));
|
|
107
118
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
119
|
+
if (msg) {
|
|
120
|
+
console.log(chalk.blue(msg));
|
|
121
|
+
}
|
|
111
122
|
|
|
112
|
-
|
|
113
|
-
if (!test.steps || test.steps.trim() === "") {
|
|
114
|
-
test.steps = "This test has no 'steps' code";
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
test.steps = this.#removeAnsiColorCodes(test.steps);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// TODO: u can added an additional test values to this checks in the future
|
|
122
|
-
});
|
|
123
|
+
tests.forEach(test => {
|
|
123
124
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
parallel: runParams.isParallel,
|
|
128
|
-
runUrl: this.store.runUrl,
|
|
129
|
-
executionTime: testExecutionSumTime(this.tests),
|
|
130
|
-
executionDate: getCurrentDateTimeFormatted(),
|
|
131
|
-
tests: this.tests
|
|
132
|
-
};
|
|
125
|
+
if (!test.message || test.message.trim() === "") {
|
|
126
|
+
test.message = "This test has no 'message' code";
|
|
127
|
+
}
|
|
133
128
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
129
|
+
if (!test.suite_title || test.suite_title.trim() === "") {
|
|
130
|
+
test.suite_title = "Unknown suite";
|
|
131
|
+
}
|
|
138
132
|
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
if (!test.title || test.title.trim() === "") {
|
|
134
|
+
test.title = "Unknown test title";
|
|
135
|
+
}
|
|
141
136
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
137
|
+
if (!test.files || test.files.length === 0) {
|
|
138
|
+
test.files = "This test has no files";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (test.steps) {
|
|
142
|
+
if (!test.steps || test.steps.trim() === "") {
|
|
143
|
+
test.steps = "This test has no 'steps' code";
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
test.steps = removeAnsiColorCodes(test.steps);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// TODO: u can added an additional test values to this checks in the future
|
|
151
|
+
});
|
|
146
152
|
|
|
147
|
-
|
|
153
|
+
const data = {
|
|
154
|
+
runId: this.store.runId || "",
|
|
155
|
+
status: runParams.status || "No status info",
|
|
156
|
+
parallel: runParams.isParallel || "No parallel info",
|
|
157
|
+
runUrl: this.store.runUrl || "",
|
|
158
|
+
executionTime: testExecutionSumTime(tests),
|
|
159
|
+
executionDate: getCurrentDateTimeFormatted(),
|
|
160
|
+
tests
|
|
161
|
+
};
|
|
148
162
|
// generate output HTML based on the template
|
|
149
|
-
const html = this.#generateHTMLReport(data);
|
|
163
|
+
const html = this.#generateHTMLReport(data, templatePath);
|
|
164
|
+
|
|
165
|
+
if (!html) return;
|
|
150
166
|
|
|
151
|
-
fs.writeFileSync(
|
|
167
|
+
fs.writeFileSync(outputPath, html, 'utf-8');
|
|
168
|
+
// Check if the file exists
|
|
169
|
+
if (fs.existsSync(outputPath)) {
|
|
170
|
+
// Get the absolute path of the file
|
|
171
|
+
const absolutePath = path.resolve(outputPath);
|
|
172
|
+
// Convert the file path to a file URL
|
|
173
|
+
const fileUrlPath = fileUrl(absolutePath, {resolve: true});
|
|
174
|
+
|
|
175
|
+
debug('HTML tests data:', fileUrlPath);
|
|
176
|
+
|
|
177
|
+
console.log(chalk.green(`📊 The HTML report was successfully generated. Full filepath: ${fileUrlPath}`));
|
|
178
|
+
} else {
|
|
179
|
+
console.log(chalk.red(`🚨 Failed to generate the HTML report.`));
|
|
180
|
+
}
|
|
152
181
|
}
|
|
153
182
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
183
|
+
/**
|
|
184
|
+
* Generates an HTML report based on provided test data and a template path.
|
|
185
|
+
* @param {any} data - Test data used to generate the HTML report.
|
|
186
|
+
* @param {string} [templatePath=""] - The path to the HTML template used for generating the report.
|
|
187
|
+
* @returns {string | void} - The generated HTML report as a string or void if templatePath is not provided.
|
|
188
|
+
*/
|
|
189
|
+
#generateHTMLReport(data, templatePath = "") {
|
|
190
|
+
if (!templatePath) {
|
|
191
|
+
console.log(chalk.red(`🚨 HTML template not found. Report generation is impossible!`))
|
|
157
192
|
return;
|
|
158
193
|
}
|
|
159
194
|
|
|
160
|
-
const templateSource = fs.readFileSync(
|
|
195
|
+
const templateSource = fs.readFileSync(templatePath, 'utf8');
|
|
161
196
|
this.#loadReportHelpers();
|
|
162
197
|
try {
|
|
163
198
|
const template = handlebars.compile(templateSource);
|
|
164
199
|
|
|
165
|
-
console.log(chalk.green(`Generated HTML report saved in file: ${this.htmlOutputPath}`));
|
|
166
200
|
return template(data);
|
|
167
201
|
}
|
|
168
202
|
catch (e) {
|
|
@@ -213,18 +247,17 @@ class HtmlPipe {
|
|
|
213
247
|
});
|
|
214
248
|
}
|
|
215
249
|
|
|
216
|
-
#removeAnsiColorCodes(str) {
|
|
217
|
-
let updatedStr = str.replace(ansiRegExp(), "");
|
|
218
|
-
updatedStr = updatedStr.replace(/\n/g, '<br>');
|
|
219
|
-
|
|
220
|
-
return updatedStr;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
250
|
toString() {
|
|
224
251
|
return 'HTML Reporter';
|
|
225
252
|
}
|
|
226
253
|
}
|
|
227
254
|
|
|
255
|
+
/**
|
|
256
|
+
* Calculates the total execution time for an array of tests.
|
|
257
|
+
* @param {Object[]} tests - An array of test objects.
|
|
258
|
+
* @param {number} tests[].run_time - The execution time of each test in milliseconds.
|
|
259
|
+
* @returns {string} - The total execution time in a formatted duration string.
|
|
260
|
+
*/
|
|
228
261
|
function testExecutionSumTime(tests) {
|
|
229
262
|
const totalMilliseconds = tests.reduce((sum, test) => {
|
|
230
263
|
if (typeof test.run_time === 'number') {
|
|
@@ -236,6 +269,23 @@ function testExecutionSumTime(tests) {
|
|
|
236
269
|
return formatDuration(totalMilliseconds);
|
|
237
270
|
}
|
|
238
271
|
|
|
272
|
+
/**
|
|
273
|
+
* Removes ANSI color codes and converts newline characters to HTML line breaks in a given string.
|
|
274
|
+
* @param {string} str - The input string containing ANSI color codes.
|
|
275
|
+
* @returns {string} - The updated string with removed ANSI color codes and replaced newline characters.
|
|
276
|
+
*/
|
|
277
|
+
function removeAnsiColorCodes(str) {
|
|
278
|
+
let updatedStr = str.replace(ansiRegExp(), "");
|
|
279
|
+
updatedStr = updatedStr.replace(/\n/g, '<br>');
|
|
280
|
+
|
|
281
|
+
return updatedStr;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Formats duration in milliseconds into a human-readable string representation.
|
|
286
|
+
* @param {number} duration - The duration in milliseconds.
|
|
287
|
+
* @returns {string} - The formatted duration string (e.g., "2h 30m 15s 500ms").
|
|
288
|
+
*/
|
|
239
289
|
function formatDuration(duration) {
|
|
240
290
|
const milliseconds = duration % 1000;
|
|
241
291
|
duration = (duration - milliseconds) / 1000;
|
|
@@ -247,6 +297,10 @@ function formatDuration(duration) {
|
|
|
247
297
|
return `${hours}h ${minutes}m ${seconds}s ${milliseconds}ms`;
|
|
248
298
|
}
|
|
249
299
|
|
|
300
|
+
/**
|
|
301
|
+
* Retrieves the current date and time in a formatted string.
|
|
302
|
+
* @returns {string} - The formatted date and time string (e.g., "(01/01/2023 12:00:00)").
|
|
303
|
+
*/
|
|
250
304
|
function getCurrentDateTimeFormatted() {
|
|
251
305
|
const currentDate = new Date();
|
|
252
306
|
const day = currentDate.getDate().toString().padStart(2, '0');
|
|
@@ -7,7 +7,11 @@
|
|
|
7
7
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
8
8
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
|
9
9
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css" integrity="sha512-SzlrxWUlpfuzQ+pcUCosxcglQRNAq/DZjVsC0lE40xsADsfeQoEypE+enwcOiGjk/bSuGGKHEyjSoQ1zVisanQ==" crossorigin="anonymous" referrerpolicy="no-referrer">
|
|
10
|
-
|
|
10
|
+
{{#if runId}}
|
|
11
|
+
<title>Report #{{runId}} - Testomat.io</title>
|
|
12
|
+
{{else}}
|
|
13
|
+
<title>Report Testomat.io</title>
|
|
14
|
+
{{/if}}
|
|
11
15
|
<style>
|
|
12
16
|
body {
|
|
13
17
|
padding: 0;
|
|
@@ -32,7 +36,7 @@
|
|
|
32
36
|
}
|
|
33
37
|
p, span{
|
|
34
38
|
font-weight: 400;
|
|
35
|
-
font-size:
|
|
39
|
+
font-size: 14px;
|
|
36
40
|
color: grey;
|
|
37
41
|
margin: 0;
|
|
38
42
|
}
|
|
@@ -245,6 +249,33 @@
|
|
|
245
249
|
font-size: 14px;
|
|
246
250
|
white-space: pre-line;
|
|
247
251
|
}
|
|
252
|
+
.test__empty__list {
|
|
253
|
+
margin-bottom: 10px;
|
|
254
|
+
color: grey;
|
|
255
|
+
}
|
|
256
|
+
/* Passed TAB*/
|
|
257
|
+
#passedTest:not(:checked) + .btn-outline-dark {
|
|
258
|
+
background-color: #39BD2F;
|
|
259
|
+
}
|
|
260
|
+
#passedTest:checked + .btn-outline-dark {
|
|
261
|
+
background-color: #68cf61;
|
|
262
|
+
color: white;
|
|
263
|
+
}
|
|
264
|
+
/* Failed TAB*/
|
|
265
|
+
#failedTest:not(:checked) + .btn-outline-dark {
|
|
266
|
+
background-color: #F2230C;
|
|
267
|
+
}
|
|
268
|
+
#failedTest:checked + .btn-outline-dark {
|
|
269
|
+
background-color: #FA6E5E;
|
|
270
|
+
color: white;
|
|
271
|
+
}
|
|
272
|
+
/* Skipped TAB*/
|
|
273
|
+
#skippedTest:not(:checked) + .btn-outline-dark {
|
|
274
|
+
background-color: #F2C00C;
|
|
275
|
+
}
|
|
276
|
+
#skippedTest:checked + .btn-outline-dark {
|
|
277
|
+
background-color: #dfc155;
|
|
278
|
+
}
|
|
248
279
|
</style>
|
|
249
280
|
</head>
|
|
250
281
|
|
|
@@ -256,19 +287,27 @@
|
|
|
256
287
|
<div class="col-12">
|
|
257
288
|
<div class="header">
|
|
258
289
|
<div class="header__block">
|
|
259
|
-
|
|
260
|
-
<
|
|
261
|
-
|
|
262
|
-
|
|
290
|
+
{{#if runId}}
|
|
291
|
+
<div class="header__case">
|
|
292
|
+
<p>Run</p>
|
|
293
|
+
<span><strong>#</strong>{{runId}}</span>
|
|
294
|
+
</div>
|
|
295
|
+
{{/if}}
|
|
263
296
|
<p class="header__type">
|
|
264
297
|
<i class="fa-solid fa-face-smile"></i>
|
|
265
298
|
automated job
|
|
266
299
|
</p>
|
|
267
300
|
</div>
|
|
268
301
|
<div class="header__block">
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
302
|
+
{{#if runUrl}}
|
|
303
|
+
<a href="{{runUrl}}" target="_blank" class="btn btn-primary">
|
|
304
|
+
Full Report
|
|
305
|
+
</a>
|
|
306
|
+
{{else}}
|
|
307
|
+
<button class="btn btn-primary" disabled>
|
|
308
|
+
Full Report
|
|
309
|
+
</button>
|
|
310
|
+
{{/if}}
|
|
272
311
|
</div>
|
|
273
312
|
</div>
|
|
274
313
|
</div>
|
|
@@ -366,72 +405,78 @@
|
|
|
366
405
|
|
|
367
406
|
<div class="row level_5">
|
|
368
407
|
<div class="col-12">
|
|
408
|
+
{{#if tests.length}}
|
|
409
|
+
<div class="testWrapp">
|
|
410
|
+
{{#each tests}}
|
|
369
411
|
|
|
370
|
-
|
|
371
|
-
{{#each tests}}
|
|
372
|
-
|
|
373
|
-
<div class="testitem d-none" name="testitem" type="dummy" category="false">
|
|
412
|
+
<div class="testitem d-none" name="testitem" type="dummy" category="false">
|
|
374
413
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
414
|
+
<div class="testitem__top">
|
|
415
|
+
<div class="testitem__icon">
|
|
416
|
+
<i class="fa-solid fa-chevron-right testitem__ico testitem__ico_right"></i>
|
|
417
|
+
<i class="fa-solid fa-chevron-down d-none testitem__ico testitem__ico_down"></i>
|
|
418
|
+
</div>
|
|
419
|
+
<p class="testitem__name">Test</p>
|
|
379
420
|
</div>
|
|
380
|
-
<p class="testitem__name">Test</p>
|
|
381
|
-
</div>
|
|
382
421
|
|
|
383
|
-
|
|
422
|
+
<div class="testitem__body d-none">
|
|
384
423
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
424
|
+
<div class="testitem__menu">
|
|
425
|
+
<span type="steps" class="testitem__mitem testitem__mitem_active">Steps <i class="fa-solid fa-arrow-right"></i></span>
|
|
426
|
+
<span type="status" class="testitem__mitem">Status <i class="fa-solid fa-arrow-right"></i></span>
|
|
427
|
+
<span type="message" class="testitem__mitem">Message <i class="fa-solid fa-arrow-right"></i></span>
|
|
428
|
+
<span type="files" class="testitem__mitem">Files <i class="fa-solid fa-arrow-right"></i></span>
|
|
429
|
+
</div>
|
|
391
430
|
|
|
392
|
-
|
|
431
|
+
<div class="testitem__content">
|
|
393
432
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
433
|
+
<!-- 1 -->
|
|
434
|
+
<div class="testitem__case" type="steps">
|
|
435
|
+
<p class="testitem__title">Steps</p>
|
|
436
|
+
<div class="testitem__block">
|
|
437
|
+
<span>...</span>
|
|
438
|
+
</div>
|
|
399
439
|
</div>
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
440
|
+
<!-- 1 -->
|
|
441
|
+
|
|
442
|
+
<!-- 2 -->
|
|
443
|
+
<div class="testitem__case d-none" type="status">
|
|
444
|
+
<p class="testitem__title">Status</p>
|
|
445
|
+
<div class="testitem__block">
|
|
446
|
+
<span>...</span>
|
|
447
|
+
</div>
|
|
408
448
|
</div>
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
449
|
+
<!-- 2 -->
|
|
450
|
+
|
|
451
|
+
<!-- 3 -->
|
|
452
|
+
<div class="testitem__case d-none" type="message">
|
|
453
|
+
<p class="testitem__title">Message</p>
|
|
454
|
+
<div class="testitem__block">
|
|
455
|
+
<span>...</span>
|
|
456
|
+
</div>
|
|
417
457
|
</div>
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
458
|
+
<!-- 3 -->
|
|
459
|
+
|
|
460
|
+
<!-- 4 -->
|
|
461
|
+
<div class="testitem__case d-none" type="files">
|
|
462
|
+
<p class="testitem__title">Files</p>
|
|
463
|
+
<div class="testitem__block">
|
|
464
|
+
<span>...</span>
|
|
465
|
+
</div>
|
|
426
466
|
</div>
|
|
467
|
+
<!-- 4 -->
|
|
427
468
|
</div>
|
|
428
|
-
<!-- 4 -->
|
|
429
469
|
</div>
|
|
430
470
|
</div>
|
|
471
|
+
{{/each}}
|
|
472
|
+
</div>
|
|
473
|
+
{{else}}
|
|
474
|
+
<div class="row">
|
|
475
|
+
<div class="col-12 test__empty__list">
|
|
476
|
+
<p>No tests found to display 😔</p>
|
|
431
477
|
</div>
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
478
|
+
</div>
|
|
479
|
+
{{/if}}
|
|
435
480
|
</div>
|
|
436
481
|
</div>
|
|
437
482
|
|
|
@@ -446,23 +491,33 @@
|
|
|
446
491
|
|
|
447
492
|
// Draw the chart and set the chart values
|
|
448
493
|
function drawChart() {
|
|
494
|
+
let data = {};
|
|
449
495
|
const passedTests = {{getTestsByStatus tests "PASSED"}};
|
|
450
496
|
const failedTests = {{getTestsByStatus tests "FAILED"}};
|
|
451
497
|
const skippedTests = {{getTestsByStatus tests "SKIPPED"}};
|
|
452
498
|
|
|
453
|
-
|
|
499
|
+
if (passedTests === 0 && failedTests === 0 && skippedTests === 0) {
|
|
500
|
+
data = google.visualization.arrayToDataTable([
|
|
501
|
+
['Task', 'Tests'],
|
|
502
|
+
['No Tests', 1]
|
|
503
|
+
])
|
|
504
|
+
}
|
|
505
|
+
else {
|
|
506
|
+
data = google.visualization.arrayToDataTable([
|
|
454
507
|
['Task', 'Tests'],
|
|
508
|
+
['No Tests', 0],
|
|
455
509
|
['Passed', passedTests],
|
|
456
510
|
['Failed', failedTests],
|
|
457
511
|
['Skipped', skippedTests],
|
|
458
512
|
]);
|
|
513
|
+
}
|
|
459
514
|
|
|
460
515
|
// Optional: add a title and set the width and height of the chart
|
|
461
516
|
const options = {
|
|
462
517
|
'title':'',
|
|
463
518
|
'width':550,
|
|
464
519
|
'height':300,
|
|
465
|
-
'colors': ['#39BD2F', '#F2230C', '#F2C00C']
|
|
520
|
+
'colors': ['#939992', '#39BD2F', '#F2230C', '#F2C00C']
|
|
466
521
|
};
|
|
467
522
|
|
|
468
523
|
// Display the chart inside the <div> element with id="piechart"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@testomatio/reporter",
|
|
3
|
-
"version": "1.2.0-beta-
|
|
3
|
+
"version": "1.2.0-beta-4",
|
|
4
4
|
"description": "Testomatio Reporter Client",
|
|
5
5
|
"main": "./lib/reporter.js",
|
|
6
6
|
"typings": "typings/index.d.ts",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"debug": "^4.3.4",
|
|
21
21
|
"dotenv": "^16.0.1",
|
|
22
22
|
"fast-xml-parser": "^4.0.8",
|
|
23
|
+
"file-url": "3.0.0",
|
|
23
24
|
"glob": "^10.3",
|
|
24
25
|
"handlebars": "^4.7.8",
|
|
25
26
|
"has-flag": "^5.0.1",
|
|
@@ -65,6 +66,7 @@
|
|
|
65
66
|
"eslint-plugin-import": "^2.25.4",
|
|
66
67
|
"jasmine": "^3.10.0",
|
|
67
68
|
"jest": "^27.4.7",
|
|
69
|
+
"jsdom": "^22.1.0",
|
|
68
70
|
"mocha": "^9.2.0",
|
|
69
71
|
"mock-http-server": "^1.4.5",
|
|
70
72
|
"pino": "^8.15.0",
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
// TODO: use as example for the unit-tests
|
|
2
|
-
|
|
3
|
-
const result = {
|
|
4
|
-
"runId": "51eb2798",
|
|
5
|
-
"status": "failed",
|
|
6
|
-
"runUrl": "https://beta.testomat.io/projects/codecept-new-mode-exmple/runs/51eb2798/report",
|
|
7
|
-
"executionTime": "0 seconds",
|
|
8
|
-
"executionDate": "(30/07/2023 11:11:11)",
|
|
9
|
-
"tests": [{
|
|
10
|
-
"files": [],
|
|
11
|
-
"steps": "\u001b[32m\u001b[1mOn TodosPage: goto \u001b[22m\u001b[39m\n",
|
|
12
|
-
"status": "passed",
|
|
13
|
-
"stack": "I execute script () => sessionStorage.clear()",
|
|
14
|
-
"example": null,
|
|
15
|
-
"code": null,
|
|
16
|
-
"title": "Create a new todo item @T50e82737",
|
|
17
|
-
"suite_title": "Create Tasks @step:06 @smoke @story:12 @S2f5c1942",
|
|
18
|
-
"test_id": "50e82737",
|
|
19
|
-
"message": "",
|
|
20
|
-
"run_time": 121,
|
|
21
|
-
"artifacts": [],
|
|
22
|
-
"api_key": "tstmt_gRqrhBUaVxTpezGpZjRmlahOeqcRBBbDMA1692050199",
|
|
23
|
-
"create": false
|
|
24
|
-
}, {
|
|
25
|
-
"files": [{
|
|
26
|
-
"path": "/home/codeceptjs-testomat-example/codeceptJS/output/Create_2_@T5b8d1186.failed.png",
|
|
27
|
-
"type": "image/png"
|
|
28
|
-
}],
|
|
29
|
-
"steps": "I am on page \"http://todomvc.com/examples/angularjs/#/\"",
|
|
30
|
-
"status": "failed",
|
|
31
|
-
"stack": "I am on page \"http://todomvc.com/examples/angularjs/#/\"",
|
|
32
|
-
"example": null,
|
|
33
|
-
"code": null,
|
|
34
|
-
"title": "Create a new todo item part 2 @T5b8d1186",
|
|
35
|
-
"suite_title": "@second Create Tasks @step:07 @smoke @story:13 @S2f5c1942",
|
|
36
|
-
"test_id": "5b8d1186",
|
|
37
|
-
"message": "expected expected number of visible is 2, but found 1 \"1\" to equal \"2\"",
|
|
38
|
-
"run_time": 176,
|
|
39
|
-
"artifacts": [null],
|
|
40
|
-
"api_key": "tstmt_gRqrhBUaVxTpezGpZjRmlahOeqcRBBbDMA1692050199",
|
|
41
|
-
"create": false
|
|
42
|
-
}]
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
module.exports = {
|
|
46
|
-
result
|
|
47
|
-
}
|
|
File without changes
|